Prepare v2022.04-rc4
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEEGjx/cOCPqxcHgJu/FHw5/5Y0tywFAmIvp/8ACgkQFHw5/5Y0 tyyI6wwApR++p9BBlWEZn1B5sivCXcs9oCX3Vs8vegpiiRbs/pGsyKV6pfEHHYV5 lhw1YNZ0accKmqBmX19tdpQ2ZzHq3+g0eGJL8xioXU3hRoZZNsDewAF8KS+aHPpk qMuA+xbDi08I6z2qtrIpaDd//DO2jAkFF+/TKOzSgUSxBaomQiziZaB2x28bIBH2 zsLMP4vzZ03uCSZVSd7HMBz0qiGhioJo5Ch2eU4TTJW19CXeMTAuav6SDq+6vJGi cIUe31YEe742jOVmtf2RuJQ+mDjsEfT11wvRajcbOlH/Ho7E5iFxQkmOEThpvybE YD5d5uLLpQj42PfBpSvx4nMJcvyOmqxdizUJxCgi/q5HrhdzcO6LwLLON0T4W4zG Vsue+iTjOKXgLdD8g/VogL38iHxhpfY7zsFB98vvHcoLwhEXvfvhO8Dj/lwLw4Ic 88B6uz3TqAPNqSnTWphJPCwG8STwyqlvLXwTF+eICbtQW3uuHEtnmlsXQJeFmdUa fGK8dUfr =wyE5 -----END PGP SIGNATURE----- Merge tag 'v2022.04-rc4' into next Prepare v2022.04-rc4
This commit is contained in:
commit
2abf048ab7
23
.mailmap
23
.mailmap
@ -22,11 +22,13 @@ Andreas Bießmann <andreas@biessmann.org>
|
||||
Aneesh V <aneesh@ti.com>
|
||||
Anup Patel <anup@brainfault.org> <anup.patel@wdc.com>
|
||||
Atish Patra <atishp@atishpatra.org> <atish.patra@wdc.com>
|
||||
Bin Meng <bmeng.cn@gmail.com> <bin.meng@windriver.com>
|
||||
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
|
||||
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@free-electrons.com>
|
||||
Dirk Behme <dirk.behme@googlemail.com>
|
||||
Fabio Estevam <fabio.estevam@nxp.com>
|
||||
Heinrich Schuchardt <xypron.glpk@gmx.de> <heinrich.schuchardt@canonical.com>
|
||||
Heinrich Schuchardt <xypron.glpk@gmx.de> xypron.glpk@gmx.de <xypron.glpk@gmx.de>
|
||||
Jagan Teki <402jagan@gmail.com>
|
||||
Jagan Teki <jaganna@gmail.com>
|
||||
Jagan Teki <jaganna@xilinx.com>
|
||||
@ -35,7 +37,15 @@ Jagan Teki <jagannadha.sutradharudu-teki@xilinx.com>
|
||||
Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
|
||||
Igor Opaniuk <igor.opaniuk@gmail.com> <igor.opaniuk@linaro.org>
|
||||
Igor Opaniuk <igor.opaniuk@gmail.com> <igor.opaniuk@toradex.com>
|
||||
Marek Vasut <marex@denx.de> <marek.vasut+renesas@gmail.com>
|
||||
Marek Vasut <marex@denx.de> <marek.vasut@gmail.com>
|
||||
Marek Vasut <marex@denx.de> <marex at denx.de>
|
||||
Markus Klotzbuecher <mk@denx.de>
|
||||
Masahiro Yamada <yamada.masahiro@socionext.com> <yamada.m@jp.panasonic.com>
|
||||
Masahiro Yamada <yamada.masahiro@socionext.com> <masahiroy@kernel.org>
|
||||
Michal Simek <michal.simek@xilinx.com> <monstr@monstr.eu>
|
||||
Michal Simek <michal.simek@xilinx.com> <Monstr@seznam.cz>
|
||||
Michal Simek <michal.simek@xilinx.com> <root@monstr.eu>
|
||||
Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de>
|
||||
Patrice Chotard <patrice.chotard@foss.st.com> <patrice.chotard@st.com>
|
||||
Patrick Delaunay <patrick.delaunay@foss.st.com> <patrick.delaunay@st.com>
|
||||
@ -47,10 +57,19 @@ Ricardo Ribalda <ricardo@ribalda.com> <ricardo.ribalda@gmail.com>
|
||||
Ruchika Gupta <ruchika.gupta@nxp.com> <ruchika.gupta@freescale.com>
|
||||
Sandeep Paulraj <s-paulraj@ti.com>
|
||||
Shaohui Xie <Shaohui.Xie@freescale.com>
|
||||
Stefan Roese <stroese>
|
||||
Stefan Roese <sr@denx.de> <stroese>
|
||||
Stefano Babic <sbabic@denx.de>
|
||||
Tom Rini <trini@konsulko.com> <trini@ti.com>
|
||||
TsiChung Liew <Tsi-Chung.Liew@freescale.com>
|
||||
Wolfgang Denk <wdenk>
|
||||
Wolfgang Denk <wd@denx.de> <wdenk>
|
||||
Wolfgang Denk <wd@denx.de> <wd@pollux.denx.de>
|
||||
Wolfgang Denk <wd@denx.de> <wd@pollux.(none)>
|
||||
Wolfgang Denk <wd@denx.de> <wd@fifi.denx.de>
|
||||
Wolfgang Denk <wd@denx.de> <wd@nyx.denx.de>
|
||||
Wolfgang Denk <wd@denx.de> <wd@atlas.denx.de>
|
||||
Wolfgang Denk <wd@denx.de> <wd@castor.denx.de>
|
||||
Wolfgang Denk <wd@denx.de> <wd@xpert.denx.de>
|
||||
Wolfgang Denk <wd@denx.de> <wd@nyx.(none)>
|
||||
York Sun <yorksun@freescale.com>
|
||||
York Sun <york.sun@nxp.com>
|
||||
Łukasz Majewski <l.majewski@samsung.com>
|
||||
|
15
MAINTAINERS
15
MAINTAINERS
@ -1171,6 +1171,13 @@ S: Maintained
|
||||
T: git https://source.denx.de/u-boot/custodians/u-boot-sh.git
|
||||
F: arch/sh/
|
||||
|
||||
SL28CLPD
|
||||
M: Michael Walle <michael@walle.cc>
|
||||
S: Maintained
|
||||
F: drivers/gpio/sl28cpld-gpio.c
|
||||
F: drivers/misc/sl28cpld.c
|
||||
F: drivers/watchdog/sl28cpld-wdt.c
|
||||
|
||||
SPI
|
||||
M: Jagan Teki <jagan@amarulasolutions.com>
|
||||
S: Maintained
|
||||
@ -1329,6 +1336,14 @@ F: include/virtio*.h
|
||||
F: test/dm/virtio.c
|
||||
F: doc/develop/driver-model/virtio.rst
|
||||
|
||||
WATCHDOG
|
||||
M: Stefan Roese <sr@denx.de>
|
||||
S: Maintained
|
||||
T: git https://source.denx.de/u-boot/custodians/u-boot-watchdog.git
|
||||
F: cmd/wdt.c
|
||||
F: drivers/watchdog/
|
||||
F: include/watchdog*.h
|
||||
|
||||
X86
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
M: Bin Meng <bmeng.cn@gmail.com>
|
||||
|
4
Makefile
4
Makefile
@ -3,7 +3,7 @@
|
||||
VERSION = 2022
|
||||
PATCHLEVEL = 04
|
||||
SUBLEVEL =
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME =
|
||||
|
||||
# *DOCUMENTATION*
|
||||
@ -1412,7 +1412,7 @@ MKIMAGEFLAGS_u-boot-spl.kwb = -n $(KWD_CONFIG_FILE) \
|
||||
$(if $(KEYDIR),-k $(KEYDIR))
|
||||
|
||||
MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
|
||||
-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
|
||||
-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -A $(ARCH) -T pblimage
|
||||
|
||||
ifeq ($(CONFIG_MPC85xx)$(CONFIG_OF_SEPARATE),yy)
|
||||
UBOOT_BIN := u-boot-with-dtb.bin
|
||||
|
@ -1075,6 +1075,8 @@ config ARCH_SUNXI
|
||||
select DM_ETH
|
||||
select DM_GPIO
|
||||
select DM_I2C if I2C
|
||||
select DM_SPI if SPI
|
||||
select DM_SPI_FLASH if SPI
|
||||
select DM_KEYBOARD
|
||||
select DM_MMC if MMC
|
||||
select DM_SCSI if SCSI
|
||||
|
@ -25,9 +25,9 @@ ENTRY(return_to_fel)
|
||||
mov sp, r0
|
||||
mov lr, r1
|
||||
ldr r0, =fel_stash
|
||||
ldr r1, [r0, #16]
|
||||
mcr p15, 0, r1, c1, c0, 0 @ Write CP15 Control Register
|
||||
ldr r1, [r0, #12]
|
||||
mcr p15, 0, r1, c1, c0, 0 @ Write CP15 SCTLR register
|
||||
ldr r1, [r0, #8]
|
||||
msr cpsr, r1 @ Write CPSR
|
||||
bx lr
|
||||
ENDPROC(return_to_fel)
|
||||
|
@ -139,7 +139,9 @@
|
||||
/*
|
||||
* U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property
|
||||
* contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and
|
||||
* 2 size cells and also expects that the second range starts at 16 MB offset. If these
|
||||
* 2 size cells and also expects that the second range starts at 16 MB offset. Also it
|
||||
* expects that first range uses same address for PCI (child) and CPU (parent) cells (so
|
||||
* no remapping) and that this address is the lowest from all specified ranges. If these
|
||||
* conditions are not met then U-Boot crashes during loading kernel DTB file. PCIe address
|
||||
* space is 128 MB long, so the best split between MEM and IO is to use fixed 16 MB window
|
||||
* for IO and the rest 112 MB (64+32+16) for MEM. Controller supports 32-bit IO mapping.
|
||||
@ -148,6 +150,9 @@
|
||||
* https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7
|
||||
* https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf
|
||||
* https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33
|
||||
* Bug related to requirement of same child and parent addresses for first range is fixed
|
||||
* in U-Boot version 2022.04 by following commit:
|
||||
* https://source.denx.de/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17
|
||||
*/
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
@ -499,7 +499,7 @@
|
||||
* (totaling 127 MiB) for MEM.
|
||||
*/
|
||||
ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x07f00000 /* Port 0 MEM */
|
||||
0x81000000 0 0xeff00000 0 0xeff00000 0 0x00100000>; /* Port 0 IO*/
|
||||
0x81000000 0 0x00000000 0 0xeff00000 0 0x00100000>; /* Port 0 IO */
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie_intc 0>,
|
||||
<0 0 0 2 &pcie_intc 1>,
|
||||
|
@ -27,6 +27,7 @@
|
||||
fit {
|
||||
offset = <CONFIG_SPL_PAD_TO>;
|
||||
description = "FIT image with multiple configurations";
|
||||
fit,fdt-list = "of-list";
|
||||
|
||||
images {
|
||||
uboot {
|
||||
@ -41,95 +42,20 @@
|
||||
};
|
||||
};
|
||||
|
||||
fdt-1 {
|
||||
description = "fsl-ls1028a-kontron-sl28";
|
||||
@fdt-SEQ {
|
||||
description = "NAME";
|
||||
type = "flat_dt";
|
||||
arch = "arm";
|
||||
compression = "none";
|
||||
|
||||
blob {
|
||||
filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28.dtb";
|
||||
};
|
||||
};
|
||||
|
||||
fdt-2 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var1";
|
||||
type = "flat_dt";
|
||||
arch = "arm";
|
||||
compression = "none";
|
||||
|
||||
blob {
|
||||
filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var1.dtb";
|
||||
};
|
||||
};
|
||||
|
||||
fdt-3 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var2";
|
||||
type = "flat_dt";
|
||||
arch = "arm";
|
||||
compression = "none";
|
||||
|
||||
blob {
|
||||
filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var2.dtb";
|
||||
};
|
||||
};
|
||||
|
||||
fdt-4 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var3";
|
||||
type = "flat_dt";
|
||||
arch = "arm";
|
||||
compression = "none";
|
||||
|
||||
blob {
|
||||
filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var3.dtb";
|
||||
};
|
||||
};
|
||||
|
||||
fdt-5 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var4";
|
||||
type = "flat_dt";
|
||||
arch = "arm";
|
||||
compression = "none";
|
||||
|
||||
blob {
|
||||
filename = "arch/arm/dts/fsl-ls1028a-kontron-sl28-var4.dtb";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
default = "conf-1";
|
||||
default = "@config-DEFAULT-SEQ";
|
||||
|
||||
conf-1 {
|
||||
description = "fsl-ls1028a-kontron-sl28";
|
||||
@config-SEQ {
|
||||
description = "NAME";
|
||||
firmware = "uboot";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
|
||||
conf-2 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var1";
|
||||
firmware = "uboot";
|
||||
fdt = "fdt-2";
|
||||
};
|
||||
|
||||
conf-3 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var2";
|
||||
firmware = "uboot";
|
||||
fdt = "fdt-3";
|
||||
};
|
||||
|
||||
conf-4 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var3";
|
||||
firmware = "uboot";
|
||||
loadables = "uboot";
|
||||
fdt = "fdt-4";
|
||||
};
|
||||
|
||||
conf-5 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var4";
|
||||
firmware = "uboot";
|
||||
loadables = "uboot";
|
||||
fdt = "fdt-5";
|
||||
fdt = "fdt-SEQ";
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -189,27 +115,7 @@
|
||||
};
|
||||
|
||||
configurations {
|
||||
conf-1 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
|
||||
conf-2 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
|
||||
conf-3 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
|
||||
conf-4 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
|
||||
conf-5 {
|
||||
@config-SEQ {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
@ -238,23 +144,7 @@
|
||||
};
|
||||
|
||||
configurations {
|
||||
conf-1 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
|
||||
conf-2 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
|
||||
conf-3 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
|
||||
conf-4 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
|
||||
conf-5 {
|
||||
@config-SEQ {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) Siemens AG, 2018-2021
|
||||
* Copyright (c) Siemens AG, 2018-2022
|
||||
*
|
||||
* Authors:
|
||||
* Le Jin <le.jin@siemens.com>
|
||||
@ -27,6 +27,29 @@
|
||||
|
||||
&cbass_mcu {
|
||||
u-boot,dm-spl;
|
||||
|
||||
mcu_navss: bus@28380000 {
|
||||
ringacc@2b800000 {
|
||||
reg = <0x0 0x2b800000 0x0 0x400000>,
|
||||
<0x0 0x2b000000 0x0 0x400000>,
|
||||
<0x0 0x28590000 0x0 0x100>,
|
||||
<0x0 0x2a500000 0x0 0x40000>,
|
||||
<0x0 0x28440000 0x0 0x40000>;
|
||||
reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target", "cfg";
|
||||
ti,dma-ring-reset-quirk;
|
||||
};
|
||||
|
||||
dma-controller@285c0000 {
|
||||
reg = <0x0 0x285c0000 0x0 0x100>,
|
||||
<0x0 0x284c0000 0x0 0x4000>,
|
||||
<0x0 0x2a800000 0x0 0x40000>,
|
||||
<0x0 0x284a0000 0x0 0x4000>,
|
||||
<0x0 0x2aa00000 0x0 0x40000>,
|
||||
<0x0 0x28400000 0x0 0x2000>;
|
||||
reg-names = "gcfg", "rchan", "rchanrt", "tchan",
|
||||
"tchanrt", "rflow";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&cbass_wakeup {
|
||||
|
@ -125,7 +125,9 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gmac0_default &pinctrl_gmac0_txc_default>;
|
||||
pinctrl-0 = <&pinctrl_gmac0_default
|
||||
&pinctrl_gmac0_mdio_default
|
||||
&pinctrl_gmac0_txc_default>;
|
||||
phy-mode = "rgmii-id";
|
||||
status = "okay";
|
||||
|
||||
@ -138,7 +140,7 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_gmac1_default>;
|
||||
pinctrl-0 = <&pinctrl_gmac1_default &pinctrl_gmac1_mdio_default>;
|
||||
phy-mode = "rmii";
|
||||
status = "okay";
|
||||
|
||||
@ -235,14 +237,20 @@
|
||||
<PIN_PA15__G0_TXEN>,
|
||||
<PIN_PA30__G0_RXCK>,
|
||||
<PIN_PA18__G0_RXDV>,
|
||||
<PIN_PA22__G0_MDC>,
|
||||
<PIN_PA23__G0_MDIO>,
|
||||
<PIN_PA25__G0_125CK>;
|
||||
slew-rate = <0>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pinctrl_gmac0_mdio_default: gmac0_mdio_default {
|
||||
pinmux = <PIN_PA22__G0_MDC>,
|
||||
<PIN_PA23__G0_MDIO>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pinctrl_gmac0_txc_default: gmac0_txc_default {
|
||||
pinmux = <PIN_PA24__G0_TXCK>;
|
||||
slew-rate = <0>;
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
@ -254,8 +262,13 @@
|
||||
<PIN_PD25__G1_RX0>,
|
||||
<PIN_PD26__G1_RX1>,
|
||||
<PIN_PD27__G1_RXER>,
|
||||
<PIN_PD24__G1_RXDV>,
|
||||
<PIN_PD28__G1_MDC>,
|
||||
<PIN_PD24__G1_RXDV>;
|
||||
slew-rate = <0>;
|
||||
bias-disable;
|
||||
};
|
||||
|
||||
pinctrl_gmac1_mdio_default: gmac1_mdio_default {
|
||||
pinmux = <PIN_PD28__G1_MDC>,
|
||||
<PIN_PD29__G1_MDIO>;
|
||||
bias-disable;
|
||||
};
|
||||
|
@ -160,6 +160,7 @@ enum sunxi_gpio_number {
|
||||
#define SUNXI_GPC_SDC2 3
|
||||
#define SUN6I_GPC_SDC3 4
|
||||
#define SUN50I_GPC_SPI0 4
|
||||
#define SUNIV_GPC_SPI0 2
|
||||
|
||||
#define SUNXI_GPD_LCD0 2
|
||||
#define SUNXI_GPD_LVDS0 3
|
||||
|
@ -19,6 +19,15 @@
|
||||
#define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10
|
||||
#define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12
|
||||
|
||||
/*
|
||||
* Values taken from the F1C200s BootROM stack
|
||||
* to determine where we booted from.
|
||||
*/
|
||||
#define SUNIV_BOOTED_FROM_MMC0 0xffff40f8
|
||||
#define SUNIV_BOOTED_FROM_NAND 0xffff4114
|
||||
#define SUNIV_BOOTED_FROM_SPI 0xffff4130
|
||||
#define SUNIV_BOOTED_FROM_MMC1 0xffff4150
|
||||
|
||||
#define is_boot0_magic(addr) (memcmp((void *)(addr), BOOT0_MAGIC, 8) == 0)
|
||||
|
||||
uint32_t sunxi_get_boot_device(void);
|
||||
|
@ -251,6 +251,7 @@ void board_init_f(ulong dummy)
|
||||
k3_sysfw_print_ver();
|
||||
|
||||
/* Perform EEPROM-based board detection */
|
||||
if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT))
|
||||
do_board_detect();
|
||||
|
||||
#if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
|
||||
|
@ -316,8 +316,8 @@ static int fdt_setprop_inplace_u32_partial(void *blob, int node,
|
||||
|
||||
int a3700_fdt_fix_pcie_regions(void *blob)
|
||||
{
|
||||
int acells, pacells, scells;
|
||||
u32 base, fix_offset;
|
||||
u32 base, lowest_cpu_addr, fix_offset;
|
||||
int pci_cells, cpu_cells, size_cells;
|
||||
const u32 *ranges;
|
||||
int node, pnode;
|
||||
int ret, i, len;
|
||||
@ -331,51 +331,80 @@ int a3700_fdt_fix_pcie_regions(void *blob)
|
||||
return node;
|
||||
|
||||
ranges = fdt_getprop(blob, node, "ranges", &len);
|
||||
if (!ranges || len % sizeof(u32))
|
||||
return -ENOENT;
|
||||
if (!ranges || !len || len % sizeof(u32))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The "ranges" property is an array of
|
||||
* { <child address> <parent address> <size in child address space> }
|
||||
* { <PCI address> <CPU address> <size in PCI address space> }
|
||||
* where number of PCI address cells and size cells is stored in the
|
||||
* "#address-cells" and "#size-cells" properties of the same node
|
||||
* containing the "ranges" property and number of CPU address cells
|
||||
* is stored in the parent's "#address-cells" property.
|
||||
*
|
||||
* All 3 elements can span a diffent number of cells. Fetch their sizes.
|
||||
* All 3 elements can span a diffent number of cells. Fetch them.
|
||||
*/
|
||||
pnode = fdt_parent_offset(blob, node);
|
||||
acells = fdt_address_cells(blob, node);
|
||||
pacells = fdt_address_cells(blob, pnode);
|
||||
scells = fdt_size_cells(blob, node);
|
||||
pci_cells = fdt_address_cells(blob, node);
|
||||
cpu_cells = fdt_address_cells(blob, pnode);
|
||||
size_cells = fdt_size_cells(blob, node);
|
||||
|
||||
/* Child PCI addresses always use 3 cells */
|
||||
if (acells != 3)
|
||||
return -ENOENT;
|
||||
/* PCI addresses always use 3 cells */
|
||||
if (pci_cells != 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* Calculate fixup offset from first child address (in last cell) */
|
||||
fix_offset = base - fdt32_to_cpu(ranges[2]);
|
||||
/* CPU addresses on Armada 37xx always use 2 cells */
|
||||
if (cpu_cells != 2)
|
||||
return -EINVAL;
|
||||
|
||||
/* If fixup offset is zero then there is nothing to fix */
|
||||
for (i = 0; i < len / sizeof(u32);
|
||||
i += pci_cells + cpu_cells + size_cells) {
|
||||
/*
|
||||
* Parent CPU addresses on Armada 37xx are always 32-bit, so
|
||||
* check that the high word is zero.
|
||||
*/
|
||||
if (fdt32_to_cpu(ranges[i + pci_cells]))
|
||||
return -EINVAL;
|
||||
|
||||
if (i == 0 ||
|
||||
fdt32_to_cpu(ranges[i + pci_cells + 1]) < lowest_cpu_addr)
|
||||
lowest_cpu_addr = fdt32_to_cpu(ranges[i + pci_cells + 1]);
|
||||
}
|
||||
|
||||
/* Calculate fixup offset from the lowest (first) CPU address */
|
||||
fix_offset = base - lowest_cpu_addr;
|
||||
|
||||
/* If fixup offset is zero there is nothing to fix */
|
||||
if (!fix_offset)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Fix address (last cell) of each child address and each parent
|
||||
* address
|
||||
* Fix each CPU address and corresponding PCI address if PCI address
|
||||
* is not already remapped (has the same value)
|
||||
*/
|
||||
for (i = 0; i < len / sizeof(u32); i += acells + pacells + scells) {
|
||||
for (i = 0; i < len / sizeof(u32);
|
||||
i += pci_cells + cpu_cells + size_cells) {
|
||||
u32 cpu_addr;
|
||||
u64 pci_addr;
|
||||
int idx;
|
||||
|
||||
/* fix child address */
|
||||
idx = i + acells - 1;
|
||||
/* Fix CPU address */
|
||||
idx = i + pci_cells + cpu_cells - 1;
|
||||
cpu_addr = fdt32_to_cpu(ranges[idx]);
|
||||
ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx,
|
||||
fdt32_to_cpu(ranges[idx]) +
|
||||
fix_offset);
|
||||
cpu_addr + fix_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* fix parent address */
|
||||
idx = i + acells + pacells - 1;
|
||||
/* Fix PCI address only if it isn't remapped (is same as CPU) */
|
||||
idx = i + pci_cells - 1;
|
||||
pci_addr = ((u64)fdt32_to_cpu(ranges[idx - 1]) << 32) |
|
||||
fdt32_to_cpu(ranges[idx]);
|
||||
if (cpu_addr != pci_addr)
|
||||
continue;
|
||||
|
||||
ret = fdt_setprop_inplace_u32_partial(blob, node, "ranges", idx,
|
||||
fdt32_to_cpu(ranges[idx]) +
|
||||
fix_offset);
|
||||
cpu_addr + fix_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -332,9 +332,6 @@ config MACH_SUN9I
|
||||
config MACH_SUN50I
|
||||
bool "sun50i (Allwinner A64)"
|
||||
select ARM64
|
||||
select SPI
|
||||
select DM_SPI if SPI
|
||||
select DM_SPI_FLASH
|
||||
select PHY_SUN4I_USB
|
||||
select SUN6I_PRCM
|
||||
select SUNXI_DE2
|
||||
@ -1038,7 +1035,7 @@ config SPL_STACK_R_ADDR
|
||||
|
||||
config SPL_SPI_SUNXI
|
||||
bool "Support for SPI Flash on Allwinner SoCs in SPL"
|
||||
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6
|
||||
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_R40 || MACH_SUN50I_H6 || MACH_SUNIV
|
||||
help
|
||||
Enable support for SPI Flash. This option allows SPL to read from
|
||||
sunxi SPI Flash. It uses the same method as the boot ROM, so does
|
||||
|
@ -191,11 +191,47 @@ SPL_LOAD_IMAGE_METHOD("FEL", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
|
||||
|
||||
#define SUNXI_INVALID_BOOT_SOURCE -1
|
||||
|
||||
static int suniv_get_boot_source(void)
|
||||
{
|
||||
/* Get the last function call from BootROM's stack. */
|
||||
u32 brom_call = *(u32 *)(uintptr_t)(fel_stash.sp - 4);
|
||||
|
||||
/* translate SUNIV BootROM stack to standard SUNXI boot sources */
|
||||
switch (brom_call) {
|
||||
case SUNIV_BOOTED_FROM_MMC0:
|
||||
return SUNXI_BOOTED_FROM_MMC0;
|
||||
case SUNIV_BOOTED_FROM_SPI:
|
||||
return SUNXI_BOOTED_FROM_SPI;
|
||||
case SUNIV_BOOTED_FROM_MMC1:
|
||||
return SUNXI_BOOTED_FROM_MMC2;
|
||||
/* SPI NAND is not supported yet. */
|
||||
case SUNIV_BOOTED_FROM_NAND:
|
||||
return SUNXI_INVALID_BOOT_SOURCE;
|
||||
}
|
||||
/* If we get here something went wrong try to boot from FEL.*/
|
||||
printf("Unknown boot source from BROM: 0x%x\n", brom_call);
|
||||
return SUNXI_INVALID_BOOT_SOURCE;
|
||||
}
|
||||
|
||||
static int sunxi_get_boot_source(void)
|
||||
{
|
||||
/*
|
||||
* On the ARMv5 SoCs, the SPL header in SRAM is overwritten by the
|
||||
* exception vectors in U-Boot proper, so we won't find any
|
||||
* information there. Also the FEL stash is only valid in the SPL,
|
||||
* so we can't use that either. So if this is called from U-Boot
|
||||
* proper, just return MMC0 as a placeholder, for now.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_MACH_SUNIV) &&
|
||||
!IS_ENABLED(CONFIG_SPL_BUILD))
|
||||
return SUNXI_BOOTED_FROM_MMC0;
|
||||
|
||||
if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
|
||||
return SUNXI_INVALID_BOOT_SOURCE;
|
||||
|
||||
if (IS_ENABLED(CONFIG_MACH_SUNIV))
|
||||
return suniv_get_boot_source();
|
||||
else
|
||||
return readb(SPL_ADDR + 0x28);
|
||||
}
|
||||
|
||||
@ -276,36 +312,10 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
|
||||
return sector;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MACH_SUNIV
|
||||
/*
|
||||
* The suniv BROM does not pass the boot media type to SPL, so we try with the
|
||||
* boot sequence in BROM: mmc0->spinor->fail.
|
||||
* TODO: This has the slight chance of being wrong (invalid SPL signature,
|
||||
* but valid U-Boot legacy image on the SD card), but this should be rare.
|
||||
* It looks like we can deduce from some BROM state upon entering the SPL
|
||||
* (registers, SP, or stack itself) where the BROM was coming from and use
|
||||
* that here.
|
||||
*/
|
||||
void board_boot_order(u32 *spl_boot_list)
|
||||
{
|
||||
/*
|
||||
* See the comments above in sunxi_get_boot_device() for information
|
||||
* about FEL boot.
|
||||
*/
|
||||
if (!is_boot0_magic(SPL_ADDR + 4)) {
|
||||
spl_boot_list[0] = BOOT_DEVICE_BOARD;
|
||||
return;
|
||||
}
|
||||
|
||||
spl_boot_list[0] = BOOT_DEVICE_MMC1;
|
||||
spl_boot_list[1] = BOOT_DEVICE_SPI;
|
||||
}
|
||||
#else
|
||||
u32 spl_boot_device(void)
|
||||
{
|
||||
return sunxi_get_boot_device();
|
||||
}
|
||||
#endif
|
||||
|
||||
__weak void sunxi_sram_init(void)
|
||||
{
|
||||
|
@ -90,6 +90,7 @@
|
||||
|
||||
#define SPI0_CLK_DIV_BY_2 0x1000
|
||||
#define SPI0_CLK_DIV_BY_4 0x1001
|
||||
#define SPI0_CLK_DIV_BY_32 0x100f
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -132,7 +133,8 @@ static uintptr_t spi0_base_address(void)
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
|
||||
return 0x05010000;
|
||||
|
||||
if (!is_sun6i_gen_spi())
|
||||
if (!is_sun6i_gen_spi() ||
|
||||
IS_ENABLED(CONFIG_MACH_SUNIV))
|
||||
return 0x01C05000;
|
||||
|
||||
return 0x01C68000;
|
||||
@ -156,11 +158,16 @@ static void spi0_enable_clock(void)
|
||||
if (!IS_ENABLED(CONFIG_MACH_SUN50I_H6))
|
||||
setbits_le32(CCM_AHB_GATING0, (1 << AHB_GATE_OFFSET_SPI0));
|
||||
|
||||
if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
|
||||
/* Divide by 32, clock source is AHB clock 200MHz */
|
||||
writel(SPI0_CLK_DIV_BY_32, base + SUN6I_SPI0_CCTL);
|
||||
} else {
|
||||
/* Divide by 4 */
|
||||
writel(SPI0_CLK_DIV_BY_4, base + (is_sun6i_gen_spi() ?
|
||||
SUN6I_SPI0_CCTL : SUN4I_SPI0_CCTL));
|
||||
/* 24MHz from OSC24M */
|
||||
writel((1 << 31), CCM_SPI0_CLK);
|
||||
}
|
||||
|
||||
if (is_sun6i_gen_spi()) {
|
||||
/* Enable SPI in the master mode and do a soft reset */
|
||||
@ -191,6 +198,7 @@ static void spi0_disable_clock(void)
|
||||
SUN4I_CTL_ENABLE);
|
||||
|
||||
/* Disable the SPI0 clock */
|
||||
if (!IS_ENABLED(CONFIG_MACH_SUNIV))
|
||||
writel(0, CCM_SPI0_CLK);
|
||||
|
||||
/* Close the SPI0 gate */
|
||||
@ -212,6 +220,8 @@ static void spi0_init(void)
|
||||
if (IS_ENABLED(CONFIG_MACH_SUN50I) ||
|
||||
IS_ENABLED(CONFIG_MACH_SUN50I_H6))
|
||||
pin_function = SUN50I_GPC_SPI0;
|
||||
else if (IS_ENABLED(CONFIG_MACH_SUNIV))
|
||||
pin_function = SUNIV_GPC_SPI0;
|
||||
|
||||
spi0_pinmux_setup(pin_function);
|
||||
spi0_enable_clock();
|
||||
|
@ -47,7 +47,13 @@ enum {
|
||||
BINF_RW_B = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* enum cros_fw_type_t - Used to indicate Chromium OS firmware type
|
||||
*
|
||||
* Chromium OS uses a region of the GNVS starting at offset 0x100 to store
|
||||
* various bits of information, including the type of firmware being booted
|
||||
*/
|
||||
enum cros_fw_type_t {
|
||||
FIRMWARE_TYPE_AUTO_DETECT = -1,
|
||||
FIRMWARE_TYPE_RECOVERY = 0,
|
||||
FIRMWARE_TYPE_NORMAL = 1,
|
||||
|
@ -1,3 +1,3 @@
|
||||
dsdt.aml
|
||||
dsdt.asl.tmp
|
||||
dsdt.c
|
||||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
||||
|
@ -73,6 +73,7 @@ static struct mv_ddr_topology_map board_topology_map = {
|
||||
{0}, /* timing parameters */
|
||||
{ {0} }, /* electrical configuration */
|
||||
{0}, /* electrical parameters */
|
||||
0, /* ODT configuration */
|
||||
0, /* Clock enable mask */
|
||||
160 /* Clock delay */
|
||||
};
|
||||
|
@ -1,3 +1,3 @@
|
||||
dsdt.aml
|
||||
dsdt.asl.tmp
|
||||
dsdt.c
|
||||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
||||
|
@ -2,12 +2,12 @@ COREBOOT BOARD
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: board/coreboot/coreboot/
|
||||
F: include/configs/chromebook_link.h
|
||||
F: include/configs/coreboot.h
|
||||
F: configs/coreboot_defconfig
|
||||
|
||||
COREBOOT64 BOARD
|
||||
M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: board/coreboot/coreboot/
|
||||
F: include/configs/chromebook_link.h
|
||||
F: include/configs/coreboot.h
|
||||
F: configs/coreboot64_defconfig
|
||||
|
6
board/intel/bayleybay/.gitignore
vendored
6
board/intel/bayleybay/.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
dsdt.aml
|
||||
dsdt.asl.tmp
|
||||
dsdt.c
|
||||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
||||
|
6
board/intel/edison/.gitignore
vendored
6
board/intel/edison/.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
dsdt.aml
|
||||
dsdt.asl.tmp
|
||||
dsdt.c
|
||||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
||||
|
6
board/intel/galileo/.gitignore
vendored
6
board/intel/galileo/.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
dsdt.aml
|
||||
dsdt.asl.tmp
|
||||
dsdt.c
|
||||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
||||
|
6
board/intel/minnowmax/.gitignore
vendored
6
board/intel/minnowmax/.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
dsdt.aml
|
||||
dsdt.asl.tmp
|
||||
dsdt.c
|
||||
dsdt_generated.aml
|
||||
dsdt_generated.asl.tmp
|
||||
dsdt_generated.c
|
||||
|
@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <fsl_ddr.h>
|
||||
@ -14,7 +15,9 @@
|
||||
#include <asm/arch/soc.h>
|
||||
#include <fsl_immap.h>
|
||||
#include <netdev.h>
|
||||
#include <wdt.h>
|
||||
|
||||
#include <sl28cpld.h>
|
||||
#include <fdtdec.h>
|
||||
#include <miiphy.h>
|
||||
|
||||
@ -39,16 +42,68 @@ int board_eth_init(struct bd_info *bis)
|
||||
return pci_eth_init(bis);
|
||||
}
|
||||
|
||||
static int __sl28cpld_read(uint reg)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_NOP,
|
||||
DM_DRIVER_GET(sl28cpld), &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sl28cpld_read(dev, reg);
|
||||
}
|
||||
|
||||
static void print_cpld_version(void)
|
||||
{
|
||||
int version = __sl28cpld_read(SL28CPLD_VERSION);
|
||||
|
||||
if (version < 0)
|
||||
printf("CPLD: error reading version (%d)\n", version);
|
||||
else
|
||||
printf("CPLD: v%d\n", version);
|
||||
}
|
||||
|
||||
int checkboard(void)
|
||||
{
|
||||
printf("EL: %d\n", current_el());
|
||||
if (CONFIG_IS_ENABLED(SL28CPLD))
|
||||
print_cpld_version();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stop_recovery_watchdog(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_WDT,
|
||||
DM_DRIVER_GET(sl28cpld_wdt), &dev);
|
||||
if (!ret)
|
||||
wdt_stop(dev);
|
||||
}
|
||||
|
||||
int fsl_board_late_init(void)
|
||||
{
|
||||
/*
|
||||
* Usually, the after a board reset, the watchdog is enabled by
|
||||
* default. This is to supervise the bootloader boot-up. Therefore,
|
||||
* to prevent a watchdog reset if we don't actively kick it, we have
|
||||
* to disable it.
|
||||
*
|
||||
* If the watchdog isn't enabled at reset (which is a configuration
|
||||
* option) disabling it doesn't hurt either.
|
||||
*/
|
||||
if (!CONFIG_IS_ENABLED(WATCHDOG_AUTOSTART))
|
||||
stop_recovery_watchdog();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void detail_board_ddr_info(void)
|
||||
{
|
||||
puts("\nDDR ");
|
||||
print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
|
||||
print_ddr_info(0);
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,7 @@ static struct mv_ddr_topology_map board_topology_map = {
|
||||
{0}, /* timing parameters */
|
||||
{ {0} }, /* electrical configuration */
|
||||
{0,}, /* electrical parameters */
|
||||
0, /* ODT configuration */
|
||||
0x3, /* clock enable mask */
|
||||
};
|
||||
|
||||
|
@ -171,21 +171,56 @@ void i2c_init_board(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT)
|
||||
/*
|
||||
* Try to use the environment from the boot source first.
|
||||
* For MMC, this means a FAT partition on the boot device (SD or eMMC).
|
||||
* If the raw MMC environment is also enabled, this is tried next.
|
||||
* SPI flash falls back to FAT (on SD card).
|
||||
*/
|
||||
enum env_location env_get_location(enum env_operation op, int prio)
|
||||
{
|
||||
switch (prio) {
|
||||
case 0:
|
||||
return ENVL_FAT;
|
||||
enum env_location boot_loc = ENVL_FAT;
|
||||
|
||||
case 1:
|
||||
return ENVL_MMC;
|
||||
gd->env_load_prio = prio;
|
||||
|
||||
switch (sunxi_get_boot_device()) {
|
||||
case BOOT_DEVICE_MMC1:
|
||||
case BOOT_DEVICE_MMC2:
|
||||
boot_loc = ENVL_FAT;
|
||||
break;
|
||||
case BOOT_DEVICE_NAND:
|
||||
if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
|
||||
boot_loc = ENVL_NAND;
|
||||
break;
|
||||
case BOOT_DEVICE_SPI:
|
||||
if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
|
||||
boot_loc = ENVL_SPI_FLASH;
|
||||
break;
|
||||
case BOOT_DEVICE_BOARD:
|
||||
break;
|
||||
default:
|
||||
return ENVL_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Always try to access the environment on the boot device first. */
|
||||
if (prio == 0)
|
||||
return boot_loc;
|
||||
|
||||
if (prio == 1) {
|
||||
switch (boot_loc) {
|
||||
case ENVL_SPI_FLASH:
|
||||
return ENVL_FAT;
|
||||
case ENVL_FAT:
|
||||
if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
|
||||
return ENVL_MMC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ENVL_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DM_MMC
|
||||
static void mmc_pinmux_setup(int sdc);
|
||||
|
@ -129,6 +129,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TI_I2C_BOARD_DETECT
|
||||
int do_board_detect(void)
|
||||
{
|
||||
int ret;
|
||||
@ -353,9 +354,11 @@ static int probe_daughtercards(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_late_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_TI_I2C_BOARD_DETECT)) {
|
||||
struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
|
||||
|
||||
setup_board_eeprom_env();
|
||||
@ -370,6 +373,7 @@ int board_late_init(void)
|
||||
|
||||
/* Check for and probe any plugged-in daughtercards */
|
||||
probe_daughtercards();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -397,36 +397,34 @@ void configure_serdes_torrent(void)
|
||||
|
||||
void configure_serdes_sierra(void)
|
||||
{
|
||||
struct udevice *dev, *lnk_dev;
|
||||
struct phy serdes;
|
||||
struct udevice *dev, *link_dev;
|
||||
struct phy link;
|
||||
int ret, count, i;
|
||||
int link_count = 0;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PHY_CADENCE_SIERRA))
|
||||
return;
|
||||
|
||||
ret = uclass_get_device_by_driver(UCLASS_PHY,
|
||||
ret = uclass_get_device_by_driver(UCLASS_MISC,
|
||||
DM_DRIVER_GET(sierra_phy_provider),
|
||||
&dev);
|
||||
if (ret)
|
||||
printf("Sierra init failed:%d\n", ret);
|
||||
|
||||
serdes.dev = dev;
|
||||
serdes.id = 0;
|
||||
|
||||
count = device_get_child_count(dev);
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = device_get_child(dev, i, &lnk_dev);
|
||||
ret = device_get_child(dev, i, &link_dev);
|
||||
if (ret)
|
||||
printf("probe of sierra child node %d failed\n", i);
|
||||
}
|
||||
if (link_dev->driver->id == UCLASS_PHY) {
|
||||
link.dev = link_dev;
|
||||
link.id = link_count++;
|
||||
|
||||
ret = generic_phy_init(&serdes);
|
||||
if (ret)
|
||||
printf("phy_init failed!!\n");
|
||||
|
||||
ret = generic_phy_power_on(&serdes);
|
||||
ret = generic_phy_power_on(&link);
|
||||
if (ret)
|
||||
printf("phy_power_on failed !!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_LATE_INIT
|
||||
|
10
cmd/cls.c
10
cmd/cls.c
@ -11,17 +11,23 @@
|
||||
#include <lcd.h>
|
||||
#include <video.h>
|
||||
|
||||
#define CSI "\x1b["
|
||||
|
||||
static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
#if defined(CONFIG_DM_VIDEO)
|
||||
struct udevice *dev;
|
||||
__maybe_unused struct udevice *dev;
|
||||
|
||||
/* Send clear screen and home */
|
||||
printf(CSI "2J" CSI "1;1H");
|
||||
#if defined(CONFIG_DM_VIDEO)
|
||||
#if !defined(CONFIG_VIDEO_ANSI)
|
||||
if (uclass_first_device_err(UCLASS_VIDEO, &dev))
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (video_clear(dev))
|
||||
return CMD_RET_FAILURE;
|
||||
#endif
|
||||
#elif defined(CONFIG_CFB_CONSOLE)
|
||||
video_clear();
|
||||
#elif defined(CONFIG_LCD)
|
||||
|
@ -111,5 +111,5 @@ U_BOOT_CMD(pwm, 6, 0, do_pwm,
|
||||
"invert <pwm_dev_num> <channel> <polarity> - invert polarity\n"
|
||||
"pwm config <pwm_dev_num> <channel> <period_ns> <duty_ns> - config PWM\n"
|
||||
"pwm enable <pwm_dev_num> <channel> - enable PWM output\n"
|
||||
"pwm disable <pwm_dev_num> <channel> - eisable PWM output\n"
|
||||
"pwm disable <pwm_dev_num> <channel> - disable PWM output\n"
|
||||
"Note: All input values are in decimal");
|
||||
|
@ -193,3 +193,4 @@ CONFIG_UFS=y
|
||||
CONFIG_CADENCE_UFS=y
|
||||
CONFIG_TI_J721E_UFS=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_MMC_SPEED_MODE_SET=y
|
||||
|
@ -162,3 +162,4 @@ CONFIG_UFS=y
|
||||
CONFIG_CADENCE_UFS=y
|
||||
CONFIG_TI_J721E_UFS=y
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_MMC_SPEED_MODE_SET=y
|
||||
|
@ -42,23 +42,23 @@ CONFIG_CMD_GREPENV=y
|
||||
CONFIG_CMD_NVEDIT_EFI=y
|
||||
CONFIG_CMD_DFU=y
|
||||
CONFIG_CMD_DM=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_WDT=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_EFIDEBUG=y
|
||||
CONFIG_CMD_RNG=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_OF_LIST=""
|
||||
CONFIG_OF_LIST="fsl-ls1028a-kontron-sl28 fsl-ls1028a-kontron-sl28-var1 fsl-ls1028a-kontron-sl28-var2 fsl-ls1028a-kontron-sl28-var3 fsl-ls1028a-kontron-sl28-var4"
|
||||
CONFIG_ENV_OVERWRITE=y
|
||||
CONFIG_ENV_IS_IN_SPI_FLASH=y
|
||||
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_NETCONSOLE=y
|
||||
CONFIG_SPL_DM_SEQ_ALIAS=y
|
||||
CONFIG_SATA=y
|
||||
CONFIG_SCSI_AHCI=y
|
||||
@ -69,8 +69,10 @@ CONFIG_DDR_ECC=y
|
||||
CONFIG_ECC_INIT_VIA_DDRCONTROLLER=y
|
||||
CONFIG_DFU_MMC=y
|
||||
CONFIG_DFU_SF=y
|
||||
CONFIG_SL28CPLD_GPIO=y
|
||||
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_SL28CPLD=y
|
||||
CONFIG_MMC_HS400_SUPPORT=y
|
||||
CONFIG_FSL_ESDHC=y
|
||||
CONFIG_FSL_ESDHC_SUPPORT_ADMA2=y
|
||||
@ -102,6 +104,11 @@ CONFIG_USB_DWC3=y
|
||||
CONFIG_USB_DWC3_LAYERSCAPE=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_DOWNLOAD=y
|
||||
# CONFIG_WATCHDOG is not set
|
||||
# CONFIG_WATCHDOG_AUTOSTART is not set
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_SL28CPLD=y
|
||||
CONFIG_WDT_SP805=y
|
||||
CONFIG_OF_LIBFDT_ASSUME_MASK=0x0
|
||||
CONFIG_OF_LIBFDT_OVERLAY=y
|
||||
CONFIG_EFI_SET_TIME=y
|
||||
|
@ -7,9 +7,7 @@ CONFIG_DRAM_CLK=672
|
||||
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_XMC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -7,10 +7,8 @@ CONFIG_DRAM_CLK=672
|
||||
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH_XMC=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -9,3 +9,5 @@ CONFIG_MACH_SUNIV=y
|
||||
CONFIG_DRAM_CLK=156
|
||||
CONFIG_DRAM_ZQ=0
|
||||
# CONFIG_VIDEO_SUNXI is not set
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYSRESET is not set
|
||||
|
@ -11,5 +11,6 @@ CONFIG_MMC0_CD_PIN=""
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -11,9 +11,11 @@ CONFIG_SPL_SPI_SUNXI=y
|
||||
CONFIG_SPL_I2C=y
|
||||
CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SY8106A_POWER=y
|
||||
CONFIG_SY8106A_VOUT1_VOLT=1100
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_MUSB_GADGET=y
|
||||
|
@ -8,6 +8,8 @@ CONFIG_DRAM_CLK=624
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_CONSOLE_MUX=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -7,7 +7,9 @@ CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
|
||||
CONFIG_MACPWR="PD14"
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -15,5 +15,7 @@ CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
CONFIG_SYS_I2C_SLAVE=0x7f
|
||||
CONFIG_SYS_I2C_SPEED=400000
|
||||
CONFIG_SPI_FLASH_MACRONIX=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
|
@ -8,6 +8,8 @@ CONFIG_DRAM_CLK=624
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_CONSOLE_MUX=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -10,6 +10,8 @@ CONFIG_MMC0_CD_PIN=""
|
||||
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -11,8 +11,10 @@ CONFIG_USB3_VBUS_PIN="PL5"
|
||||
CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_PSCI_RESET is not set
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_PHY_SUN50I_USB3=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_DWC3=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
|
@ -12,8 +12,10 @@ CONFIG_SPL_SYS_I2C_LEGACY=y
|
||||
CONFIG_SYS_I2C_MVTWSI=y
|
||||
CONFIG_SYS_I2C_SLAVE=0x7f
|
||||
CONFIG_SYS_I2C_SPEED=400000
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
# CONFIG_NETDEVICES is not set
|
||||
CONFIG_AXP209_POWER=y
|
||||
CONFIG_AXP_DCDC2_VOLT=1250
|
||||
CONFIG_AXP_DCDC3_VOLT=3300
|
||||
CONFIG_CONS_INDEX=3
|
||||
CONFIG_SPI=y
|
||||
|
@ -13,5 +13,6 @@ CONFIG_SPL_SPI_SUNXI=y
|
||||
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
|
@ -14,6 +14,7 @@ CONFIG_DEFAULT_DEVICE_TREE="imx6q-tbs2910"
|
||||
CONFIG_PRE_CON_BUF_ADDR=0x7c000000
|
||||
CONFIG_CMD_HDMIDETECT=y
|
||||
CONFIG_AHCI=y
|
||||
CONFIG_LTO=y
|
||||
CONFIG_SUPPORT_RAW_INITRD=y
|
||||
CONFIG_BOOTDELAY=3
|
||||
CONFIG_USE_BOOTCOMMAND=y
|
||||
|
@ -93,3 +93,4 @@ CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_WDT=y
|
||||
CONFIG_WDT_ORION=y
|
||||
CONFIG_EXT4_WRITE=y
|
||||
|
@ -17,7 +17,7 @@ CONFIG_ANDROID_BOOT_IMAGE=y
|
||||
CONFIG_BOOTDELAY=1
|
||||
CONFIG_USE_BOOTARGS=y
|
||||
CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9"
|
||||
CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then set bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; set fdt_high 0xffffffffffffffff; set initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr - $fdt_addr_r; fi"
|
||||
CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then setenv bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; setenv fdt_high 0xffffffffffffffff; setenv initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr_r}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr_r - $fdt_addr_r; fi"
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
# CONFIG_DISPLAY_BOARDINFO is not set
|
||||
CONFIG_SYS_PROMPT="VExpress64# "
|
||||
|
@ -23,34 +23,17 @@ Copy u-boot.rom to a TFTP server.
|
||||
Install the bootloader on the board
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Please note, this bootloader doesn't support the builtin watchdog (yet),
|
||||
therefore you have to disable it, see below. Otherwise you'll end up in
|
||||
the failsafe bootloader on every reset::
|
||||
To install the bootloader binary use the following command::
|
||||
|
||||
> tftp path/to/u-boot.rom
|
||||
> sf probe 0
|
||||
> sf update $fileaddr 0x210000 $filesize
|
||||
|
||||
The board is fully failsafe, you can't break anything. But because you've
|
||||
disabled the builtin watchdog you might have to manually enter failsafe
|
||||
mode by asserting the ``FORCE_RECOV#`` line during board reset.
|
||||
|
||||
Disable the builtin watchdog
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- boot into the failsafe bootloader, either by asserting the
|
||||
``FORCE_RECOV#`` line or if you still have the original bootloader
|
||||
installed you can use the command::
|
||||
|
||||
> wdt dev cpld_watchdog@4a; wdt expire 1
|
||||
|
||||
- in the failsafe bootloader use the "sl28 nvm" command to disable
|
||||
the automatic start of the builtin watchdog::
|
||||
|
||||
> sl28 nvm 0008
|
||||
|
||||
- power-cycle the board
|
||||
|
||||
The board is fully failsafe, you can't break anything. If builtin watchdog
|
||||
is enabled, you'll automatically end up in the failsafe bootloader if
|
||||
something goes wrong. If the watchdog is disabled, you have to manually
|
||||
enter failsafe mode by asserting the ``FORCE_RECOV#`` line during board
|
||||
reset.
|
||||
|
||||
Update image
|
||||
------------
|
||||
@ -67,20 +50,41 @@ Afterward you can copy this file to your ESP into the /EFI/UpdateCapsule/
|
||||
folder. On the next EFI boot this will automatically update your
|
||||
bootloader.
|
||||
|
||||
Useful I2C tricks
|
||||
-----------------
|
||||
Builtin watchdog
|
||||
----------------
|
||||
|
||||
The board has a board management controller which is not supported in
|
||||
u-boot (yet). But you can use the i2c command to access it.
|
||||
The builtin watchdog will supervise the bootloader startup. If anything
|
||||
goes wrong it will reset the board and boot into the failsafe bootloader.
|
||||
|
||||
- reset into failsafe bootloader::
|
||||
Once the bootloader is started successfully, it will disable the watchdog
|
||||
timer.
|
||||
|
||||
> i2c mw 4a 5.1 0; i2c mw 4a 6.1 6b; i2c mw 4a 4.1 42
|
||||
wdt command flags
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
- read board management controller version::
|
||||
The `wdt start` as well as the `wdt expire` command take a flags argument.
|
||||
The supported bitmask is as follows.
|
||||
|
||||
> i2c md 4a 3.1 1
|
||||
| Bit | Description |
|
||||
| --- | ----------------------------- |
|
||||
| 0 | Enable failsafe mode |
|
||||
| 1 | Lock the control register |
|
||||
| 2 | Disable board reset |
|
||||
| 3 | Enable WDT_TIME_OUT# line |
|
||||
|
||||
For example, you can use `wdt expire 1` to issue a reset and boot into the
|
||||
failsafe bootloader.
|
||||
|
||||
Disable the builtin watchdog
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If for some reason, this isn't a desired behavior, the watchdog can also
|
||||
be configured to not be enabled on board reset. It's configuration is saved
|
||||
in the non-volatile board configuration bits. To change these you can use
|
||||
the `sl28 nvm` command.
|
||||
|
||||
For more information on the non-volatile board configuration bits, see the
|
||||
following section.
|
||||
|
||||
Non-volatile Board Configuration Bits
|
||||
-------------------------------------
|
||||
|
@ -560,7 +560,7 @@ Write U-boot SPL and U-boot to their partitions.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
dd if=u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync
|
||||
dd if=spl/u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync
|
||||
dd if=u-boot.itb of=/dev/mtdblock0 bs=4096 seek=261 conv=sync
|
||||
|
||||
Power off the board.
|
||||
|
11
doc/build/gcc.rst
vendored
11
doc/build/gcc.rst
vendored
@ -25,11 +25,12 @@ Depending on the build targets further packages maybe needed
|
||||
|
||||
sudo apt-get install bc bison build-essential coccinelle \
|
||||
device-tree-compiler dfu-util efitools flex gdisk graphviz imagemagick \
|
||||
liblz4-tool libguestfs-tools libncurses-dev libpython3-dev libsdl2-dev \
|
||||
libssl-dev lz4 lzma lzma-alone openssl pkg-config python3 \
|
||||
python3-coverage python3-pkg-resources python3-pycryptodome \
|
||||
python3-pyelftools python3-pytest python3-sphinxcontrib.apidoc \
|
||||
python3-sphinx-rtd-theme python3-virtualenv swig
|
||||
liblz4-tool libgnutls28-dev libguestfs-tools libncurses-dev \
|
||||
libpython3-dev libsdl2-dev libssl-dev lz4 lzma lzma-alone openssl \
|
||||
pkg-config python3 python3-coverage python3-pkg-resources \
|
||||
python3-pycryptodome python3-pyelftools python3-pytest \
|
||||
python3-sphinxcontrib.apidoc python3-sphinx-rtd-theme python3-virtualenv \
|
||||
swig
|
||||
|
||||
SUSE based
|
||||
~~~~~~~~~~
|
||||
|
105
doc/kwboot.1
105
doc/kwboot.1
@ -1,4 +1,4 @@
|
||||
.TH KWBOOT 1 "2021-08-25"
|
||||
.TH KWBOOT 1 "2022-03-02"
|
||||
|
||||
.SH NAME
|
||||
kwboot \- Boot Marvell Kirkwood (and others 32-bit) SoCs over a serial link.
|
||||
@ -11,7 +11,7 @@ kwboot \- Boot Marvell Kirkwood (and others 32-bit) SoCs over a serial link.
|
||||
.SH "DESCRIPTION"
|
||||
|
||||
The \fBkwboot\fP program boots boards based on Marvell's 32-bit
|
||||
platforms including Kirkwood, Dove, A370, AXP, A375, A38x
|
||||
platforms including Kirkwood, Dove, Avanta, A370, AXP, A375, A38x
|
||||
and A39x over their integrated UART. Boot image files will typically
|
||||
contain a second stage boot loader, such as U-Boot. The image file
|
||||
must conform to Marvell's BootROM firmware image format
|
||||
@ -47,6 +47,48 @@ code in it's header which may also print some output via UART (for
|
||||
example U-Boot SPL does this). In such a case, this output is also
|
||||
written to stdout after the header is sent.
|
||||
|
||||
.TP
|
||||
.B "\-b"
|
||||
Do only handshake on \fITTY\fP without uploading any file. File upload
|
||||
could be done later via option \fB\-D\fP or via any other Xmodem
|
||||
application, like \fBsx\fP(1).
|
||||
|
||||
.TP
|
||||
.B "\-d"
|
||||
Do special handshake on \fITTY\fP for console debug mode.
|
||||
|
||||
This will instruct BootROM to enter builtin simple console debug mode.
|
||||
Should be combined with option \fB\-t\fP.
|
||||
|
||||
To get a BootROM help, type this command followed by ENTER key:
|
||||
|
||||
.RS 1.2i
|
||||
.TP
|
||||
.B ?
|
||||
.RE
|
||||
.IP
|
||||
|
||||
Armada 38x BootROM has a bug which cause that BootROM's standard output
|
||||
is turned off on UART when SPI-NOR contains valid boot image. Nevertheless
|
||||
BootROM's standard input and BootROM's terminal echo are active and working
|
||||
fine. To workaround this BootROM bug with standard output, it is possible
|
||||
to manually overwrite BootROM variables stored in SRAM which BootROM use
|
||||
for checking if standard output is enabled or not. To enable BootROM
|
||||
standard output on UART, type this command folled by ENTER key:
|
||||
|
||||
.RS 1.2i
|
||||
.TP
|
||||
.B w 0x40034100 1
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.BI "\-D" " image"
|
||||
Upload file \fIimage\fP over \fITTY\fP without initial handshake.
|
||||
|
||||
This method is used primary on Dove platforms, where BootROM does
|
||||
not support initial handshake for entering UART upload mode and
|
||||
strapping pins (exported via e.g. buttons) are used instead.
|
||||
|
||||
.TP
|
||||
.BI "\-p"
|
||||
Obsolete. Does nothing.
|
||||
@ -55,13 +97,33 @@ In the past, when this option was used, the program patched the header
|
||||
in the image prior upload, to "UART boot" type. This is now done by
|
||||
default.
|
||||
|
||||
.TP
|
||||
.B "\-q"
|
||||
Obsolete. Does nothing.
|
||||
|
||||
It is unknown whether it did something in the past.
|
||||
|
||||
.TP
|
||||
.BI "\-s" " response-timeout"
|
||||
Specify custom response timeout when doing handshake. Default value is 50 ms.
|
||||
It is the timeout between sending two consecutive handshake patterns, meaning
|
||||
how long to wait for response from BootROM. Affects only option \fB\-b\fP with
|
||||
image file and option \fB\-d\fP.
|
||||
|
||||
Option \fB-a\fP specify response timeout suitable for Armada XP BootROM and
|
||||
currently it is 1000 ms.
|
||||
|
||||
Some testing showed that specifying 24 ms as response timeout make handshake
|
||||
with Armada 385 BootROM more stable.
|
||||
|
||||
.TP
|
||||
.BI "\-t"
|
||||
Run a terminal program, connecting standard input and output to
|
||||
.RB \fITTY\fP.
|
||||
|
||||
If used in combination with \fB-b\fP, terminal mode is entered
|
||||
immediately following a successful image upload.
|
||||
If used in combination with \fB\-b\fP, \fB\-D\fP or \fB\-d\fP option,
|
||||
terminal mode is entered immediately following a successful image upload
|
||||
or successful handshake (if not doing image upload).
|
||||
|
||||
If standard I/O streams connect to a console, this mode will terminate
|
||||
after receiving \fBctrl-\e\fP followed by \fBc\fP from console input.
|
||||
@ -85,9 +147,42 @@ Tested values for \fIbaudrate\fP for Armada 38x include: 115200,
|
||||
230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000,
|
||||
2000000, 2500000, 3125000, 4000000 and 5200000.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
|
||||
Instruct BootROM to enter boot Xmodem boot mode, send \fIu-boot-spl.kwb\fP
|
||||
kwbimage file via Xmodem on \fI/dev/ttyUSB0\fP at 115200 Bd and run terminal
|
||||
program:
|
||||
.IP
|
||||
.B kwboot -b u-boot-spl.kwb -t /dev/ttyUSB0
|
||||
|
||||
.PP
|
||||
Instruct BootROM to enter boot Xmodem boot mode, send header of
|
||||
\fIu-boot-spl.kwb\fP kwbimage file via Xmodem at 115200 Bd, then instruct
|
||||
BootROM to change baudrate to 5200000 Bd, send data part of the kwbimage
|
||||
file via Xmodem at high speed and finally run terminal program:
|
||||
.IP
|
||||
.B kwboot -b u-boot-spl.kwb -B 5200000 -t /dev/ttyUSB0
|
||||
|
||||
.PP
|
||||
Only send \fIu-boot-spl.kwb\fP kwbimage file via Xmodem on \fI/dev/ttyUSB0\fP
|
||||
at 115200 Bd:
|
||||
.IP
|
||||
.B kwboot -D u-boot-spl.kwb /dev/ttyUSB0
|
||||
|
||||
.PP
|
||||
Instruct BootROM to enter console debug mode and run terminal program on
|
||||
\fI/dev/ttyUSB0\fP at 115200 Bd:
|
||||
.IP
|
||||
.B kwboot -d -t /dev/ttyUSB0
|
||||
|
||||
.PP
|
||||
Only run terminal program on \fI/dev/ttyUSB0\fP at 115200 Bd:
|
||||
.IP
|
||||
.B kwboot -t /dev/ttyUSB0
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.PP
|
||||
\fBmkimage\fP(1)
|
||||
\fBmkimage\fP(1), \fBsx\fP(1)
|
||||
|
||||
.SH "AUTHORS"
|
||||
|
||||
|
@ -552,4 +552,10 @@ config ZYNQMP_GPIO_MODEPIN
|
||||
are accessed using xilinx firmware. In modepin register, [3:0] bits
|
||||
set direction, [7:4] bits read IO, [11:8] bits set/clear IO.
|
||||
|
||||
config SL28CPLD_GPIO
|
||||
bool "Kontron sl28cpld GPIO driver"
|
||||
depends on DM_GPIO && SL28CPLD
|
||||
help
|
||||
Support GPIO access on Kontron sl28cpld board management controllers.
|
||||
|
||||
endif
|
||||
|
@ -71,4 +71,5 @@ obj-$(CONFIG_NX_GPIO) += nx_gpio.o
|
||||
obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o
|
||||
obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
|
||||
obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o
|
||||
obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
|
||||
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
|
||||
|
165
drivers/gpio/sl28cpld-gpio.c
Normal file
165
drivers/gpio/sl28cpld-gpio.c
Normal file
@ -0,0 +1,165 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* GPIO driver for the sl28cpld
|
||||
*
|
||||
* Copyright (c) 2021 Michael Walle <michael@walle.cc>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <sl28cpld.h>
|
||||
|
||||
/* GPIO flavor */
|
||||
#define SL28CPLD_GPIO_DIR 0x00
|
||||
#define SL28CPLD_GPIO_OUT 0x01
|
||||
#define SL28CPLD_GPIO_IN 0x02
|
||||
|
||||
/* input-only flavor */
|
||||
#define SL28CPLD_GPI_IN 0x00
|
||||
|
||||
/* output-only flavor */
|
||||
#define SL28CPLD_GPO_OUT 0x00
|
||||
|
||||
enum {
|
||||
SL28CPLD_GPIO,
|
||||
SL28CPLD_GPI,
|
||||
SL28CPLD_GPO,
|
||||
};
|
||||
|
||||
static int sl28cpld_gpio_get_value(struct udevice *dev, unsigned int gpio)
|
||||
{
|
||||
ulong type = dev_get_driver_data(dev);
|
||||
int val, reg;
|
||||
|
||||
switch (type) {
|
||||
case SL28CPLD_GPIO:
|
||||
reg = SL28CPLD_GPIO_IN;
|
||||
break;
|
||||
case SL28CPLD_GPI:
|
||||
reg = SL28CPLD_GPI_IN;
|
||||
break;
|
||||
case SL28CPLD_GPO:
|
||||
/* we are output only, thus just return the output value */
|
||||
reg = SL28CPLD_GPO_OUT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = sl28cpld_read(dev, reg);
|
||||
|
||||
return val < 0 ? val : !!(val & BIT(gpio));
|
||||
}
|
||||
|
||||
static int sl28cpld_gpio_set_value(struct udevice *dev, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
ulong type = dev_get_driver_data(dev);
|
||||
uint reg;
|
||||
|
||||
switch (type) {
|
||||
case SL28CPLD_GPIO:
|
||||
reg = SL28CPLD_GPIO_OUT;
|
||||
break;
|
||||
case SL28CPLD_GPO:
|
||||
reg = SL28CPLD_GPO_OUT;
|
||||
break;
|
||||
case SL28CPLD_GPI:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (value)
|
||||
return sl28cpld_update(dev, reg, 0, BIT(gpio));
|
||||
else
|
||||
return sl28cpld_update(dev, reg, BIT(gpio), 0);
|
||||
}
|
||||
|
||||
static int sl28cpld_gpio_direction_input(struct udevice *dev, unsigned int gpio)
|
||||
{
|
||||
ulong type = dev_get_driver_data(dev);
|
||||
|
||||
switch (type) {
|
||||
case SL28CPLD_GPI:
|
||||
return 0;
|
||||
case SL28CPLD_GPIO:
|
||||
return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, BIT(gpio), 0);
|
||||
case SL28CPLD_GPO:
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int sl28cpld_gpio_direction_output(struct udevice *dev,
|
||||
unsigned int gpio, int value)
|
||||
{
|
||||
ulong type = dev_get_driver_data(dev);
|
||||
int ret;
|
||||
|
||||
/* set_value() will report an error if we are input-only */
|
||||
ret = sl28cpld_gpio_set_value(dev, gpio, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (type == SL28CPLD_GPIO)
|
||||
return sl28cpld_update(dev, SL28CPLD_GPIO_DIR, 0, BIT(gpio));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sl28cpld_gpio_get_function(struct udevice *dev, unsigned int gpio)
|
||||
{
|
||||
ulong type = dev_get_driver_data(dev);
|
||||
int val;
|
||||
|
||||
switch (type) {
|
||||
case SL28CPLD_GPIO:
|
||||
val = sl28cpld_read(dev, SL28CPLD_GPIO_DIR);
|
||||
if (val < 0)
|
||||
return val;
|
||||
if (val & BIT(gpio))
|
||||
return GPIOF_OUTPUT;
|
||||
else
|
||||
return GPIOF_INPUT;
|
||||
case SL28CPLD_GPI:
|
||||
return GPIOF_INPUT;
|
||||
case SL28CPLD_GPO:
|
||||
return GPIOF_OUTPUT;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops sl28cpld_gpio_ops = {
|
||||
.direction_input = sl28cpld_gpio_direction_input,
|
||||
.direction_output = sl28cpld_gpio_direction_output,
|
||||
.get_value = sl28cpld_gpio_get_value,
|
||||
.set_value = sl28cpld_gpio_set_value,
|
||||
.get_function = sl28cpld_gpio_get_function,
|
||||
};
|
||||
|
||||
static int sl28cpld_gpio_probe(struct udevice *dev)
|
||||
{
|
||||
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
|
||||
uc_priv->gpio_count = 8;
|
||||
uc_priv->bank_name = dev_read_name(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sl28cpld_gpio_ids[] = {
|
||||
{ .compatible = "kontron,sl28cpld-gpio", .data = SL28CPLD_GPIO},
|
||||
{ .compatible = "kontron,sl28cpld-gpo", .data = SL28CPLD_GPO},
|
||||
{ .compatible = "kontron,sl28cpld-gpi", .data = SL28CPLD_GPI},
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sl28cpld_gpio) = {
|
||||
.name = "sl28cpld_gpio",
|
||||
.id = UCLASS_GPIO,
|
||||
.of_match = sl28cpld_gpio_ids,
|
||||
.probe = sl28cpld_gpio_probe,
|
||||
.ops = &sl28cpld_gpio_ops,
|
||||
};
|
@ -512,4 +512,12 @@ config ESM_PMIC
|
||||
config FSL_IFC
|
||||
bool
|
||||
|
||||
config SL28CPLD
|
||||
bool "Enable Kontron sl28cpld multi-function driver"
|
||||
depends on DM_I2C
|
||||
help
|
||||
Support for the Kontron sl28cpld management controller. This is
|
||||
the base driver which provides common access methods for the
|
||||
sub-drivers.
|
||||
|
||||
endmenu
|
||||
|
@ -82,3 +82,4 @@ obj-$(CONFIG_MICROCHIP_FLEXCOM) += microchip_flexcom.o
|
||||
obj-$(CONFIG_K3_AVS0) += k3_avs.o
|
||||
obj-$(CONFIG_ESM_K3) += k3_esm.o
|
||||
obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
|
||||
obj-$(CONFIG_SL28CPLD) += sl28cpld.o
|
||||
|
105
drivers/misc/sl28cpld.c
Normal file
105
drivers/misc/sl28cpld.c
Normal file
@ -0,0 +1,105 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2021 Michael Walle <michael@walle.cc>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
|
||||
struct sl28cpld_child_plat {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* The access methods works either with the first argument being a child
|
||||
* device or with the MFD device itself.
|
||||
*/
|
||||
static int sl28cpld_read_child(struct udevice *dev, uint offset)
|
||||
{
|
||||
struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev);
|
||||
struct udevice *mfd = dev_get_parent(dev);
|
||||
|
||||
return dm_i2c_reg_read(mfd, offset + plat->offset);
|
||||
}
|
||||
|
||||
int sl28cpld_read(struct udevice *dev, uint offset)
|
||||
{
|
||||
if (dev->driver == DM_DRIVER_GET(sl28cpld))
|
||||
return dm_i2c_reg_read(dev, offset);
|
||||
else
|
||||
return sl28cpld_read_child(dev, offset);
|
||||
}
|
||||
|
||||
static int sl28cpld_write_child(struct udevice *dev, uint offset,
|
||||
uint8_t value)
|
||||
{
|
||||
struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev);
|
||||
struct udevice *mfd = dev_get_parent(dev);
|
||||
|
||||
return dm_i2c_reg_write(mfd, offset + plat->offset, value);
|
||||
}
|
||||
|
||||
int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value)
|
||||
{
|
||||
if (dev->driver == DM_DRIVER_GET(sl28cpld))
|
||||
return dm_i2c_reg_write(dev, offset, value);
|
||||
else
|
||||
return sl28cpld_write_child(dev, offset, value);
|
||||
}
|
||||
|
||||
int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear,
|
||||
uint8_t set)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = sl28cpld_read(dev, offset);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
|
||||
return sl28cpld_write(dev, offset, val);
|
||||
}
|
||||
|
||||
static int sl28cpld_probe(struct udevice *dev)
|
||||
{
|
||||
i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
|
||||
DM_I2C_CHIP_WR_ADDRESS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sl28cpld_child_post_bind(struct udevice *dev)
|
||||
{
|
||||
struct sl28cpld_child_plat *plat = dev_get_parent_plat(dev);
|
||||
int offset;
|
||||
|
||||
if (!dev_has_ofnode(dev))
|
||||
return 0;
|
||||
|
||||
offset = dev_read_u32_default(dev, "reg", -1);
|
||||
if (offset == -1)
|
||||
return -EINVAL;
|
||||
|
||||
plat->offset = offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id sl28cpld_ids[] = {
|
||||
{ .compatible = "kontron,sl28cpld" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sl28cpld) = {
|
||||
.name = "sl28cpld",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = sl28cpld_ids,
|
||||
.probe = sl28cpld_probe,
|
||||
.bind = dm_scan_fdt_dev,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
.per_child_plat_auto = sizeof(struct sl28cpld_child_plat),
|
||||
.child_post_bind = sl28cpld_child_post_bind,
|
||||
};
|
@ -90,9 +90,33 @@ struct rockchip_sdhc {
|
||||
};
|
||||
|
||||
struct sdhci_data {
|
||||
int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
|
||||
int (*emmc_phy_init)(struct udevice *dev);
|
||||
int (*get_phy)(struct udevice *dev);
|
||||
|
||||
/**
|
||||
* set_control_reg() - Set SDHCI control registers
|
||||
*
|
||||
* This is the set_control_reg() SDHCI operation that should be
|
||||
* used for the hardware this driver data is associated with.
|
||||
* Normally, this is used to set up control registers for
|
||||
* voltage level and UHS speed mode.
|
||||
*
|
||||
* @host: SDHCI host structure
|
||||
*/
|
||||
void (*set_control_reg)(struct sdhci_host *host);
|
||||
|
||||
/**
|
||||
* set_ios_post() - Host specific hook after set_ios() calls
|
||||
*
|
||||
* This is the set_ios_post() SDHCI operation that should be
|
||||
* used for the hardware this driver data is associated with.
|
||||
* Normally, this is a hook that is called after sdhci_set_ios()
|
||||
* that does any necessary host-specific configuration.
|
||||
*
|
||||
* @host: SDHCI host structure
|
||||
* Return: 0 if successful, -ve on error
|
||||
*/
|
||||
int (*set_ios_post)(struct sdhci_host *host);
|
||||
};
|
||||
|
||||
static int rk3399_emmc_phy_init(struct udevice *dev)
|
||||
@ -182,15 +206,28 @@ static int rk3399_emmc_get_phy(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
static void rk3399_sdhci_set_control_reg(struct sdhci_host *host)
|
||||
{
|
||||
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
|
||||
struct mmc *mmc = host->mmc;
|
||||
uint clock = mmc->tran_speed;
|
||||
int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ;
|
||||
|
||||
if (cycle_phy)
|
||||
rk3399_emmc_phy_power_off(priv->phy);
|
||||
|
||||
sdhci_set_clock(host->mmc, clock);
|
||||
sdhci_set_control_reg(host);
|
||||
};
|
||||
|
||||
static int rk3399_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
{
|
||||
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
|
||||
struct mmc *mmc = host->mmc;
|
||||
uint clock = mmc->tran_speed;
|
||||
int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ;
|
||||
|
||||
if (!clock)
|
||||
clock = mmc->clock;
|
||||
|
||||
if (cycle_phy)
|
||||
rk3399_emmc_phy_power_on(priv->phy, clock);
|
||||
@ -269,10 +306,8 @@ static int rk3568_emmc_get_phy(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
{
|
||||
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
|
||||
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
|
||||
struct mmc *mmc = host->mmc;
|
||||
uint clock = mmc->tran_speed;
|
||||
u32 reg;
|
||||
@ -280,8 +315,7 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
if (!clock)
|
||||
clock = mmc->clock;
|
||||
|
||||
if (data->emmc_set_clock)
|
||||
data->emmc_set_clock(host, clock);
|
||||
rk3568_sdhci_emmc_set_clock(host, clock);
|
||||
|
||||
if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
|
||||
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
|
||||
@ -295,6 +329,26 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_sdhci_set_control_reg(struct sdhci_host *host)
|
||||
{
|
||||
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
|
||||
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
|
||||
|
||||
if (data->set_control_reg)
|
||||
data->set_control_reg(host);
|
||||
}
|
||||
|
||||
static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
|
||||
{
|
||||
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
|
||||
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
|
||||
|
||||
if (data->set_ios_post)
|
||||
return data->set_ios_post(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
||||
{
|
||||
struct sdhci_host *host = dev_get_priv(mmc->dev);
|
||||
@ -358,6 +412,7 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
|
||||
static struct sdhci_ops rockchip_sdhci_ops = {
|
||||
.set_ios_post = rockchip_sdhci_set_ios_post,
|
||||
.platform_execute_tuning = &rockchip_sdhci_execute_tuning,
|
||||
.set_control_reg = rockchip_sdhci_set_control_reg,
|
||||
};
|
||||
|
||||
static int rockchip_sdhci_probe(struct udevice *dev)
|
||||
@ -436,15 +491,16 @@ static int rockchip_sdhci_bind(struct udevice *dev)
|
||||
}
|
||||
|
||||
static const struct sdhci_data rk3399_data = {
|
||||
.emmc_set_clock = rk3399_sdhci_emmc_set_clock,
|
||||
.get_phy = rk3399_emmc_get_phy,
|
||||
.emmc_phy_init = rk3399_emmc_phy_init,
|
||||
.set_control_reg = rk3399_sdhci_set_control_reg,
|
||||
.set_ios_post = rk3399_sdhci_set_ios_post,
|
||||
};
|
||||
|
||||
static const struct sdhci_data rk3568_data = {
|
||||
.emmc_set_clock = rk3568_sdhci_emmc_set_clock,
|
||||
.get_phy = rk3568_emmc_get_phy,
|
||||
.emmc_phy_init = rk3568_emmc_phy_init,
|
||||
.set_ios_post = rk3568_sdhci_set_ios_post,
|
||||
};
|
||||
|
||||
static const struct udevice_id sdhci_ids[] = {
|
||||
|
@ -119,7 +119,7 @@ const struct flash_info spi_nor_ids[] = {
|
||||
},
|
||||
{
|
||||
INFO("gd25lq128", 0xc86018, 0, 64 * 1024, 256,
|
||||
SECT_4K | SPI_NOR_DUAL_READ |
|
||||
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
|
||||
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
|
||||
},
|
||||
{
|
||||
|
@ -30,37 +30,25 @@
|
||||
#include <linux/sizes.h>
|
||||
|
||||
/* PCIe unit register offsets */
|
||||
#define SELECT(x, n) ((x >> n) & 1UL)
|
||||
|
||||
#define PCIE_DEV_ID_OFF 0x0000
|
||||
#define PCIE_CMD_OFF 0x0004
|
||||
#define PCIE_DEV_REV_OFF 0x0008
|
||||
#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3))
|
||||
#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3))
|
||||
#define PCIE_EXP_ROM_BAR_OFF 0x0030
|
||||
#define PCIE_CAPAB_OFF 0x0060
|
||||
#define PCIE_CTRL_STAT_OFF 0x0068
|
||||
#define PCIE_HEADER_LOG_4_OFF 0x0128
|
||||
#define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4))
|
||||
#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4))
|
||||
#define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4))
|
||||
#define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4))
|
||||
#define PCIE_WIN5_CTRL_OFF 0x1880
|
||||
#define PCIE_WIN5_BASE_OFF 0x1884
|
||||
#define PCIE_WIN5_REMAP_OFF 0x188c
|
||||
#define PCIE_CONF_ADDR_OFF 0x18f8
|
||||
#define PCIE_CONF_DATA_OFF 0x18fc
|
||||
#define PCIE_MASK_OFF 0x1910
|
||||
#define PCIE_MASK_ENABLE_INTS (0xf << 24)
|
||||
#define PCIE_CTRL_OFF 0x1a00
|
||||
#define PCIE_CTRL_X1_MODE BIT(0)
|
||||
#define PCIE_CTRL_RC_MODE BIT(1)
|
||||
#define PCIE_STAT_OFF 0x1a04
|
||||
#define PCIE_STAT_BUS (0xff << 8)
|
||||
#define PCIE_STAT_DEV (0x1f << 16)
|
||||
#define PCIE_STAT_LINK_DOWN BIT(0)
|
||||
#define PCIE_DEBUG_CTRL 0x1a60
|
||||
#define PCIE_DEBUG_SOFT_RESET BIT(20)
|
||||
#define MVPCIE_ROOT_PORT_PCI_CFG_OFF 0x0000
|
||||
#define MVPCIE_ROOT_PORT_PCI_EXP_OFF 0x0060
|
||||
#define MVPCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3))
|
||||
#define MVPCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3))
|
||||
#define MVPCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4))
|
||||
#define MVPCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4))
|
||||
#define MVPCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4))
|
||||
#define MVPCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4))
|
||||
#define MVPCIE_WIN5_CTRL_OFF 0x1880
|
||||
#define MVPCIE_WIN5_BASE_OFF 0x1884
|
||||
#define MVPCIE_WIN5_REMAP_OFF 0x188c
|
||||
#define MVPCIE_CONF_ADDR_OFF 0x18f8
|
||||
#define MVPCIE_CONF_DATA_OFF 0x18fc
|
||||
#define MVPCIE_CTRL_OFF 0x1a00
|
||||
#define MVPCIE_CTRL_RC_MODE BIT(1)
|
||||
#define MVPCIE_STAT_OFF 0x1a04
|
||||
#define MVPCIE_STAT_BUS (0xff << 8)
|
||||
#define MVPCIE_STAT_DEV (0x1f << 16)
|
||||
#define MVPCIE_STAT_LINK_DOWN BIT(0)
|
||||
|
||||
#define LINK_WAIT_RETRIES 100
|
||||
#define LINK_WAIT_TIMEOUT 1000
|
||||
@ -77,7 +65,6 @@ struct mvebu_pcie {
|
||||
u32 lane;
|
||||
bool is_x4;
|
||||
int devfn;
|
||||
u32 lane_mask;
|
||||
int sec_busno;
|
||||
char name[16];
|
||||
unsigned int mem_target;
|
||||
@ -90,8 +77,8 @@ struct mvebu_pcie {
|
||||
static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
|
||||
{
|
||||
u32 val;
|
||||
val = readl(pcie->base + PCIE_STAT_OFF);
|
||||
return !(val & PCIE_STAT_LINK_DOWN);
|
||||
val = readl(pcie->base + MVPCIE_STAT_OFF);
|
||||
return !(val & MVPCIE_STAT_LINK_DOWN);
|
||||
}
|
||||
|
||||
static void mvebu_pcie_wait_for_link(struct mvebu_pcie *pcie)
|
||||
@ -115,20 +102,20 @@ static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie *pcie, int busno)
|
||||
{
|
||||
u32 stat;
|
||||
|
||||
stat = readl(pcie->base + PCIE_STAT_OFF);
|
||||
stat &= ~PCIE_STAT_BUS;
|
||||
stat = readl(pcie->base + MVPCIE_STAT_OFF);
|
||||
stat &= ~MVPCIE_STAT_BUS;
|
||||
stat |= busno << 8;
|
||||
writel(stat, pcie->base + PCIE_STAT_OFF);
|
||||
writel(stat, pcie->base + MVPCIE_STAT_OFF);
|
||||
}
|
||||
|
||||
static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int devno)
|
||||
{
|
||||
u32 stat;
|
||||
|
||||
stat = readl(pcie->base + PCIE_STAT_OFF);
|
||||
stat &= ~PCIE_STAT_DEV;
|
||||
stat = readl(pcie->base + MVPCIE_STAT_OFF);
|
||||
stat &= ~MVPCIE_STAT_DEV;
|
||||
stat |= devno << 16;
|
||||
writel(stat, pcie->base + PCIE_STAT_OFF);
|
||||
writel(stat, pcie->base + MVPCIE_STAT_OFF);
|
||||
}
|
||||
|
||||
static inline struct mvebu_pcie *hose_to_pcie(struct pci_controller *hose)
|
||||
@ -198,18 +185,18 @@ static int mvebu_pcie_read_config(const struct udevice *bus, pci_dev_t bdf,
|
||||
addr = PCI_CONF1_EXT_ADDRESS(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset);
|
||||
|
||||
/* write address */
|
||||
writel(addr, pcie->base + PCIE_CONF_ADDR_OFF);
|
||||
writel(addr, pcie->base + MVPCIE_CONF_ADDR_OFF);
|
||||
|
||||
/* read data */
|
||||
switch (size) {
|
||||
case PCI_SIZE_8:
|
||||
data = readb(pcie->base + PCIE_CONF_DATA_OFF + (offset & 3));
|
||||
data = readb(pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 3));
|
||||
break;
|
||||
case PCI_SIZE_16:
|
||||
data = readw(pcie->base + PCIE_CONF_DATA_OFF + (offset & 2));
|
||||
data = readw(pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 2));
|
||||
break;
|
||||
case PCI_SIZE_32:
|
||||
data = readl(pcie->base + PCIE_CONF_DATA_OFF);
|
||||
data = readl(pcie->base + MVPCIE_CONF_DATA_OFF);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -289,18 +276,18 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf,
|
||||
addr = PCI_CONF1_EXT_ADDRESS(busno, PCI_DEV(bdf), PCI_FUNC(bdf), offset);
|
||||
|
||||
/* write address */
|
||||
writel(addr, pcie->base + PCIE_CONF_ADDR_OFF);
|
||||
writel(addr, pcie->base + MVPCIE_CONF_ADDR_OFF);
|
||||
|
||||
/* write data */
|
||||
switch (size) {
|
||||
case PCI_SIZE_8:
|
||||
writeb(value, pcie->base + PCIE_CONF_DATA_OFF + (offset & 3));
|
||||
writeb(value, pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 3));
|
||||
break;
|
||||
case PCI_SIZE_16:
|
||||
writew(value, pcie->base + PCIE_CONF_DATA_OFF + (offset & 2));
|
||||
writew(value, pcie->base + MVPCIE_CONF_DATA_OFF + (offset & 2));
|
||||
break;
|
||||
case PCI_SIZE_32:
|
||||
writel(value, pcie->base + PCIE_CONF_DATA_OFF);
|
||||
writel(value, pcie->base + MVPCIE_CONF_DATA_OFF);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -324,20 +311,20 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
|
||||
|
||||
/* First, disable and clear BARs and windows. */
|
||||
for (i = 1; i < 3; i++) {
|
||||
writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i));
|
||||
writel(0, pcie->base + PCIE_BAR_LO_OFF(i));
|
||||
writel(0, pcie->base + PCIE_BAR_HI_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_BAR_CTRL_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_BAR_LO_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_BAR_HI_OFF(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i));
|
||||
writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i));
|
||||
writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_WIN04_CTRL_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_WIN04_BASE_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_WIN04_REMAP_OFF(i));
|
||||
}
|
||||
|
||||
writel(0, pcie->base + PCIE_WIN5_CTRL_OFF);
|
||||
writel(0, pcie->base + PCIE_WIN5_BASE_OFF);
|
||||
writel(0, pcie->base + PCIE_WIN5_REMAP_OFF);
|
||||
writel(0, pcie->base + MVPCIE_WIN5_CTRL_OFF);
|
||||
writel(0, pcie->base + MVPCIE_WIN5_BASE_OFF);
|
||||
writel(0, pcie->base + MVPCIE_WIN5_REMAP_OFF);
|
||||
|
||||
/* Setup windows for DDR banks. Count total DDR size on the fly. */
|
||||
size = 0;
|
||||
@ -345,12 +332,12 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
|
||||
const struct mbus_dram_window *cs = dram->cs + i;
|
||||
|
||||
writel(cs->base & 0xffff0000,
|
||||
pcie->base + PCIE_WIN04_BASE_OFF(i));
|
||||
writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
|
||||
pcie->base + MVPCIE_WIN04_BASE_OFF(i));
|
||||
writel(0, pcie->base + MVPCIE_WIN04_REMAP_OFF(i));
|
||||
writel(((cs->size - 1) & 0xffff0000) |
|
||||
(cs->mbus_attr << 8) |
|
||||
(dram->mbus_dram_target_id << 4) | 1,
|
||||
pcie->base + PCIE_WIN04_CTRL_OFF(i));
|
||||
pcie->base + MVPCIE_WIN04_CTRL_OFF(i));
|
||||
|
||||
size += cs->size;
|
||||
}
|
||||
@ -360,14 +347,14 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
|
||||
size = 1 << fls(size);
|
||||
|
||||
/* Setup BAR[1] to all DRAM banks. */
|
||||
writel(dram->cs[0].base | 0xc, pcie->base + PCIE_BAR_LO_OFF(1));
|
||||
writel(0, pcie->base + PCIE_BAR_HI_OFF(1));
|
||||
writel(dram->cs[0].base | 0xc, pcie->base + MVPCIE_BAR_LO_OFF(1));
|
||||
writel(0, pcie->base + MVPCIE_BAR_HI_OFF(1));
|
||||
writel(((size - 1) & 0xffff0000) | 0x1,
|
||||
pcie->base + PCIE_BAR_CTRL_OFF(1));
|
||||
pcie->base + MVPCIE_BAR_CTRL_OFF(1));
|
||||
|
||||
/* Setup BAR[0] to internal registers. */
|
||||
writel(pcie->intregs, pcie->base + PCIE_BAR_LO_OFF(0));
|
||||
writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
|
||||
writel(pcie->intregs, pcie->base + MVPCIE_BAR_LO_OFF(0));
|
||||
writel(0, pcie->base + MVPCIE_BAR_HI_OFF(0));
|
||||
}
|
||||
|
||||
/* Only enable PCIe link, do not setup it */
|
||||
@ -406,9 +393,9 @@ static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie)
|
||||
u32 reg;
|
||||
|
||||
/* Setup PCIe controller to Root Complex mode */
|
||||
reg = readl(pcie->base + PCIE_CTRL_OFF);
|
||||
reg |= PCIE_CTRL_RC_MODE;
|
||||
writel(reg, pcie->base + PCIE_CTRL_OFF);
|
||||
reg = readl(pcie->base + MVPCIE_CTRL_OFF);
|
||||
reg |= MVPCIE_CTRL_RC_MODE;
|
||||
writel(reg, pcie->base + MVPCIE_CTRL_OFF);
|
||||
|
||||
/*
|
||||
* Set Maximum Link Width to X1 or X4 in Root Port's PCIe Link
|
||||
@ -417,10 +404,10 @@ static void mvebu_pcie_setup_link(struct mvebu_pcie *pcie)
|
||||
* be set to number of SerDes PCIe lanes (1 or 4). If this register is
|
||||
* not set correctly then link with endpoint card is not established.
|
||||
*/
|
||||
reg = readl(pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
|
||||
reg = readl(pcie->base + MVPCIE_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_LNKCAP);
|
||||
reg &= ~PCI_EXP_LNKCAP_MLW;
|
||||
reg |= (pcie->is_x4 ? 4 : 1) << 4;
|
||||
writel(reg, pcie->base + PCIE_CAPAB_OFF + PCI_EXP_LNKCAP);
|
||||
writel(reg, pcie->base + MVPCIE_ROOT_PORT_PCI_EXP_OFF + PCI_EXP_LNKCAP);
|
||||
}
|
||||
|
||||
static int mvebu_pcie_probe(struct udevice *dev)
|
||||
@ -443,7 +430,7 @@ static int mvebu_pcie_probe(struct udevice *dev)
|
||||
* have the same format in Marvell's specification as in PCIe
|
||||
* specification, but their meaning is totally different and they do
|
||||
* different things: they are aliased into internal mvebu registers
|
||||
* (e.g. PCIE_BAR_LO_OFF) and these should not be changed or
|
||||
* (e.g. MVPCIE_BAR_LO_OFF) and these should not be changed or
|
||||
* reconfigured by pci device drivers.
|
||||
*
|
||||
* So our driver converts Type 0 config space to Type 1 and reports
|
||||
@ -451,10 +438,10 @@ static int mvebu_pcie_probe(struct udevice *dev)
|
||||
* Type 1 registers is redirected to the virtual cfgcache[] buffer,
|
||||
* which avoids changing unrelated registers.
|
||||
*/
|
||||
reg = readl(pcie->base + PCIE_DEV_REV_OFF);
|
||||
reg = readl(pcie->base + MVPCIE_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION);
|
||||
reg &= ~0xffffff00;
|
||||
reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
|
||||
writel(reg, pcie->base + PCIE_DEV_REV_OFF);
|
||||
writel(reg, pcie->base + MVPCIE_ROOT_PORT_PCI_CFG_OFF + PCI_CLASS_REVISION);
|
||||
|
||||
/*
|
||||
* mvebu uses local bus number and local device number to determinate
|
||||
|
@ -358,26 +358,10 @@ static inline int cdns_reset_deassert(struct reset_control *rst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct cdns_sierra_inst *phy_get_drvdata(struct phy *phy)
|
||||
static int cdns_sierra_link_init(struct phy *gphy)
|
||||
{
|
||||
struct cdns_sierra_phy *sp = dev_get_priv(phy->dev);
|
||||
int index;
|
||||
|
||||
if (phy->id >= SIERRA_MAX_LANES)
|
||||
return NULL;
|
||||
|
||||
for (index = 0; index < sp->nsubnodes; index++) {
|
||||
if (phy->id == sp->phys[index]->mlane)
|
||||
return sp->phys[index];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cdns_sierra_phy_init(struct phy *gphy)
|
||||
{
|
||||
struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
|
||||
struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev);
|
||||
struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev);
|
||||
struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev->parent);
|
||||
struct cdns_sierra_data *init_data = phy->init_data;
|
||||
struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals;
|
||||
enum cdns_sierra_phy_type phy_type = ins->phy_type;
|
||||
@ -443,10 +427,11 @@ static int cdns_sierra_phy_init(struct phy *gphy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdns_sierra_phy_on(struct phy *gphy)
|
||||
static int cdns_sierra_link_on(struct phy *gphy)
|
||||
{
|
||||
struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
|
||||
struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev);
|
||||
struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev);
|
||||
struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent);
|
||||
|
||||
struct udevice *dev = gphy->dev;
|
||||
u32 val;
|
||||
int ret;
|
||||
@ -503,16 +488,16 @@ static int cdns_sierra_phy_on(struct phy *gphy)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cdns_sierra_phy_off(struct phy *gphy)
|
||||
static int cdns_sierra_link_off(struct phy *gphy)
|
||||
{
|
||||
struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
|
||||
struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev);
|
||||
|
||||
return reset_assert_bulk(ins->lnk_rst);
|
||||
}
|
||||
|
||||
static int cdns_sierra_phy_reset(struct phy *gphy)
|
||||
static int cdns_sierra_link_reset(struct phy *gphy)
|
||||
{
|
||||
struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev);
|
||||
struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent);
|
||||
|
||||
reset_control_assert(sp->phy_rst);
|
||||
reset_control_deassert(sp->phy_rst);
|
||||
@ -520,10 +505,10 @@ static int cdns_sierra_phy_reset(struct phy *gphy)
|
||||
};
|
||||
|
||||
static const struct phy_ops ops = {
|
||||
.init = cdns_sierra_phy_init,
|
||||
.power_on = cdns_sierra_phy_on,
|
||||
.power_off = cdns_sierra_phy_off,
|
||||
.reset = cdns_sierra_phy_reset,
|
||||
.init = cdns_sierra_link_init,
|
||||
.power_on = cdns_sierra_link_on,
|
||||
.power_off = cdns_sierra_link_off,
|
||||
.reset = cdns_sierra_link_reset,
|
||||
};
|
||||
|
||||
struct cdns_sierra_pll_mux_sel {
|
||||
@ -580,7 +565,7 @@ static const struct clk_ops cdns_sierra_pll_mux_ops = {
|
||||
.set_parent = cdns_sierra_pll_mux_set_parent,
|
||||
};
|
||||
|
||||
int cdns_sierra_pll_mux_probe(struct udevice *dev)
|
||||
static int cdns_sierra_pll_mux_probe(struct udevice *dev)
|
||||
{
|
||||
struct cdns_sierra_pll_mux *priv = dev_get_priv(dev);
|
||||
struct cdns_sierra_phy *sp = dev_get_priv(dev->parent);
|
||||
@ -1012,9 +997,8 @@ static int cdns_sierra_phy_get_resets(struct cdns_sierra_phy *sp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cdns_sierra_bind_link_nodes(struct cdns_sierra_phy *sp)
|
||||
static int cdns_sierra_phy_bind(struct udevice *dev)
|
||||
{
|
||||
struct udevice *dev = sp->dev;
|
||||
struct driver *link_drv;
|
||||
ofnode child;
|
||||
int rc;
|
||||
@ -1079,6 +1063,7 @@ U_BOOT_DRIVER(sierra_phy_link) = {
|
||||
.name = "sierra_phy_link",
|
||||
.id = UCLASS_PHY,
|
||||
.probe = cdns_sierra_link_probe,
|
||||
.ops = &ops,
|
||||
.priv_auto = sizeof(struct cdns_sierra_inst),
|
||||
};
|
||||
|
||||
@ -1141,10 +1126,6 @@ static int cdns_sierra_phy_probe(struct udevice *dev)
|
||||
}
|
||||
|
||||
sp->autoconf = dev_read_bool(dev, "cdns,autoconf");
|
||||
/* Binding link nodes as children to serdes */
|
||||
ret = cdns_sierra_bind_link_nodes(sp);
|
||||
if (ret)
|
||||
goto clk_disable;
|
||||
|
||||
dev_info(dev, "sierra probed\n");
|
||||
return 0;
|
||||
@ -1971,10 +1952,10 @@ static const struct udevice_id cdns_sierra_id_table[] = {
|
||||
|
||||
U_BOOT_DRIVER(sierra_phy_provider) = {
|
||||
.name = "cdns,sierra",
|
||||
.id = UCLASS_PHY,
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = cdns_sierra_id_table,
|
||||
.probe = cdns_sierra_phy_probe,
|
||||
.remove = cdns_sierra_phy_remove,
|
||||
.ops = &ops,
|
||||
.bind = cdns_sierra_phy_bind,
|
||||
.priv_auto = sizeof(struct cdns_sierra_phy),
|
||||
};
|
||||
|
@ -45,12 +45,14 @@ static int nop_phy_init(struct phy *phy)
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_GPIO)
|
||||
/* Take phy out of reset */
|
||||
if (dm_gpio_is_valid(&priv->reset_gpio)) {
|
||||
ret = dm_gpio_set_value(&priv->reset_gpio, false);
|
||||
if (ret) {
|
||||
if (CONFIG_IS_ENABLED(CLK))
|
||||
clk_disable_bulk(&priv->bulk);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,11 +162,11 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
||||
PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"),
|
||||
PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3),
|
||||
"pwm", "led"),
|
||||
PIN_GRP_GPIO_3("pwm1", 11, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4),
|
||||
PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4),
|
||||
"pwm", "led"),
|
||||
PIN_GRP_GPIO_3("pwm2", 11, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5),
|
||||
PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5),
|
||||
"pwm", "led"),
|
||||
PIN_GRP_GPIO_3("pwm3", 11, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6),
|
||||
PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6),
|
||||
"pwm", "led"),
|
||||
PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
|
||||
PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
|
||||
|
@ -121,7 +121,7 @@ static int armada38x_rtc_reset(struct udevice *dev)
|
||||
armada38x_rtc_write(0, rtc, RTC_CONF_TEST);
|
||||
mdelay(500);
|
||||
armada38x_rtc_write(0, rtc, RTC_TIME);
|
||||
armada38x_rtc_write(BIT(0) | BIT(1), 0, RTC_STATUS);
|
||||
armada38x_rtc_write(BIT(0) | BIT(1), rtc, RTC_STATUS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -66,7 +66,8 @@ static int serial_check_stdout(const void *blob, struct udevice **devp)
|
||||
*/
|
||||
if (node > 0 && !lists_bind_fdt(gd->dm_root, offset_to_ofnode(node),
|
||||
devp, NULL, false)) {
|
||||
if (!device_probe(*devp))
|
||||
if (device_get_uclass_id(*devp) == UCLASS_SERIAL &&
|
||||
!device_probe(*devp))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,12 @@ config ICH_SPI
|
||||
access the SPI NOR flash on platforms embedding this Intel
|
||||
ICH IP core.
|
||||
|
||||
config IPROC_QSPI
|
||||
bool "Broadcom iProc QSPI Flash Controller driver"
|
||||
help
|
||||
Enable Broadcom iProc QSPI Flash Controller driver.
|
||||
This driver can be used to access the SPI NOR flash.
|
||||
|
||||
config KIRKWOOD_SPI
|
||||
bool "Marvell Kirkwood SPI Driver"
|
||||
help
|
||||
|
@ -34,6 +34,7 @@ obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
|
||||
obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
|
||||
obj-$(CONFIG_SYNQUACER_SPI) += spi-synquacer.o
|
||||
obj-$(CONFIG_ICH_SPI) += ich.o
|
||||
obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o
|
||||
obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
|
||||
obj-$(CONFIG_MESON_SPIFC) += meson_spifc.o
|
||||
obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
|
||||
|
@ -201,11 +201,9 @@ static int cadence_spi_probe(struct udevice *bus)
|
||||
}
|
||||
}
|
||||
|
||||
ret = reset_get_bulk(bus, &priv->resets);
|
||||
if (ret)
|
||||
dev_warn(bus, "Can't get reset: %d\n", ret);
|
||||
else
|
||||
reset_deassert_bulk(&priv->resets);
|
||||
priv->resets = devm_reset_bulk_get_optional(bus);
|
||||
if (priv->resets)
|
||||
reset_deassert_bulk(priv->resets);
|
||||
|
||||
if (!priv->qspi_is_init) {
|
||||
cadence_qspi_apb_controller_init(plat);
|
||||
@ -220,8 +218,12 @@ static int cadence_spi_probe(struct udevice *bus)
|
||||
static int cadence_spi_remove(struct udevice *dev)
|
||||
{
|
||||
struct cadence_spi_priv *priv = dev_get_priv(dev);
|
||||
int ret = 0;
|
||||
|
||||
return reset_release_bulk(&priv->resets);
|
||||
if (priv->resets)
|
||||
ret = reset_release_bulk(priv->resets);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cadence_spi_set_mode(struct udevice *bus, uint mode)
|
||||
|
@ -56,7 +56,7 @@ struct cadence_spi_priv {
|
||||
unsigned int qspi_calibrated_cs;
|
||||
unsigned int previous_hz;
|
||||
|
||||
struct reset_ctl_bulk resets;
|
||||
struct reset_ctl_bulk *resets;
|
||||
};
|
||||
|
||||
/* Functions call declaration */
|
||||
|
@ -572,7 +572,7 @@ static int dw_spi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
|
||||
int pos, i, ret = 0;
|
||||
struct udevice *bus = slave->dev->parent;
|
||||
struct dw_spi_priv *priv = dev_get_priv(bus);
|
||||
u8 op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
|
||||
u8 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
|
||||
u8 op_buf[op_len];
|
||||
u32 cr0;
|
||||
|
||||
|
576
drivers/spi/iproc_qspi.c
Normal file
576
drivers/spi/iproc_qspi.c
Normal file
@ -0,0 +1,576 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2020-2021 Broadcom
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <spi.h>
|
||||
#include <spi-mem.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
/* Delay required to change the mode of operation */
|
||||
#define BUSY_DELAY_US 1
|
||||
#define BUSY_TIMEOUT_US 200000
|
||||
#define DWORD_ALIGNED(a) (!(((ulong)(a)) & 3))
|
||||
|
||||
/* Chip attributes */
|
||||
#define QSPI_AXI_CLK 175000000
|
||||
#define SPBR_MIN 8U
|
||||
#define SPBR_MAX 255U
|
||||
#define NUM_CDRAM 16U
|
||||
|
||||
#define CDRAM_PCS0 2
|
||||
#define CDRAM_CONT BIT(7)
|
||||
#define CDRAM_BITS_EN BIT(6)
|
||||
#define CDRAM_QUAD_MODE BIT(8)
|
||||
#define CDRAM_RBIT_INPUT BIT(10)
|
||||
#define MSPI_SPE BIT(6)
|
||||
#define MSPI_CONT_AFTER_CMD BIT(7)
|
||||
#define MSPI_MSTR BIT(7)
|
||||
|
||||
/* Register fields */
|
||||
#define MSPI_SPCR0_MSB_BITS_8 0x00000020
|
||||
#define BSPI_RAF_CONTROL_START_MASK 0x00000001
|
||||
#define BSPI_RAF_STATUS_SESSION_BUSY_MASK 0x00000001
|
||||
#define BSPI_RAF_STATUS_FIFO_EMPTY_MASK 0x00000002
|
||||
#define BSPI_STRAP_OVERRIDE_DATA_QUAD_SHIFT 3
|
||||
#define BSPI_STRAP_OVERRIDE_4BYTE_SHIFT 2
|
||||
#define BSPI_STRAP_OVERRIDE_DATA_DUAL_SHIFT 1
|
||||
#define BSPI_STRAP_OVERRIDE_SHIFT 0
|
||||
#define BSPI_BPC_DATA_SHIFT 0
|
||||
#define BSPI_BPC_MODE_SHIFT 8
|
||||
#define BSPI_BPC_ADDR_SHIFT 16
|
||||
#define BSPI_BPC_CMD_SHIFT 24
|
||||
#define BSPI_BPP_ADDR_SHIFT 16
|
||||
|
||||
/* MSPI registers */
|
||||
#define MSPI_SPCR0_LSB_REG 0x000
|
||||
#define MSPI_SPCR0_MSB_REG 0x004
|
||||
#define MSPI_SPCR1_LSB_REG 0x008
|
||||
#define MSPI_SPCR1_MSB_REG 0x00c
|
||||
#define MSPI_NEWQP_REG 0x010
|
||||
#define MSPI_ENDQP_REG 0x014
|
||||
#define MSPI_SPCR2_REG 0x018
|
||||
#define MSPI_STATUS_REG 0x020
|
||||
#define MSPI_CPTQP_REG 0x024
|
||||
#define MSPI_TX_REG 0x040
|
||||
#define MSPI_RX_REG 0x0c0
|
||||
#define MSPI_CDRAM_REG 0x140
|
||||
#define MSPI_WRITE_LOCK_REG 0x180
|
||||
#define MSPI_DISABLE_FLUSH_GEN_REG 0x184
|
||||
|
||||
/* BSPI registers */
|
||||
#define BSPI_REVISION_ID_REG 0x000
|
||||
#define BSPI_SCRATCH_REG 0x004
|
||||
#define BSPI_MAST_N_BOOT_CTRL_REG 0x008
|
||||
#define BSPI_BUSY_STATUS_REG 0x00c
|
||||
#define BSPI_INTR_STATUS_REG 0x010
|
||||
#define BSPI_B0_STATUS_REG 0x014
|
||||
#define BSPI_B0_CTRL_REG 0x018
|
||||
#define BSPI_B1_STATUS_REG 0x01c
|
||||
#define BSPI_B1_CTRL_REG 0x020
|
||||
#define BSPI_STRAP_OVERRIDE_CTRL_REG 0x024
|
||||
#define BSPI_FLEX_MODE_ENABLE_REG 0x028
|
||||
#define BSPI_BITS_PER_CYCLE_REG 0x02C
|
||||
#define BSPI_BITS_PER_PHASE_REG 0x030
|
||||
#define BSPI_CMD_AND_MODE_BYTE_REG 0x034
|
||||
#define BSPI_FLASH_UPPER_ADDR_BYTE_REG 0x038
|
||||
#define BSPI_XOR_VALUE_REG 0x03C
|
||||
#define BSPI_XOR_ENABLE_REG 0x040
|
||||
#define BSPI_PIO_MODE_ENABLE_REG 0x044
|
||||
#define BSPI_PIO_IODIR_REG 0x048
|
||||
#define BSPI_PIO_DATA_REG 0x04C
|
||||
|
||||
/* RAF registers */
|
||||
#define BSPI_RAF_START_ADDRESS_REG 0x00
|
||||
#define BSPI_RAF_NUM_WORDS_REG 0x04
|
||||
#define BSPI_RAF_CTRL_REG 0x08
|
||||
#define BSPI_RAF_FULLNESS_REG 0x0C
|
||||
#define BSPI_RAF_WATERMARK_REG 0x10
|
||||
#define BSPI_RAF_STATUS_REG 0x14
|
||||
#define BSPI_RAF_READ_DATA_REG 0x18
|
||||
#define BSPI_RAF_WORD_CNT_REG 0x1C
|
||||
#define BSPI_RAF_CURR_ADDR_REG 0x20
|
||||
|
||||
#define XFER_DUAL BIT(30)
|
||||
#define XFER_QUAD BIT(31)
|
||||
|
||||
#define FLUSH_BIT BIT(0)
|
||||
#define MAST_N_BOOT_BIT BIT(0)
|
||||
#define WRITE_LOCK_BIT BIT(0)
|
||||
|
||||
#define CEIL(m, n) (((m) + (n) - 1) / (n))
|
||||
#define UPPER_BYTE_MASK 0xFF000000
|
||||
#define SIZE_16MB 0x001000000
|
||||
|
||||
/*
|
||||
* struct bcmspi_priv - qspi private structure
|
||||
*
|
||||
* @bspi_addr: bspi read address
|
||||
* @bspi_4byte_addr: bspi 4 byte address mode
|
||||
* @mspi: mspi registers block address
|
||||
* @bspi: bspi registers block address
|
||||
* @bspi_raf: bspi raf registers block address
|
||||
*/
|
||||
struct bcmspi_priv {
|
||||
u32 bspi_addr;
|
||||
bool bspi_4byte_addr;
|
||||
fdt_addr_t mspi;
|
||||
fdt_addr_t bspi;
|
||||
fdt_addr_t bspi_raf;
|
||||
};
|
||||
|
||||
/* BSPI mode */
|
||||
|
||||
static void bspi_flush_prefetch_buffers(struct bcmspi_priv *priv)
|
||||
{
|
||||
writel(0, priv->bspi + BSPI_B0_CTRL_REG);
|
||||
writel(0, priv->bspi + BSPI_B1_CTRL_REG);
|
||||
writel(FLUSH_BIT, priv->bspi + BSPI_B0_CTRL_REG);
|
||||
writel(FLUSH_BIT, priv->bspi + BSPI_B1_CTRL_REG);
|
||||
}
|
||||
|
||||
static int bspi_enable(struct bcmspi_priv *priv)
|
||||
{
|
||||
/* Disable write lock */
|
||||
writel(0, priv->mspi + MSPI_WRITE_LOCK_REG);
|
||||
/* Flush prefetch buffers */
|
||||
bspi_flush_prefetch_buffers(priv);
|
||||
/* Switch to BSPI */
|
||||
writel(0, priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bspi_disable(struct bcmspi_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
uint val;
|
||||
|
||||
if ((readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG) & 1) == 0) {
|
||||
ret = readl_poll_timeout(priv->bspi + BSPI_BUSY_STATUS_REG, val, !(val & 1),
|
||||
BUSY_TIMEOUT_US);
|
||||
if (ret) {
|
||||
printf("%s: Failed to disable bspi, device busy\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Switch to MSPI */
|
||||
writel(MAST_N_BOOT_BIT, priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG);
|
||||
udelay(BUSY_DELAY_US);
|
||||
|
||||
val = readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG);
|
||||
if (!(val & 1)) {
|
||||
printf("%s: Failed to enable mspi\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable write lock */
|
||||
writel(WRITE_LOCK_BIT, priv->mspi + MSPI_WRITE_LOCK_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bspi_read_via_raf(struct bcmspi_priv *priv, u8 *rx, uint bytes)
|
||||
{
|
||||
u32 status;
|
||||
uint words;
|
||||
int aligned;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Flush data from the previous session (unlikely)
|
||||
* Read outstanding bits in the poll condition to empty FIFO
|
||||
*/
|
||||
ret = readl_poll_timeout(priv->bspi_raf + BSPI_RAF_STATUS_REG,
|
||||
status,
|
||||
(!readl(priv->bspi_raf + BSPI_RAF_READ_DATA_REG) &&
|
||||
status & BSPI_RAF_STATUS_FIFO_EMPTY_MASK) &&
|
||||
!(status & BSPI_RAF_STATUS_SESSION_BUSY_MASK),
|
||||
BUSY_TIMEOUT_US);
|
||||
if (ret) {
|
||||
printf("%s: Failed to flush fifo\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Transfer is in words */
|
||||
words = CEIL(bytes, 4);
|
||||
|
||||
/* Setup hardware */
|
||||
if (priv->bspi_4byte_addr) {
|
||||
u32 val = priv->bspi_addr & UPPER_BYTE_MASK;
|
||||
|
||||
if (val != readl(priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG)) {
|
||||
writel(val, priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG);
|
||||
bspi_flush_prefetch_buffers(priv);
|
||||
}
|
||||
}
|
||||
|
||||
writel(priv->bspi_addr & ~UPPER_BYTE_MASK, priv->bspi_raf + BSPI_RAF_START_ADDRESS_REG);
|
||||
writel(words, priv->bspi_raf + BSPI_RAF_NUM_WORDS_REG);
|
||||
writel(0, priv->bspi_raf + BSPI_RAF_WATERMARK_REG);
|
||||
|
||||
/* Start reading */
|
||||
writel(BSPI_RAF_CONTROL_START_MASK, priv->bspi_raf + BSPI_RAF_CTRL_REG);
|
||||
aligned = DWORD_ALIGNED(rx);
|
||||
while (bytes) {
|
||||
status = readl(priv->bspi_raf + BSPI_RAF_STATUS_REG);
|
||||
if (!(status & BSPI_RAF_STATUS_FIFO_EMPTY_MASK)) {
|
||||
/* RAF is LE only, convert data to host endianness */
|
||||
u32 data = le32_to_cpu(readl(priv->bspi_raf + BSPI_RAF_READ_DATA_REG));
|
||||
|
||||
/* Check if we can use the whole word */
|
||||
if (aligned && bytes >= 4) {
|
||||
*(u32 *)rx = data;
|
||||
rx += 4;
|
||||
bytes -= 4;
|
||||
} else {
|
||||
uint chunk = min(bytes, 4U);
|
||||
|
||||
/* Read out bytes one by one */
|
||||
while (chunk) {
|
||||
*rx++ = (u8)data;
|
||||
data >>= 8;
|
||||
chunk--;
|
||||
bytes--;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (!(status & BSPI_RAF_STATUS_SESSION_BUSY_MASK)) {
|
||||
/* FIFO is empty and the session is done */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bspi_read(struct bcmspi_priv *priv, u8 *rx, uint bytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Transfer data */
|
||||
while (bytes > 0) {
|
||||
/* Special handing since RAF cannot go across 16MB boundary */
|
||||
uint trans = bytes;
|
||||
/* Divide into multiple transfers if it goes across the 16MB boundary */
|
||||
if (priv->bspi_4byte_addr && (priv->bspi_addr >> 24) !=
|
||||
((priv->bspi_addr + bytes) >> 24))
|
||||
trans = SIZE_16MB - (priv->bspi_addr & ~UPPER_BYTE_MASK);
|
||||
|
||||
ret = bspi_read_via_raf(priv, rx, trans);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->bspi_addr += trans;
|
||||
rx += trans;
|
||||
bytes -= trans;
|
||||
}
|
||||
|
||||
bspi_flush_prefetch_buffers(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bspi_set_flex_mode(struct bcmspi_priv *priv, const struct spi_mem_op *op)
|
||||
{
|
||||
int bpp = (op->dummy.nbytes * 8) / op->dummy.buswidth;
|
||||
int cmd = op->cmd.opcode;
|
||||
int bpc = ilog2(op->data.buswidth) << BSPI_BPC_DATA_SHIFT |
|
||||
ilog2(op->addr.buswidth) << BSPI_BPC_ADDR_SHIFT |
|
||||
ilog2(op->cmd.buswidth) << BSPI_BPC_CMD_SHIFT;
|
||||
int so = BIT(BSPI_STRAP_OVERRIDE_SHIFT) |
|
||||
(op->data.buswidth > 1) << BSPI_STRAP_OVERRIDE_DATA_DUAL_SHIFT |
|
||||
(op->addr.nbytes > 3) << BSPI_STRAP_OVERRIDE_4BYTE_SHIFT |
|
||||
(op->data.buswidth > 3) << BSPI_STRAP_OVERRIDE_DATA_QUAD_SHIFT;
|
||||
|
||||
/* Disable flex mode first */
|
||||
writel(0, priv->bspi + BSPI_FLEX_MODE_ENABLE_REG);
|
||||
|
||||
/* Configure single, dual or quad mode */
|
||||
writel(bpc, priv->bspi + BSPI_BITS_PER_CYCLE_REG);
|
||||
|
||||
/* Opcode */
|
||||
writel(cmd, priv->bspi + BSPI_CMD_AND_MODE_BYTE_REG);
|
||||
|
||||
/* Count of dummy cycles */
|
||||
writel(bpp, priv->bspi + BSPI_BITS_PER_PHASE_REG);
|
||||
|
||||
/* Enable 4-byte address */
|
||||
if (priv->bspi_4byte_addr) {
|
||||
setbits_le32(priv->bspi + BSPI_BITS_PER_PHASE_REG, BIT(BSPI_BPP_ADDR_SHIFT));
|
||||
} else {
|
||||
clrbits_le32(priv->bspi + BSPI_BITS_PER_PHASE_REG, BIT(BSPI_BPP_ADDR_SHIFT));
|
||||
writel(0, priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG);
|
||||
}
|
||||
|
||||
/* Enable flex mode to take effect */
|
||||
writel(1, priv->bspi + BSPI_FLEX_MODE_ENABLE_REG);
|
||||
|
||||
/* Flush prefetch buffers since 32MB window BSPI could be used */
|
||||
bspi_flush_prefetch_buffers(priv);
|
||||
|
||||
/* Override the strap settings */
|
||||
writel(so, priv->bspi + BSPI_STRAP_OVERRIDE_CTRL_REG);
|
||||
}
|
||||
|
||||
static int bspi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
|
||||
{
|
||||
struct udevice *bus = dev_get_parent(slave->dev);
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
int ret = -ENOTSUPP;
|
||||
|
||||
/* BSPI read */
|
||||
if (op->data.dir == SPI_MEM_DATA_IN &&
|
||||
op->data.nbytes && op->addr.nbytes) {
|
||||
priv->bspi_4byte_addr = (op->addr.nbytes > 3);
|
||||
priv->bspi_addr = op->addr.val;
|
||||
bspi_set_flex_mode(priv, op);
|
||||
ret = bspi_read(priv, op->data.buf.in, op->data.nbytes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct spi_controller_mem_ops bspi_mem_ops = {
|
||||
.exec_op = bspi_exec_op,
|
||||
};
|
||||
|
||||
/* MSPI mode */
|
||||
|
||||
static int mspi_exec(struct bcmspi_priv *priv, uint bytes, const u8 *tx, u8 *rx, ulong flags)
|
||||
{
|
||||
u32 cdr = CDRAM_PCS0 | CDRAM_CONT;
|
||||
bool use_16bits = !(bytes & 1);
|
||||
|
||||
if (flags & XFER_QUAD) {
|
||||
cdr |= CDRAM_QUAD_MODE;
|
||||
|
||||
if (!tx)
|
||||
cdr |= CDRAM_RBIT_INPUT;
|
||||
}
|
||||
|
||||
while (bytes) {
|
||||
uint chunk;
|
||||
uint queues;
|
||||
uint i;
|
||||
uint val;
|
||||
int ret;
|
||||
|
||||
if (use_16bits) {
|
||||
chunk = min(bytes, NUM_CDRAM * 2);
|
||||
queues = (chunk + 1) / 2;
|
||||
bytes -= chunk;
|
||||
|
||||
/* Fill CDRAMs */
|
||||
for (i = 0; i < queues; i++)
|
||||
writel(cdr | CDRAM_BITS_EN, priv->mspi + MSPI_CDRAM_REG + 4 * i);
|
||||
|
||||
/* Fill TXRAMs */
|
||||
for (i = 0; i < chunk; i++)
|
||||
writel(tx ? tx[i] : 0xff, priv->mspi + MSPI_TX_REG + 4 * i);
|
||||
} else {
|
||||
/* Determine how many bytes to process this time */
|
||||
chunk = min(bytes, NUM_CDRAM);
|
||||
queues = chunk;
|
||||
bytes -= chunk;
|
||||
|
||||
/* Fill CDRAMs and TXRAMS */
|
||||
for (i = 0; i < chunk; i++) {
|
||||
writel(cdr, priv->mspi + MSPI_CDRAM_REG + 4 * i);
|
||||
writel(tx ? tx[i] : 0xff, priv->mspi + MSPI_TX_REG + 8 * i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup queue pointers */
|
||||
writel(0, priv->mspi + MSPI_NEWQP_REG);
|
||||
writel(queues - 1, priv->mspi + MSPI_ENDQP_REG);
|
||||
|
||||
/* Deassert CS if requested and it's the last transfer */
|
||||
if (bytes == 0 && (flags & SPI_XFER_END))
|
||||
clrbits_le32(priv->mspi + MSPI_CDRAM_REG + ((queues - 1) << 2), CDRAM_CONT);
|
||||
|
||||
/* Kick off */
|
||||
writel(0, priv->mspi + MSPI_STATUS_REG);
|
||||
if (bytes == 0 && (flags & SPI_XFER_END))
|
||||
writel(MSPI_SPE, priv->mspi + MSPI_SPCR2_REG);
|
||||
else
|
||||
writel(MSPI_SPE | MSPI_CONT_AFTER_CMD,
|
||||
priv->mspi + MSPI_SPCR2_REG);
|
||||
|
||||
ret = readl_poll_timeout(priv->mspi + MSPI_STATUS_REG, val, (val & 1),
|
||||
BUSY_TIMEOUT_US);
|
||||
if (ret) {
|
||||
printf("%s: Failed to disable bspi, device busy\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read data out */
|
||||
if (rx) {
|
||||
if (use_16bits) {
|
||||
for (i = 0; i < chunk; i++)
|
||||
rx[i] = readl(priv->mspi + MSPI_RX_REG + 4 * i) & 0xff;
|
||||
} else {
|
||||
for (i = 0; i < chunk; i++)
|
||||
rx[i] = readl(priv->mspi + MSPI_RX_REG + 8 * i + 4) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance pointers */
|
||||
if (tx)
|
||||
tx += chunk;
|
||||
if (rx)
|
||||
rx += chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mspi_xfer(struct udevice *dev, uint bitlen, const void *dout, void *din, ulong flags)
|
||||
{
|
||||
struct udevice *bus = dev_get_parent(dev);
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
uint bytes;
|
||||
int ret = 0;
|
||||
|
||||
/* we can only transfer multiples of 8 bits */
|
||||
if (bitlen % 8)
|
||||
return -EPROTONOSUPPORT;
|
||||
|
||||
bytes = bitlen / 8;
|
||||
|
||||
if (flags & SPI_XFER_BEGIN) {
|
||||
/* Switch to MSPI */
|
||||
ret = bspi_disable(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* MSPI: Transfer */
|
||||
if (bytes)
|
||||
ret = mspi_exec(priv, bytes, dout, din, flags);
|
||||
|
||||
if (flags & SPI_XFER_END) {
|
||||
/* Switch back to BSPI */
|
||||
ret = bspi_enable(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* iProc interface */
|
||||
|
||||
static int iproc_qspi_set_speed(struct udevice *bus, uint speed)
|
||||
{
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
uint spbr;
|
||||
|
||||
/* MSPI: SCK configuration */
|
||||
spbr = (QSPI_AXI_CLK - 1) / (2 * speed) + 1;
|
||||
writel(max(min(spbr, SPBR_MAX), SPBR_MIN), priv->mspi + MSPI_SPCR0_LSB_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iproc_qspi_set_mode(struct udevice *bus, uint mode)
|
||||
{
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
/* MSPI: set master bit and mode */
|
||||
writel(MSPI_MSTR /* Master */ | (mode & 3), priv->mspi + MSPI_SPCR0_MSB_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iproc_qspi_claim_bus(struct udevice *dev)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iproc_qspi_release_bus(struct udevice *dev)
|
||||
{
|
||||
struct udevice *bus = dev_get_parent(dev);
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
/* Make sure no operation is in progress */
|
||||
writel(0, priv->mspi + MSPI_SPCR2_REG);
|
||||
udelay(BUSY_DELAY_US);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iproc_qspi_of_to_plat(struct udevice *bus)
|
||||
{
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
priv->bspi = dev_read_addr_name(bus, "bspi");
|
||||
if (IS_ERR((void *)priv->bspi)) {
|
||||
printf("%s: Failed to get bspi base address\n", __func__);
|
||||
return PTR_ERR((void *)priv->bspi);
|
||||
}
|
||||
|
||||
priv->bspi_raf = dev_read_addr_name(bus, "bspi_raf");
|
||||
if (IS_ERR((void *)priv->bspi_raf)) {
|
||||
printf("%s: Failed to get bspi_raf base address\n", __func__);
|
||||
return PTR_ERR((void *)priv->bspi_raf);
|
||||
}
|
||||
|
||||
priv->mspi = dev_read_addr_name(bus, "mspi");
|
||||
if (IS_ERR((void *)priv->mspi)) {
|
||||
printf("%s: Failed to get mspi base address\n", __func__);
|
||||
return PTR_ERR((void *)priv->mspi);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iproc_qspi_probe(struct udevice *bus)
|
||||
{
|
||||
struct bcmspi_priv *priv = dev_get_priv(bus);
|
||||
|
||||
/* configure mspi */
|
||||
writel(0, priv->mspi + MSPI_SPCR1_LSB_REG);
|
||||
writel(0, priv->mspi + MSPI_SPCR1_MSB_REG);
|
||||
writel(0, priv->mspi + MSPI_NEWQP_REG);
|
||||
writel(0, priv->mspi + MSPI_ENDQP_REG);
|
||||
writel(0, priv->mspi + MSPI_SPCR2_REG);
|
||||
|
||||
/* configure bspi */
|
||||
bspi_enable(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_spi_ops iproc_qspi_ops = {
|
||||
.claim_bus = iproc_qspi_claim_bus,
|
||||
.release_bus = iproc_qspi_release_bus,
|
||||
.xfer = mspi_xfer,
|
||||
.set_speed = iproc_qspi_set_speed,
|
||||
.set_mode = iproc_qspi_set_mode,
|
||||
.mem_ops = &bspi_mem_ops,
|
||||
};
|
||||
|
||||
static const struct udevice_id iproc_qspi_ids[] = {
|
||||
{ .compatible = "brcm,iproc-qspi" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(iproc_qspi) = {
|
||||
.name = "iproc_qspi",
|
||||
.id = UCLASS_SPI,
|
||||
.of_match = iproc_qspi_ids,
|
||||
.ops = &iproc_qspi_ops,
|
||||
.of_to_plat = iproc_qspi_of_to_plat,
|
||||
.priv_auto = sizeof(struct bcmspi_priv),
|
||||
.probe = iproc_qspi_probe,
|
||||
};
|
@ -267,6 +267,13 @@ config WDT_SBSA
|
||||
In the single stage mode, when the timeout is reached, your system
|
||||
will be reset by WS1. The first signal (WS0) is ignored.
|
||||
|
||||
config WDT_SL28CPLD
|
||||
bool "sl28cpld watchdog timer support"
|
||||
depends on WDT && SL28CPLD
|
||||
help
|
||||
Enable support for the watchdog timer in the Kontron sl28cpld
|
||||
management controller.
|
||||
|
||||
config WDT_SP805
|
||||
bool "SP805 watchdog timer support"
|
||||
depends on WDT
|
||||
|
@ -35,6 +35,7 @@ obj-$(CONFIG_WDT_OCTEONTX) += octeontx_wdt.o
|
||||
obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
|
||||
obj-$(CONFIG_WDT_SBSA) += sbsa_gwdt.o
|
||||
obj-$(CONFIG_WDT_K3_RTI) += rti_wdt.o
|
||||
obj-$(CONFIG_WDT_SL28CPLD) += sl28cpld-wdt.o
|
||||
obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
|
||||
obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
|
||||
obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o
|
||||
|
@ -58,13 +58,11 @@ static void counter_disable(struct a37xx_wdt *priv, int id)
|
||||
clrbits_le32(priv->reg + CNTR_CTRL(id), CNTR_CTRL_ENABLE);
|
||||
}
|
||||
|
||||
static int init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src)
|
||||
static void init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = readl(priv->reg + CNTR_CTRL(id));
|
||||
if (reg & CNTR_CTRL_ACTIVE)
|
||||
return -EBUSY;
|
||||
|
||||
reg &= ~(CNTR_CTRL_MODE_MASK | CNTR_CTRL_PRESCALE_MASK |
|
||||
CNTR_CTRL_TRIG_SRC_MASK);
|
||||
@ -79,8 +77,6 @@ static int init_counter(struct a37xx_wdt *priv, int id, u32 mode, u32 trig_src)
|
||||
reg |= trig_src;
|
||||
|
||||
writel(reg, priv->reg + CNTR_CTRL(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a37xx_wdt_reset(struct udevice *dev)
|
||||
@ -116,16 +112,9 @@ static int a37xx_wdt_expire_now(struct udevice *dev, ulong flags)
|
||||
static int a37xx_wdt_start(struct udevice *dev, u64 ms, ulong flags)
|
||||
{
|
||||
struct a37xx_wdt *priv = dev_get_priv(dev);
|
||||
int err;
|
||||
|
||||
err = init_counter(priv, 0, CNTR_CTRL_MODE_ONESHOT, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = init_counter(priv, 1, CNTR_CTRL_MODE_HWSIG,
|
||||
CNTR_CTRL_TRIG_SRC_PREV_CNTR);
|
||||
if (err < 0)
|
||||
return err;
|
||||
init_counter(priv, 0, CNTR_CTRL_MODE_ONESHOT, 0);
|
||||
init_counter(priv, 1, CNTR_CTRL_MODE_HWSIG, CNTR_CTRL_TRIG_SRC_PREV_CNTR);
|
||||
|
||||
priv->timeout = ms * priv->clk_rate / 1000 / CNTR_CTRL_PRESCALE_MIN;
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
struct rti_wdt_priv {
|
||||
phys_addr_t regs;
|
||||
unsigned int clk_khz;
|
||||
unsigned int clk_hz;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WDT_K3_RTI_LOAD_FW
|
||||
@ -139,7 +139,7 @@ static int rti_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
timer_margin = timeout_ms * priv->clk_khz / 1000;
|
||||
timer_margin = timeout_ms * priv->clk_hz / 1000;
|
||||
timer_margin >>= WDT_PRELOAD_SHIFT;
|
||||
if (timer_margin > WDT_PRELOAD_MAX)
|
||||
timer_margin = WDT_PRELOAD_MAX;
|
||||
@ -185,7 +185,15 @@ static int rti_wdt_probe(struct udevice *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->clk_khz = clk_get_rate(&clk);
|
||||
priv->clk_hz = clk_get_rate(&clk);
|
||||
|
||||
/*
|
||||
* If watchdog is running at 32k clock, it is not accurate.
|
||||
* Adjust frequency down in this case so that it does not expire
|
||||
* earlier than expected.
|
||||
*/
|
||||
if (priv->clk_hz < 32768)
|
||||
priv->clk_hz = priv->clk_hz * 9 / 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
109
drivers/watchdog/sl28cpld-wdt.c
Normal file
109
drivers/watchdog/sl28cpld-wdt.c
Normal file
@ -0,0 +1,109 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Watchdog driver for the sl28cpld
|
||||
*
|
||||
* Copyright (c) 2021 Michael Walle <michael@walle.cc>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <wdt.h>
|
||||
#include <sl28cpld.h>
|
||||
#include <div64.h>
|
||||
|
||||
#define SL28CPLD_WDT_CTRL 0x00
|
||||
#define WDT_CTRL_EN0 BIT(0)
|
||||
#define WDT_CTRL_EN1 BIT(1)
|
||||
#define WDT_CTRL_EN_MASK GENMASK(1, 0)
|
||||
#define WDT_CTRL_LOCK BIT(2)
|
||||
#define WDT_CTRL_ASSERT_SYS_RESET BIT(6)
|
||||
#define WDT_CTRL_ASSERT_WDT_TIMEOUT BIT(7)
|
||||
#define SL28CPLD_WDT_TIMEOUT 0x01
|
||||
#define SL28CPLD_WDT_KICK 0x02
|
||||
#define WDT_KICK_VALUE 0x6b
|
||||
|
||||
static int sl28cpld_wdt_reset(struct udevice *dev)
|
||||
{
|
||||
return sl28cpld_write(dev, SL28CPLD_WDT_KICK, WDT_KICK_VALUE);
|
||||
}
|
||||
|
||||
static int sl28cpld_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
|
||||
{
|
||||
int ret, val;
|
||||
|
||||
val = sl28cpld_read(dev, SL28CPLD_WDT_CTRL);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
/* (1) disable watchdog */
|
||||
val &= ~WDT_CTRL_EN_MASK;
|
||||
ret = sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* (2) set timeout */
|
||||
ret = sl28cpld_write(dev, SL28CPLD_WDT_TIMEOUT, lldiv(timeout, 1000));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* (3) kick it, will reset timer to the timeout value */
|
||||
ret = sl28cpld_wdt_reset(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* (4) enable either recovery or normal one */
|
||||
if (flags & BIT(0))
|
||||
val |= WDT_CTRL_EN1;
|
||||
else
|
||||
val |= WDT_CTRL_EN0;
|
||||
|
||||
if (flags & BIT(1))
|
||||
val |= WDT_CTRL_LOCK;
|
||||
|
||||
if (flags & BIT(2))
|
||||
val &= ~WDT_CTRL_ASSERT_SYS_RESET;
|
||||
else
|
||||
val |= WDT_CTRL_ASSERT_SYS_RESET;
|
||||
|
||||
if (flags & BIT(3))
|
||||
val |= WDT_CTRL_ASSERT_WDT_TIMEOUT;
|
||||
else
|
||||
val &= ~WDT_CTRL_ASSERT_WDT_TIMEOUT;
|
||||
|
||||
return sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val);
|
||||
}
|
||||
|
||||
static int sl28cpld_wdt_stop(struct udevice *dev)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = sl28cpld_read(dev, SL28CPLD_WDT_CTRL);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
return sl28cpld_write(dev, SL28CPLD_WDT_CTRL, val & ~WDT_CTRL_EN_MASK);
|
||||
}
|
||||
|
||||
static int sl28cpld_wdt_expire_now(struct udevice *dev, ulong flags)
|
||||
{
|
||||
return sl28cpld_wdt_start(dev, 0, flags);
|
||||
}
|
||||
|
||||
static const struct wdt_ops sl28cpld_wdt_ops = {
|
||||
.start = sl28cpld_wdt_start,
|
||||
.reset = sl28cpld_wdt_reset,
|
||||
.stop = sl28cpld_wdt_stop,
|
||||
.expire_now = sl28cpld_wdt_expire_now,
|
||||
};
|
||||
|
||||
static const struct udevice_id sl28cpld_wdt_ids[] = {
|
||||
{ .compatible = "kontron,sl28cpld-wdt", },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(sl28cpld_wdt) = {
|
||||
.name = "sl28cpld-wdt",
|
||||
.id = UCLASS_WDT,
|
||||
.of_match = sl28cpld_wdt_ids,
|
||||
.ops = &sl28cpld_wdt_ops,
|
||||
};
|
@ -36,6 +36,8 @@ struct wdt_priv {
|
||||
ulong next_reset;
|
||||
/* Whether watchdog_start() has been called on the device. */
|
||||
bool running;
|
||||
/* No autostart */
|
||||
bool noautostart;
|
||||
};
|
||||
|
||||
static void init_watchdog_dev(struct udevice *dev)
|
||||
@ -52,7 +54,7 @@ static void init_watchdog_dev(struct udevice *dev)
|
||||
dev->name);
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART)) {
|
||||
if (!IS_ENABLED(CONFIG_WATCHDOG_AUTOSTART) || priv->noautostart) {
|
||||
printf("WDT: Not starting %s\n", dev->name);
|
||||
return;
|
||||
}
|
||||
@ -256,16 +258,19 @@ static int wdt_pre_probe(struct udevice *dev)
|
||||
* indicated by a hw_margin_ms property.
|
||||
*/
|
||||
ulong reset_period = 1000;
|
||||
bool noautostart = false;
|
||||
struct wdt_priv *priv;
|
||||
|
||||
if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
|
||||
timeout = dev_read_u32_default(dev, "timeout-sec", timeout);
|
||||
reset_period = dev_read_u32_default(dev, "hw_margin_ms",
|
||||
4 * reset_period) / 4;
|
||||
noautostart = dev_read_bool(dev, "u-boot,noautostart");
|
||||
}
|
||||
priv = dev_get_uclass_priv(dev);
|
||||
priv->timeout = timeout;
|
||||
priv->reset_period = reset_period;
|
||||
priv->noautostart = noautostart;
|
||||
/*
|
||||
* Pretend this device was last reset "long" ago so the first
|
||||
* watchdog_reset will actually call its ->reset method.
|
||||
|
7
env/Kconfig
vendored
7
env/Kconfig
vendored
@ -320,6 +320,7 @@ config ENV_IS_IN_SPI_FLASH
|
||||
default y if NORTHBRIDGE_INTEL_IVYBRIDGE
|
||||
default y if INTEL_QUARK
|
||||
default y if INTEL_QUEENSBAY
|
||||
default y if ARCH_SUNXI
|
||||
help
|
||||
Define this if you have a SPI Flash memory device which you
|
||||
want to use for the environment.
|
||||
@ -536,7 +537,7 @@ config ENV_OFFSET
|
||||
ENV_IS_IN_SPI_FLASH
|
||||
default 0x3f8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC
|
||||
default 0x140000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH
|
||||
default 0x88000 if ARCH_SUNXI
|
||||
default 0xF0000 if ARCH_SUNXI
|
||||
default 0xE0000 if ARCH_ZYNQ
|
||||
default 0x1E00000 if ARCH_ZYNQMP
|
||||
default 0x7F40000 if ARCH_VERSAL
|
||||
@ -559,7 +560,8 @@ config ENV_OFFSET_REDUND
|
||||
config ENV_SIZE
|
||||
hex "Environment Size"
|
||||
default 0x40000 if ENV_IS_IN_SPI_FLASH && ARCH_ZYNQMP
|
||||
default 0x20000 if ARCH_SUNXI || ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
|
||||
default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
|
||||
default 0x10000 if ARCH_SUNXI
|
||||
default 0x8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC
|
||||
default 0x2000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH
|
||||
default 0x8000 if ARCH_ZYNQMP || ARCH_VERSAL
|
||||
@ -575,6 +577,7 @@ config ENV_SECT_SIZE
|
||||
default 0x40000 if ARCH_ZYNQMP || ARCH_VERSAL
|
||||
default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
|
||||
default 0x20000 if MICROBLAZE && ENV_IS_IN_SPI_FLASH
|
||||
default 0x10000 if ARCH_SUNXI && ENV_IS_IN_SPI_FLASH
|
||||
help
|
||||
Size of the sector containing the environment.
|
||||
|
||||
|
@ -243,12 +243,36 @@
|
||||
"run distro_bootcmd;run sd2_bootcmd;" \
|
||||
"env exists secureboot && esbc_halt;"
|
||||
|
||||
#ifdef CONFIG_CMD_USB
|
||||
#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
|
||||
#else
|
||||
#define BOOT_TARGET_DEVICES_USB(func)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MMC
|
||||
#define BOOT_TARGET_DEVICES_MMC(func, instance) func(MMC, mmc, instance)
|
||||
#else
|
||||
#define BOOT_TARGET_DEVICES_MMC(func)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCSI
|
||||
#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0)
|
||||
#else
|
||||
#define BOOT_TARGET_DEVICES_SCSI(func)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CMD_DHCP
|
||||
#define BOOT_TARGET_DEVICES_DHCP(func) func(DHCP, dhcp, na)
|
||||
#else
|
||||
#define BOOT_TARGET_DEVICES_DHCP(func)
|
||||
#endif
|
||||
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(USB, usb, 0) \
|
||||
func(MMC, mmc, 0) \
|
||||
func(MMC, mmc, 1) \
|
||||
func(SCSI, scsi, 0) \
|
||||
func(DHCP, dhcp, na)
|
||||
BOOT_TARGET_DEVICES_USB(func) \
|
||||
BOOT_TARGET_DEVICES_MMC(func, 0) \
|
||||
BOOT_TARGET_DEVICES_MMC(func, 1) \
|
||||
BOOT_TARGET_DEVICES_SCSI(func) \
|
||||
BOOT_TARGET_DEVICES_DHCP(func)
|
||||
#include <config_distro_bootcmd.h>
|
||||
|
||||
#endif /* __LX2_COMMON_H */
|
||||
|
@ -55,7 +55,7 @@
|
||||
"do;" \
|
||||
"setenv overlaystring ${overlaystring}'#'${overlay};" \
|
||||
"done;\0" \
|
||||
"run_fit=bootm ${addr_fit}#${fdtfile}${overlaystring}\0" \
|
||||
"run_fit=bootm ${addr_fit}#conf-${fdtfile}${overlaystring}\0" \
|
||||
|
||||
/*
|
||||
* DDR information. If the CONFIG_NR_DRAM_BANKS is not defined,
|
||||
|
@ -342,7 +342,7 @@ struct efi_open_protocol_info_item {
|
||||
*/
|
||||
struct efi_handler {
|
||||
struct list_head link;
|
||||
const efi_guid_t *guid;
|
||||
const efi_guid_t guid;
|
||||
void *protocol_interface;
|
||||
struct list_head open_infos;
|
||||
};
|
||||
|
16
include/sl28cpld.h
Normal file
16
include/sl28cpld.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright (c) 2021 Michael Walle <michael@walle.cc>
|
||||
*/
|
||||
|
||||
#ifndef __SL28CPLD_H
|
||||
#define __SL28CPLD_H
|
||||
|
||||
#define SL28CPLD_VERSION 0x03
|
||||
|
||||
int sl28cpld_read(struct udevice *dev, uint offset);
|
||||
int sl28cpld_write(struct udevice *dev, uint offset, uint8_t value);
|
||||
int sl28cpld_update(struct udevice *dev, uint offset, uint8_t clear,
|
||||
uint8_t set);
|
||||
|
||||
#endif
|
@ -552,7 +552,7 @@ efi_status_t efi_search_protocol(const efi_handle_t handle,
|
||||
struct efi_handler *protocol;
|
||||
|
||||
protocol = list_entry(lhandle, struct efi_handler, link);
|
||||
if (!guidcmp(protocol->guid, protocol_guid)) {
|
||||
if (!guidcmp(&protocol->guid, protocol_guid)) {
|
||||
if (handler)
|
||||
*handler = protocol;
|
||||
return EFI_SUCCESS;
|
||||
@ -604,7 +604,7 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle)
|
||||
list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) {
|
||||
efi_status_t ret;
|
||||
|
||||
ret = efi_remove_protocol(handle, protocol->guid,
|
||||
ret = efi_remove_protocol(handle, &protocol->guid,
|
||||
protocol->protocol_interface);
|
||||
if (ret != EFI_SUCCESS)
|
||||
return ret;
|
||||
@ -1131,7 +1131,7 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
|
||||
handler = calloc(1, sizeof(struct efi_handler));
|
||||
if (!handler)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
handler->guid = protocol;
|
||||
memcpy((void *)&handler->guid, protocol, sizeof(efi_guid_t));
|
||||
handler->protocol_interface = protocol_interface;
|
||||
INIT_LIST_HEAD(&handler->open_infos);
|
||||
list_add_tail(&handler->link, &efiobj->protocols);
|
||||
@ -1227,7 +1227,7 @@ static efi_status_t efi_get_drivers(efi_handle_t handle,
|
||||
|
||||
/* Count all driver associations */
|
||||
list_for_each_entry(handler, &handle->protocols, link) {
|
||||
if (protocol && guidcmp(handler->guid, protocol))
|
||||
if (protocol && guidcmp(&handler->guid, protocol))
|
||||
continue;
|
||||
list_for_each_entry(item, &handler->open_infos, link) {
|
||||
if (item->info.attributes &
|
||||
@ -1249,7 +1249,7 @@ static efi_status_t efi_get_drivers(efi_handle_t handle,
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
/* Collect unique driver handles */
|
||||
list_for_each_entry(handler, &handle->protocols, link) {
|
||||
if (protocol && guidcmp(handler->guid, protocol))
|
||||
if (protocol && guidcmp(&handler->guid, protocol))
|
||||
continue;
|
||||
list_for_each_entry(item, &handler->open_infos, link) {
|
||||
if (item->info.attributes &
|
||||
@ -2446,7 +2446,7 @@ static efi_status_t EFIAPI efi_protocols_per_handle(
|
||||
|
||||
protocol = list_entry(protocol_handle,
|
||||
struct efi_handler, link);
|
||||
(*protocol_buffer)[j] = (void *)protocol->guid;
|
||||
(*protocol_buffer)[j] = (void *)&protocol->guid;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
@ -3094,7 +3094,7 @@ close_next:
|
||||
(efi_handle_t)image_obj)
|
||||
continue;
|
||||
r = EFI_CALL(efi_close_protocol
|
||||
(efiobj, protocol->guid,
|
||||
(efiobj, &protocol->guid,
|
||||
info->info.agent_handle,
|
||||
info->info.controller_handle
|
||||
));
|
||||
|
@ -91,7 +91,7 @@ void efi_print_image_infos(void *pc)
|
||||
|
||||
list_for_each_entry(efiobj, &efi_obj_list, link) {
|
||||
list_for_each_entry(handler, &efiobj->protocols, link) {
|
||||
if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
|
||||
if (!guidcmp(&handler->guid, &efi_guid_loaded_image)) {
|
||||
efi_print_image_info(
|
||||
(struct efi_loaded_image_obj *)efiobj,
|
||||
handler->protocol_interface, pc);
|
||||
|
@ -383,12 +383,11 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo,
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
context = EVP_MD_CTX_create();
|
||||
context = EVP_MD_CTX_new();
|
||||
if (!context) {
|
||||
ret = rsa_err("EVP context creation failed");
|
||||
goto err_create;
|
||||
}
|
||||
EVP_MD_CTX_init(context);
|
||||
|
||||
ckey = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (!ckey) {
|
||||
@ -425,8 +424,7 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo,
|
||||
goto err_sign;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_reset(context);
|
||||
EVP_MD_CTX_destroy(context);
|
||||
EVP_MD_CTX_free(context);
|
||||
|
||||
debug("Got signature: %zu bytes, expected %d\n", size, EVP_PKEY_size(pkey));
|
||||
*sigp = sig;
|
||||
@ -435,7 +433,7 @@ static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo,
|
||||
return 0;
|
||||
|
||||
err_sign:
|
||||
EVP_MD_CTX_destroy(context);
|
||||
EVP_MD_CTX_free(context);
|
||||
err_create:
|
||||
free(sig);
|
||||
err_alloc:
|
||||
|
@ -196,6 +196,9 @@ hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl
|
||||
hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl
|
||||
HOSTCFLAGS_mkexynosspl.o := -pedantic
|
||||
|
||||
HOSTCFLAGS_kwboot.o += -pthread
|
||||
HOSTLDLIBS_kwboot += -pthread -ltinfo
|
||||
|
||||
ifdtool-objs := $(LIBFDT_OBJS) ifdtool.o
|
||||
hostprogs-$(CONFIG_X86) += ifdtool
|
||||
|
||||
|
504
tools/kwboot.c
504
tools/kwboot.c
@ -1,15 +1,40 @@
|
||||
/*
|
||||
* Boot a Marvell SoC, with Xmodem over UART0.
|
||||
* supports Kirkwood, Dove, Armada 370, Armada XP, Armada 375, Armada 38x and
|
||||
* Armada 39x
|
||||
* supports Kirkwood, Dove, Avanta, Armada 370, Armada XP, Armada 375,
|
||||
* Armada 38x and Armada 39x.
|
||||
*
|
||||
* (c) 2012 Daniel Stodden <daniel.stodden@gmail.com>
|
||||
* (c) 2021 Pali Rohár <pali@kernel.org>
|
||||
* (c) 2021 Marek Behún <marek.behun@nic.cz>
|
||||
*
|
||||
* References: marvell.com, "88F6180, 88F6190, 88F6192, and 88F6281
|
||||
* Integrated Controller: Functional Specifications" December 2,
|
||||
* 2008. Chapter 24.2 "BootROM Firmware".
|
||||
* References:
|
||||
* - "88F6180, 88F6190, 88F6192, and 88F6281: Integrated Controller: Functional
|
||||
* Specifications" December 2, 2008. Chapter 24.2 "BootROM Firmware".
|
||||
* https://web.archive.org/web/20130730091033/https://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
|
||||
* - "88AP510: High-Performance SoC with Integrated CPU, 2D/3D Graphics
|
||||
* Processor, and High-Definition Video Decoder: Functional Specifications"
|
||||
* August 3, 2011. Chapter 5 "BootROM Firmware"
|
||||
* https://web.archive.org/web/20120130172443/https://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf
|
||||
* - "88F6710, 88F6707, and 88F6W11: ARMADA(R) 370 SoC: Functional Specifications"
|
||||
* May 26, 2014. Chapter 6 "BootROM Firmware".
|
||||
* https://web.archive.org/web/20140617183701/https://www.marvell.com/embedded-processors/armada-300/assets/ARMADA370-FunctionalSpec-datasheet.pdf
|
||||
* - "MV78230, MV78260, and MV78460: ARMADA(R) XP Family of Highly Integrated
|
||||
* Multi-Core ARMv7 Based SoC Processors: Functional Specifications"
|
||||
* May 29, 2014. Chapter 6 "BootROM Firmware".
|
||||
* https://web.archive.org/web/20180829171131/https://www.marvell.com/embedded-processors/armada-xp/assets/ARMADA-XP-Functional-SpecDatasheet.pdf
|
||||
* - "ARMADA(R) 375 Value-Performance Dual Core CPU System on Chip: Functional
|
||||
* Specifications" Doc. No. MV-S109377-00, Rev. A. September 18, 2013.
|
||||
* Chapter 7 "Boot Sequence"
|
||||
* CONFIDENTIAL, no public documentation available
|
||||
* - "88F6810, 88F6811, 88F6821, 88F6W21, 88F6820, and 88F6828: ARMADA(R) 38x
|
||||
* Family High-Performance Single/Dual CPU System on Chip: Functional
|
||||
* Specifications" Doc. No. MV-S109094-00, Rev. C. August 2, 2015.
|
||||
* Chapter 7 "Boot Flow"
|
||||
* CONFIDENTIAL, no public documentation available
|
||||
* - "88F6920, 88F6925 and 88F6928: ARMADA(R) 39x High-Performance Dual Core CPU
|
||||
* System on Chip Functional Specifications" Doc. No. MV-S109896-00, Rev. B.
|
||||
* December 22, 2015. Chapter 7 "Boot Flow"
|
||||
* CONFIDENTIAL, no public documentation available
|
||||
*/
|
||||
|
||||
#include "kwbimage.h"
|
||||
@ -28,6 +53,7 @@
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include "termios_linux.h"
|
||||
@ -35,6 +61,13 @@
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These functions are in <term.h> header file, but this header file conflicts
|
||||
* with "termios_linux.h" header file. So declare these functions manually.
|
||||
*/
|
||||
extern int setupterm(const char *, int, int *);
|
||||
extern char *tigetstr(const char *);
|
||||
|
||||
/*
|
||||
* Marvell BootROM UART Sensing
|
||||
*/
|
||||
@ -48,11 +81,9 @@ static unsigned char kwboot_msg_debug[] = {
|
||||
};
|
||||
|
||||
/* Defines known to work on Kirkwood */
|
||||
#define KWBOOT_MSG_REQ_DELAY 10 /* ms */
|
||||
#define KWBOOT_MSG_RSP_TIMEO 50 /* ms */
|
||||
|
||||
/* Defines known to work on Armada XP */
|
||||
#define KWBOOT_MSG_REQ_DELAY_AXP 1000 /* ms */
|
||||
#define KWBOOT_MSG_RSP_TIMEO_AXP 1000 /* ms */
|
||||
|
||||
/*
|
||||
@ -285,7 +316,6 @@ static const char kwb_baud_magic[16] = "$baudratechange";
|
||||
|
||||
static int kwboot_verbose;
|
||||
|
||||
static int msg_req_delay = KWBOOT_MSG_REQ_DELAY;
|
||||
static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO;
|
||||
static int blk_rsp_timeo = KWBOOT_BLK_RSP_TIMEO;
|
||||
|
||||
@ -720,42 +750,120 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void *
|
||||
kwboot_msg_write_handler(void *arg)
|
||||
{
|
||||
int tty = *(int *)((void **)arg)[0];
|
||||
const void *msg = ((void **)arg)[1];
|
||||
int rsp_timeo = msg_rsp_timeo;
|
||||
int i, dummy_oldtype;
|
||||
|
||||
/* allow to cancel this thread at any time */
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &dummy_oldtype);
|
||||
|
||||
while (1) {
|
||||
/* write 128 samples of message pattern into the output queue without waiting */
|
||||
for (i = 0; i < 128; i++) {
|
||||
if (kwboot_tty_send(tty, msg, 8, 1) < 0) {
|
||||
perror("\nFailed to send message pattern");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/* wait until output queue is transmitted and then make pause */
|
||||
if (tcdrain(tty) < 0) {
|
||||
perror("\nFailed to send message pattern");
|
||||
exit(1);
|
||||
}
|
||||
/* BootROM requires pause on UART after it detects message pattern */
|
||||
usleep(rsp_timeo * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
kwboot_bootmsg(int tty, void *msg)
|
||||
kwboot_msg_start_thread(pthread_t *thread, int *tty, void *msg)
|
||||
{
|
||||
void *arg[2];
|
||||
int rc;
|
||||
|
||||
arg[0] = tty;
|
||||
arg[1] = msg;
|
||||
rc = pthread_create(thread, NULL, kwboot_msg_write_handler, arg);
|
||||
if (rc) {
|
||||
errno = rc;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
kwboot_msg_stop_thread(pthread_t thread)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = pthread_cancel(thread);
|
||||
if (rc) {
|
||||
errno = rc;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = pthread_join(thread, NULL);
|
||||
if (rc) {
|
||||
errno = rc;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
kwboot_bootmsg(int tty)
|
||||
{
|
||||
struct kwboot_block block;
|
||||
int rc;
|
||||
pthread_t write_thread;
|
||||
int rc, err;
|
||||
char c;
|
||||
int count;
|
||||
|
||||
if (msg == NULL)
|
||||
kwboot_printv("Please reboot the target into UART boot mode...");
|
||||
else
|
||||
/* flush input and output queue */
|
||||
tcflush(tty, TCIOFLUSH);
|
||||
|
||||
rc = kwboot_msg_start_thread(&write_thread, &tty, kwboot_msg_boot);
|
||||
if (rc) {
|
||||
perror("Failed to start write thread");
|
||||
return rc;
|
||||
}
|
||||
|
||||
kwboot_printv("Sending boot message. Please reboot the target...");
|
||||
|
||||
do {
|
||||
rc = tcflush(tty, TCIOFLUSH);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
for (count = 0; count < 128; count++) {
|
||||
rc = kwboot_tty_send(tty, msg, 8, 0);
|
||||
if (rc) {
|
||||
usleep(msg_req_delay * 1000);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo);
|
||||
|
||||
err = 0;
|
||||
while (1) {
|
||||
kwboot_spinner();
|
||||
|
||||
} while (rc || c != NAK);
|
||||
rc = kwboot_tty_recv(tty, &c, 1, msg_rsp_timeo);
|
||||
if (rc && errno == ETIMEDOUT) {
|
||||
continue;
|
||||
} else if (rc) {
|
||||
err = errno;
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == NAK)
|
||||
break;
|
||||
}
|
||||
|
||||
kwboot_printv("\n");
|
||||
|
||||
if (rc)
|
||||
rc = kwboot_msg_stop_thread(write_thread);
|
||||
if (rc) {
|
||||
perror("Failed to stop write thread");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
perror("Failed to read response for boot message pattern");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this stage we have sent more boot message patterns and BootROM
|
||||
@ -772,11 +880,19 @@ kwboot_bootmsg(int tty, void *msg)
|
||||
*/
|
||||
|
||||
/* flush output queue with remaining boot message patterns */
|
||||
tcflush(tty, TCOFLUSH);
|
||||
rc = tcflush(tty, TCOFLUSH);
|
||||
if (rc) {
|
||||
perror("Failed to flush output queue");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* send one xmodem packet with 0xff bytes to force BootROM to re-sync */
|
||||
memset(&block, 0xff, sizeof(block));
|
||||
kwboot_tty_send(tty, &block, sizeof(block), 0);
|
||||
rc = kwboot_tty_send(tty, &block, sizeof(block), 0);
|
||||
if (rc) {
|
||||
perror("Failed to send sync sequence");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending 132 bytes via 115200B/8-N-1 takes 11.45 ms, reading 132 bytes
|
||||
@ -785,40 +901,151 @@ kwboot_bootmsg(int tty, void *msg)
|
||||
usleep(30 * 1000);
|
||||
|
||||
/* flush remaining NAK replies from input queue */
|
||||
tcflush(tty, TCIFLUSH);
|
||||
rc = tcflush(tty, TCIFLUSH);
|
||||
if (rc) {
|
||||
perror("Failed to flush input queue");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
kwboot_debugmsg(int tty, void *msg)
|
||||
kwboot_debugmsg(int tty)
|
||||
{
|
||||
int rc;
|
||||
unsigned char buf[8192];
|
||||
pthread_t write_thread;
|
||||
int rc, err, i, pos;
|
||||
size_t off;
|
||||
|
||||
kwboot_printv("Sending debug message. Please reboot the target...");
|
||||
/* flush input and output queue */
|
||||
tcflush(tty, TCIOFLUSH);
|
||||
|
||||
do {
|
||||
char buf[16];
|
||||
|
||||
rc = tcflush(tty, TCIOFLUSH);
|
||||
if (rc)
|
||||
break;
|
||||
|
||||
rc = kwboot_tty_send(tty, msg, 8, 0);
|
||||
rc = kwboot_msg_start_thread(&write_thread, &tty, kwboot_msg_debug);
|
||||
if (rc) {
|
||||
usleep(msg_req_delay * 1000);
|
||||
continue;
|
||||
perror("Failed to start write thread");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = kwboot_tty_recv(tty, buf, 16, msg_rsp_timeo);
|
||||
kwboot_printv("Sending debug message. Please reboot the target...");
|
||||
kwboot_spinner();
|
||||
|
||||
err = 0;
|
||||
off = 0;
|
||||
while (1) {
|
||||
/* Read immediately all bytes in queue without waiting */
|
||||
rc = read(tty, buf + off, sizeof(buf) - off);
|
||||
if ((rc < 0 && errno == EINTR) || rc == 0) {
|
||||
continue;
|
||||
} else if (rc < 0) {
|
||||
err = errno;
|
||||
break;
|
||||
}
|
||||
off += rc - 1;
|
||||
|
||||
kwboot_spinner();
|
||||
|
||||
} while (rc);
|
||||
/*
|
||||
* Check if we received at least 4 debug message patterns
|
||||
* (console echo from BootROM) in cyclic buffer
|
||||
*/
|
||||
|
||||
for (pos = 0; pos < sizeof(kwboot_msg_debug); pos++)
|
||||
if (buf[off] == kwboot_msg_debug[(pos + off) % sizeof(kwboot_msg_debug)])
|
||||
break;
|
||||
|
||||
for (i = off; i >= 0; i--)
|
||||
if (buf[i] != kwboot_msg_debug[(pos + i) % sizeof(kwboot_msg_debug)])
|
||||
break;
|
||||
|
||||
off -= i;
|
||||
|
||||
if (off >= 4 * sizeof(kwboot_msg_debug))
|
||||
break;
|
||||
|
||||
/* If not move valid suffix from end of the buffer to the beginning of buffer */
|
||||
memmove(buf, buf + i + 1, off);
|
||||
}
|
||||
|
||||
kwboot_printv("\n");
|
||||
|
||||
rc = kwboot_msg_stop_thread(write_thread);
|
||||
if (rc) {
|
||||
perror("Failed to stop write thread");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
perror("Failed to read response for debug message pattern");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* flush output queue with remaining debug message patterns */
|
||||
rc = tcflush(tty, TCOFLUSH);
|
||||
if (rc) {
|
||||
perror("Failed to flush output queue");
|
||||
return rc;
|
||||
}
|
||||
|
||||
kwboot_printv("Clearing input buffer...\n");
|
||||
|
||||
/*
|
||||
* Wait until BootROM transmit all remaining echo characters.
|
||||
* Experimentally it was measured that for Armada 385 BootROM
|
||||
* it is required to wait at least 0.415s. So wait 0.5s.
|
||||
*/
|
||||
usleep(500 * 1000);
|
||||
|
||||
/*
|
||||
* In off variable is stored number of characters received after the
|
||||
* successful detection of echo reply. So these characters are console
|
||||
* echo for other following debug message patterns. BootROM may have in
|
||||
* its output queue other echo characters which were being transmitting
|
||||
* before above sleep call. So read remaining number of echo characters
|
||||
* sent by the BootROM now.
|
||||
*/
|
||||
while ((rc = kwboot_tty_recv(tty, &buf[0], 1, 0)) == 0)
|
||||
off++;
|
||||
if (errno != ETIMEDOUT) {
|
||||
perror("Failed to read response");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear every echo character set by the BootROM by backspace byte.
|
||||
* This is required prior writing any command to the BootROM debug
|
||||
* because BootROM command line buffer has limited size. If length
|
||||
* of the command is larger than buffer size then it looks like
|
||||
* that Armada 385 BootROM crashes after sending ENTER. So erase it.
|
||||
* Experimentally it was measured that for Armada 385 BootROM it is
|
||||
* required to send at least 3 backspace bytes for one echo character.
|
||||
* This is unknown why. But lets do it.
|
||||
*/
|
||||
off *= 3;
|
||||
memset(buf, '\x08', sizeof(buf));
|
||||
while (off > sizeof(buf)) {
|
||||
rc = kwboot_tty_send(tty, buf, sizeof(buf), 1);
|
||||
if (rc) {
|
||||
perror("Failed to send clear sequence");
|
||||
return rc;
|
||||
}
|
||||
off -= sizeof(buf);
|
||||
}
|
||||
rc = kwboot_tty_send(tty, buf, off, 0);
|
||||
if (rc) {
|
||||
perror("Failed to send clear sequence");
|
||||
return rc;
|
||||
}
|
||||
|
||||
usleep(msg_rsp_timeo * 1000);
|
||||
rc = tcflush(tty, TCIFLUSH);
|
||||
if (rc) {
|
||||
perror("Failed to flush input queue");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
@ -1181,37 +1408,84 @@ kwboot_xmodem(int tty, const void *_img, size_t size, int baudrate)
|
||||
}
|
||||
|
||||
static int
|
||||
kwboot_term_pipe(int in, int out, const char *quit, int *s)
|
||||
kwboot_term_pipe(int in, int out, const char *quit, int *s, const char *kbs, int *k)
|
||||
{
|
||||
char buf[128];
|
||||
ssize_t nin;
|
||||
ssize_t nin, noff;
|
||||
|
||||
nin = read(in, buf, sizeof(buf));
|
||||
if (nin <= 0)
|
||||
return -1;
|
||||
|
||||
if (quit) {
|
||||
noff = 0;
|
||||
|
||||
if (quit || kbs) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nin; i++) {
|
||||
if (buf[i] == quit[*s]) {
|
||||
if ((quit || kbs) &&
|
||||
(!quit || buf[i] != quit[*s]) &&
|
||||
(!kbs || buf[i] != kbs[*k])) {
|
||||
const char *prefix;
|
||||
int plen;
|
||||
|
||||
if (quit && kbs) {
|
||||
prefix = (*s >= *k) ? quit : kbs;
|
||||
plen = (*s >= *k) ? *s : *k;
|
||||
} else if (quit) {
|
||||
prefix = quit;
|
||||
plen = *s;
|
||||
} else {
|
||||
prefix = kbs;
|
||||
plen = *k;
|
||||
}
|
||||
|
||||
if (plen > i && kwboot_write(out, prefix, plen - i) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (quit && buf[i] == quit[*s]) {
|
||||
(*s)++;
|
||||
if (!quit[*s]) {
|
||||
nin = i - *s;
|
||||
nin = (i > *s) ? (i - *s) : 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (*s > i && kwboot_write(out, quit, *s - i) < 0)
|
||||
return -1;
|
||||
} else if (quit) {
|
||||
*s = 0;
|
||||
}
|
||||
|
||||
if (kbs && buf[i] == kbs[*k]) {
|
||||
(*k)++;
|
||||
if (!kbs[*k]) {
|
||||
if (i > *k + noff &&
|
||||
kwboot_write(out, buf + noff, i - *k - noff) < 0)
|
||||
return -1;
|
||||
/*
|
||||
* Replace backspace key by '\b' (0x08)
|
||||
* byte which is the only recognized
|
||||
* backspace byte by Marvell BootROM.
|
||||
*/
|
||||
if (write(out, "\x08", 1) < 0)
|
||||
return -1;
|
||||
noff = i + 1;
|
||||
*k = 0;
|
||||
}
|
||||
} else if (kbs) {
|
||||
*k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == nin)
|
||||
nin -= *s;
|
||||
if (i == nin) {
|
||||
i = 0;
|
||||
if (quit && i < *s)
|
||||
i = *s;
|
||||
if (kbs && i < *k)
|
||||
i = *k;
|
||||
nin -= (nin > i) ? i : nin;
|
||||
}
|
||||
}
|
||||
|
||||
if (kwboot_write(out, buf, nin) < 0)
|
||||
if (nin > noff && kwboot_write(out, buf + noff, nin - noff) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -1220,7 +1494,8 @@ kwboot_term_pipe(int in, int out, const char *quit, int *s)
|
||||
static int
|
||||
kwboot_terminal(int tty)
|
||||
{
|
||||
int rc, in, s;
|
||||
int rc, in, s, k;
|
||||
const char *kbs = NULL;
|
||||
const char *quit = "\34c";
|
||||
struct termios otio, tio;
|
||||
|
||||
@ -1239,6 +1514,33 @@ kwboot_terminal(int tty)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get sequence for backspace key used by the current
|
||||
* terminal. Every occurrence of this sequence will be
|
||||
* replaced by '\b' byte which is the only recognized
|
||||
* backspace byte by Marvell BootROM.
|
||||
*
|
||||
* Note that we cannot read this sequence from termios
|
||||
* c_cc[VERASE] as VERASE is valid only when ICANON is
|
||||
* set in termios c_lflag, which is not case for us.
|
||||
*
|
||||
* Also most terminals do not set termios c_cc[VERASE]
|
||||
* as c_cc[VERASE] can specify only one-byte sequence
|
||||
* and instead let applications to read (possible
|
||||
* multi-byte) sequence for backspace key from "kbs"
|
||||
* terminfo database based on $TERM env variable.
|
||||
*
|
||||
* So read "kbs" from terminfo database via tigetstr()
|
||||
* call after successful setupterm(). Most terminals
|
||||
* use byte 0x7F for backspace key, so replacement with
|
||||
* '\b' is required.
|
||||
*/
|
||||
if (setupterm(NULL, STDOUT_FILENO, &rc) == 0) {
|
||||
kbs = tigetstr("kbs");
|
||||
if (kbs == (char *)-1)
|
||||
kbs = NULL;
|
||||
}
|
||||
|
||||
kwboot_printv("[Type Ctrl-%c + %c to quit]\r\n",
|
||||
quit[0] | 0100, quit[1]);
|
||||
} else
|
||||
@ -1246,6 +1548,7 @@ kwboot_terminal(int tty)
|
||||
|
||||
rc = 0;
|
||||
s = 0;
|
||||
k = 0;
|
||||
|
||||
do {
|
||||
fd_set rfds;
|
||||
@ -1265,13 +1568,13 @@ kwboot_terminal(int tty)
|
||||
break;
|
||||
|
||||
if (FD_ISSET(tty, &rfds)) {
|
||||
rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL);
|
||||
rc = kwboot_term_pipe(tty, STDOUT_FILENO, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
|
||||
if (in >= 0 && FD_ISSET(in, &rfds)) {
|
||||
rc = kwboot_term_pipe(in, tty, quit, &s);
|
||||
rc = kwboot_term_pipe(in, tty, quit, &s, kbs, &k);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
@ -1708,16 +2011,16 @@ static void
|
||||
kwboot_usage(FILE *stream, char *progname)
|
||||
{
|
||||
fprintf(stream,
|
||||
"Usage: %s [OPTIONS] [-b <image> | -D <image> ] [-B <baud> ] <TTY>\n",
|
||||
"Usage: %s [OPTIONS] [-b <image> | -D <image> | -b | -d ] [-B <baud> ] [-t] <TTY>\n",
|
||||
progname);
|
||||
fprintf(stream, "\n");
|
||||
fprintf(stream,
|
||||
" -b <image>: boot <image> with preamble (Kirkwood, Armada 370/XP)\n");
|
||||
" -b <image>: boot <image> with preamble (Kirkwood, Avanta, Armada 370/XP/375/38x/39x)\n");
|
||||
fprintf(stream,
|
||||
" -D <image>: boot <image> without preamble (Dove)\n");
|
||||
fprintf(stream, " -d: enter debug mode\n");
|
||||
fprintf(stream, " -b: enter xmodem boot mode\n");
|
||||
fprintf(stream, " -d: enter console debug mode\n");
|
||||
fprintf(stream, " -a: use timings for Armada XP\n");
|
||||
fprintf(stream, " -q <req-delay>: use specific request-delay\n");
|
||||
fprintf(stream, " -s <resp-timeo>: use specific response-timeout\n");
|
||||
fprintf(stream,
|
||||
" -o <block-timeo>: use specific xmodem block timeout\n");
|
||||
@ -1733,8 +2036,8 @@ main(int argc, char **argv)
|
||||
{
|
||||
const char *ttypath, *imgpath;
|
||||
int rv, rc, tty, term;
|
||||
void *bootmsg;
|
||||
void *debugmsg;
|
||||
int bootmsg;
|
||||
int debugmsg;
|
||||
void *img;
|
||||
size_t size;
|
||||
size_t after_img_rsv;
|
||||
@ -1744,8 +2047,8 @@ main(int argc, char **argv)
|
||||
|
||||
rv = 1;
|
||||
tty = -1;
|
||||
bootmsg = NULL;
|
||||
debugmsg = NULL;
|
||||
bootmsg = 0;
|
||||
debugmsg = 0;
|
||||
imgpath = NULL;
|
||||
img = NULL;
|
||||
term = 0;
|
||||
@ -1767,24 +2070,25 @@ main(int argc, char **argv)
|
||||
case 'b':
|
||||
if (imgpath || bootmsg || debugmsg)
|
||||
goto usage;
|
||||
bootmsg = kwboot_msg_boot;
|
||||
bootmsg = 1;
|
||||
if (prev_optind == optind)
|
||||
goto usage;
|
||||
if (optind < argc - 1 && argv[optind] && argv[optind][0] != '-')
|
||||
/* Option -b could have optional argument which specify image path */
|
||||
if (optind < argc && argv[optind] && argv[optind][0] != '-')
|
||||
imgpath = argv[optind++];
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (imgpath || bootmsg || debugmsg)
|
||||
goto usage;
|
||||
bootmsg = NULL;
|
||||
bootmsg = 0;
|
||||
imgpath = optarg;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
if (imgpath || bootmsg || debugmsg)
|
||||
goto usage;
|
||||
debugmsg = kwboot_msg_debug;
|
||||
debugmsg = 1;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
@ -1796,12 +2100,11 @@ main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
msg_req_delay = KWBOOT_MSG_REQ_DELAY_AXP;
|
||||
msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO_AXP;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
msg_req_delay = atoi(optarg);
|
||||
/* nop, for backward compatibility */
|
||||
break;
|
||||
|
||||
case 's':
|
||||
@ -1826,17 +2129,44 @@ main(int argc, char **argv)
|
||||
if (!bootmsg && !term && !debugmsg && !imgpath)
|
||||
goto usage;
|
||||
|
||||
ttypath = argv[optind++];
|
||||
|
||||
if (optind != argc)
|
||||
/*
|
||||
* If there is no remaining argument but optional imgpath was parsed
|
||||
* then it means that optional imgpath was eaten by getopt parser.
|
||||
* Reassing imgpath to required ttypath argument.
|
||||
*/
|
||||
if (optind == argc && imgpath) {
|
||||
ttypath = imgpath;
|
||||
imgpath = NULL;
|
||||
} else if (optind + 1 == argc) {
|
||||
ttypath = argv[optind];
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
tty = kwboot_open_tty(ttypath, imgpath ? 115200 : baudrate);
|
||||
/* boot and debug message use baudrate 115200 */
|
||||
if (((bootmsg && !imgpath) || debugmsg) && baudrate != 115200) {
|
||||
fprintf(stderr, "Baudrate other than 115200 cannot be used for this operation.\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
tty = kwboot_open_tty(ttypath, baudrate);
|
||||
if (tty < 0) {
|
||||
perror(ttypath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* initial baudrate for image transfer is always 115200,
|
||||
* the change to different baudrate is done only after the header is sent
|
||||
*/
|
||||
if (imgpath && baudrate != 115200) {
|
||||
rc = kwboot_tty_change_baudrate(tty, 115200);
|
||||
if (rc) {
|
||||
perror(ttypath);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (baudrate == 115200)
|
||||
/* do not change baudrate during Xmodem to the same value */
|
||||
baudrate = 0;
|
||||
@ -1866,18 +2196,14 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (debugmsg) {
|
||||
rc = kwboot_debugmsg(tty, debugmsg);
|
||||
if (rc) {
|
||||
perror("debugmsg");
|
||||
rc = kwboot_debugmsg(tty);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
} else if (bootmsg) {
|
||||
rc = kwboot_bootmsg(tty, bootmsg);
|
||||
if (rc) {
|
||||
perror("bootmsg");
|
||||
rc = kwboot_bootmsg(tty);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (img) {
|
||||
rc = kwboot_xmodem(tty, img, size, baudrate);
|
||||
|
@ -381,6 +381,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (params.fflag){
|
||||
if (!tparams) {
|
||||
fprintf(stderr, "%s: Missing FIT support\n",
|
||||
params.cmdname);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if (tparams->fflag_handle)
|
||||
/*
|
||||
* in some cases, some additional processing needs
|
||||
@ -391,7 +396,7 @@ int main(int argc, char **argv)
|
||||
retval = tparams->fflag_handle(¶ms);
|
||||
|
||||
if (retval != EXIT_SUCCESS)
|
||||
exit (retval);
|
||||
usage("Bad parameters for FIT image type");
|
||||
}
|
||||
|
||||
if (params.lflag || params.fflag) {
|
||||
|
@ -230,19 +230,25 @@ static int pblimage_verify_header(unsigned char *ptr, int image_size,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
struct pbl_header *pbl_hdr = (struct pbl_header *) ptr;
|
||||
uint32_t rcwheader;
|
||||
|
||||
if (params->arch == IH_ARCH_ARM)
|
||||
rcwheader = RCW_ARM_HEADER;
|
||||
else
|
||||
rcwheader = RCW_PPC_HEADER;
|
||||
|
||||
/* Only a few checks can be done: search for magic numbers */
|
||||
if (ENDIANNESS == 'l') {
|
||||
if (pbl_hdr->preamble != reverse_byte(RCW_PREAMBLE))
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
|
||||
if (pbl_hdr->rcwheader != reverse_byte(RCW_HEADER))
|
||||
if (pbl_hdr->rcwheader != reverse_byte(rcwheader))
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
} else {
|
||||
if (pbl_hdr->preamble != RCW_PREAMBLE)
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
|
||||
if (pbl_hdr->rcwheader != RCW_HEADER)
|
||||
if (pbl_hdr->rcwheader != rcwheader)
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
return 0;
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
#define RCW_BYTES 64
|
||||
#define RCW_PREAMBLE 0xaa55aa55
|
||||
#define RCW_HEADER 0x010e0100
|
||||
#define RCW_ARM_HEADER 0x01ee0100
|
||||
#define RCW_PPC_HEADER 0x010e0100
|
||||
|
||||
struct pbl_header {
|
||||
uint32_t preamble;
|
||||
|
Loading…
Reference in New Issue
Block a user