diff options
126 files changed, 4347 insertions, 5124 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d4591535039..0c7efde5a5b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -92,14 +92,17 @@ T: git git://git.denx.de/u-boot-atmel.git F: arch/arm/mach-at91/ ARM BROADCOM BCM283X -#M: Stephen Warren <swarren@wwwdotorg.org> -S: Orphaned (Since 2017-07) +M: Alexander Graf <agraf@suse.de> +S: Maintained F: arch/arm/mach-bcm283x/ F: drivers/gpio/bcm2835_gpio.c F: drivers/mmc/bcm2835_sdhci.c +F: drivers/mmc/bcm2835_sdhost.c F: drivers/serial/serial_bcm283x_mu.c +F: drivers/serial/serial_bcm283x_pl011.c F: drivers/video/bcm2835.c F: include/dm/platform_data/serial_bcm283x_mu.h +F: drivers/pinctrl/broadcom/ ARM FREESCALE IMX M: Stefano Babic <sbabic@denx.de> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 73fbd54edb3..30a6f6dc538 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -348,6 +348,7 @@ config ARCH_AT91 config TARGET_EDB93XX bool "Support edb93xx" select CPU_ARM920T + select PL010_SERIAL config TARGET_ASPENITE bool "Support aspenite" @@ -399,49 +400,58 @@ config TARGET_APX4DEVKIT bool "Support apx4devkit" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config TARGET_XFI3 bool "Support xfi3" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config TARGET_M28EVK bool "Support m28evk" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config TARGET_MX23EVK bool "Support mx23evk" select CPU_ARM926EJS select SUPPORT_SPL select BOARD_EARLY_INIT_F + select PL011_SERIAL config TARGET_MX28EVK bool "Support mx28evk" select CPU_ARM926EJS select SUPPORT_SPL select BOARD_EARLY_INIT_F + select PL011_SERIAL config TARGET_MX23_OLINUXINO bool "Support mx23_olinuxino" select CPU_ARM926EJS select SUPPORT_SPL select BOARD_EARLY_INIT_F + select PL011_SERIAL config TARGET_BG0900 bool "Support bg0900" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config TARGET_SANSA_FUZE_PLUS bool "Support sansa_fuze_plus" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config TARGET_SC_SPS_1 bool "Support sc_sps_1" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config ORION5X bool "Marvell Orion" @@ -452,24 +462,28 @@ config TARGET_SPEAR300 select CPU_ARM926EJS select BOARD_EARLY_INIT_F imply CMD_SAVES + select PL011_SERIAL config TARGET_SPEAR310 bool "Support spear310" select CPU_ARM926EJS select BOARD_EARLY_INIT_F imply CMD_SAVES + select PL011_SERIAL config TARGET_SPEAR320 bool "Support spear320" select CPU_ARM926EJS select BOARD_EARLY_INIT_F imply CMD_SAVES + select PL011_SERIAL config TARGET_SPEAR600 bool "Support spear600" select CPU_ARM926EJS select BOARD_EARLY_INIT_F imply CMD_SAVES + select PL011_SERIAL config TARGET_STV0991 bool "Support stv0991" @@ -479,12 +493,14 @@ config TARGET_STV0991 select DM_SPI select DM_SPI_FLASH select SPI_FLASH + select PL01X_SERIAL config TARGET_X600 bool "Support x600" select BOARD_LATE_INIT select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config TARGET_IMX31_PHYCORE bool "Support imx31_phycore_eet" @@ -533,6 +549,7 @@ config ARCH_BCM283X select DM_SERIAL select DM_GPIO select OF_CONTROL + select PL01X_SERIAL imply FAT_WRITE config TARGET_VEXPRESS_CA15_TC2 @@ -540,14 +557,17 @@ config TARGET_VEXPRESS_CA15_TC2 select CPU_V7 select CPU_V7_HAS_NONSEC select CPU_V7_HAS_VIRT + select PL011_SERIAL config TARGET_VEXPRESS_CA5X2 bool "Support vexpress_ca5x2" select CPU_V7 + select PL011_SERIAL config TARGET_VEXPRESS_CA9X4 bool "Support vexpress_ca9x4" select CPU_V7 + select PL011_SERIAL config TARGET_BCM23550_W1D bool "Support bcm23550_w1d" @@ -606,11 +626,13 @@ config ARCH_S5PC1XX config ARCH_HIGHBANK bool "Calxeda Highbank" select CPU_V7 + select PL011_SERIAL config ARCH_INTEGRATOR bool "ARM Ltd. Integrator family" select DM select DM_SERIAL + select PL01X_SERIAL config ARCH_KEYSTONE bool "TI Keystone" @@ -678,6 +700,7 @@ config ARCH_QEMU select DM select DM_SERIAL select OF_CONTROL + select PL01X_SERIAL config ARCH_RMOBILE bool "Renesas ARM SoCs" @@ -761,6 +784,7 @@ config TARGET_TS4600 bool "Support TS4600" select CPU_ARM926EJS select SUPPORT_SPL + select PL011_SERIAL config ARCH_VF610 bool "Freescale Vybrid" @@ -816,15 +840,18 @@ config TEGRA config TARGET_VEXPRESS64_AEMV8A bool "Support vexpress_aemv8a" select ARM64 + select PL01X_SERIAL config TARGET_VEXPRESS64_BASE_FVP bool "Support Versatile Express ARMv8a FVP BASE model" select ARM64 select SEMIHOSTING + select PL01X_SERIAL config TARGET_VEXPRESS64_BASE_FVP_DRAM bool "Support Versatile Express ARMv8a FVP BASE model booting from DRAM" select ARM64 + select PL01X_SERIAL help This target is derived from TARGET_VEXPRESS64_BASE_FVP and over-rides the default config to allow the user to load the images directly into @@ -834,6 +861,7 @@ config TARGET_VEXPRESS64_BASE_FVP_DRAM config TARGET_VEXPRESS64_JUNO bool "Support Versatile Express Juno Development Platform" select ARM64 + select PL01X_SERIAL config TARGET_LS2080A_EMU bool "Support ls2080a_emu" @@ -926,6 +954,7 @@ config TARGET_HIKEY select DM_GPIO select DM_SERIAL select OF_CONTROL + select PL01X_SERIAL help Support for HiKey 96boards platform. It features a HI6220 SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM. @@ -937,6 +966,7 @@ config TARGET_POPLAR select OF_CONTROL select DM_SERIAL select DM_USB + select PL01X_SERIAL help Support for Poplar 96boards EE platform. It features a HI3798cv200 SoC, with 4xA53 CPU, 1GB RAM and the high performance Mali T720 GPU @@ -1192,6 +1222,7 @@ config TARGET_THUNDERX_88XX select ARM64 select OF_CONTROL select SYS_CACHE_SHIFT_7 + select PL01X_SERIAL config ARCH_ASPEED bool "Support Aspeed SoCs" @@ -1291,6 +1322,7 @@ source "board/broadcom/bcmns2/Kconfig" source "board/cavium/thunderx/Kconfig" source "board/cirrus/edb93xx/Kconfig" source "board/creative/xfi3/Kconfig" +source "board/eets/pdu001/Kconfig" source "board/freescale/ls2080a/Kconfig" source "board/freescale/ls2080aqds/Kconfig" source "board/freescale/ls2080ardb/Kconfig" diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 9540ba43131..da0ae0d2427 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -161,7 +161,8 @@ dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \ am335x-bonegreen.dtb \ am335x-icev2.dtb \ am335x-pxm50.dtb \ - am335x-rut.dtb + am335x-rut.dtb \ + am335x-pdu001.dtb dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb \ am43x-epos-evm.dtb \ am437x-idk-evm.dtb @@ -217,6 +218,7 @@ dtb-$(CONFIG_TARGET_DRAGONBOARD410C) += dragonboard410c.dtb dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb dtb-$(CONFIG_STM32F4) += stm32f429-disco.dtb \ + stm32429i-eval.dtb \ stm32f469-disco.dtb dtb-$(CONFIG_STM32F7) += stm32f746-disco.dtb \ diff --git a/arch/arm/dts/am335x-pdu001-u-boot.dtsi b/arch/arm/dts/am335x-pdu001-u-boot.dtsi new file mode 100644 index 00000000000..0dcffd56fa5 --- /dev/null +++ b/arch/arm/dts/am335x-pdu001-u-boot.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 EETS GmbH - https://www.eets.ch/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/ { + ocp { + u-boot,dm-pre-reloc; + }; +}; + +&l4_wkup { + u-boot,dm-pre-reloc; +}; + +&scm { + u-boot,dm-pre-reloc; +}; + +&am33xx_pinmux { + u-boot,dm-pre-reloc; +}; + +&uart3_pins { + u-boot,dm-pre-reloc; +}; + +&uart3 { + u-boot,dm-pre-reloc; +}; + +&mmc1_pins { + u-boot,dm-pre-reloc; +}; + +&mmc2_pins { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/am335x-pdu001.dts b/arch/arm/dts/am335x-pdu001.dts new file mode 100644 index 00000000000..bdf3b277def --- /dev/null +++ b/arch/arm/dts/am335x-pdu001.dts @@ -0,0 +1,595 @@ +/* + * pdu001.dts + * + * EETS GmbH PDU001 board device tree file + * + * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/leds/leds-pca9532.h> + +/ { + model = "EETS,PDU001"; + compatible = "eets,pdu001", "ti,am33xx"; + + chosen { + stdout-path = &uart3; + }; + + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + vbat: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <3600000>; + regulator-max-microvolt = <3600000>; + regulator-boot-on; + }; + + lis3_reg: fixedregulator@1 { + compatible = "regulator-fixed"; + regulator-name = "lis3_reg"; + regulator-boot-on; + }; + + panel { + compatible = "ti,tilcdc,panel"; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&lcd_pins_s0>; + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <16>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + display-timings { + 240x320p16 { + clock-frequency = <6500000>; + hactive = <240>; + vactive = <320>; + hfront-porch = <6>; + hback-porch = <6>; + hsync-len = <1>; + vback-porch = <6>; + vfront-porch = <6>; + vsync-len = <1>; + hsync-active = <0>; + vsync-active = <0>; + pixelclk-active = <1>; + de-active = <0>; + }; + }; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&clkout2_pin>; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */ + AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_clk.i2c2_sda */ + AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d0.i2c2_scl */ + >; + }; + + spi1_pins: pinmux_spi1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE3) /* mcasp0_aclkx.spi1_sclk */ + AM33XX_IOPAD(0x994, PIN_OUTPUT | MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ + AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcasp0_axr0.spi1_d1 */ + AM33XX_IOPAD(0x99C, PIN_OUTPUT | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x96C, PIN_OUTPUT | MUX_MODE7) /* uart0_rtsn.gpio1_9 */ + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */ + AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */ + >; + }; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE1) /* spi0_cs1.uart3_rxd */ + AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* ecap0_in_pwm0_out.uart3_txd */ + >; + }; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Port 1 (emac0) */ + AM33XX_IOPAD(0x908, PIN_INPUT | MUX_MODE0) /* mii1_col.mii1_col */ + AM33XX_IOPAD(0x90C, PIN_INPUT | MUX_MODE0) /* mii1_crs.mii1_crs */ + AM33XX_IOPAD(0x910, PIN_INPUT | MUX_MODE0) /* mii1_rxer.mii1_rxer */ + AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE0) /* mii1_txen.mii1_txen */ + AM33XX_IOPAD(0x918, PIN_INPUT | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */ + AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE0) /* mii1_txd3.mii1_txd3 */ + AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE0) /* mii1_txd2.mii1_txd2 */ + AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE0) /* mii1_txd1.mii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE0) /* mii1_txd0.mii1_txd0 */ + AM33XX_IOPAD(0x92c, PIN_INPUT | MUX_MODE0) /* mii1_txclk.mii1_txclk */ + AM33XX_IOPAD(0x930, PIN_INPUT | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */ + AM33XX_IOPAD(0x934, PIN_INPUT | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */ + AM33XX_IOPAD(0x938, PIN_INPUT | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */ + AM33XX_IOPAD(0x93c, PIN_INPUT | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */ + + /* Port 2 (emac1) */ + AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE1) /* mii2_txen.gpmc_a0 */ + AM33XX_IOPAD(0x844, PIN_INPUT | MUX_MODE1) /* mii2_rxdv.gpmc_a1 */ + AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE1) /* mii2_txd3.gpmc_a2 */ + AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE1) /* mii2_txd2.gpmc_a3 */ + AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE1) /* mii2_txd1.gpmc_a4 */ + AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE1) /* mii2_txd0.gpmc_a5 */ + AM33XX_IOPAD(0x858, PIN_INPUT | MUX_MODE1) /* mii2_txclk.gpmc_a6 */ + AM33XX_IOPAD(0x85c, PIN_INPUT | MUX_MODE1) /* mii2_rxclk.gpmc_a7 */ + AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE1) /* mii2_rxd3.gpmc_a8 */ + AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE1) /* mii2_rxd2.gpmc_a9 */ + AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE1) /* mii2_rxd1.gpmc_a10 */ + AM33XX_IOPAD(0x86C, PIN_INPUT | MUX_MODE1) /* mii2_rxd0.gpmc_a11 */ + AM33XX_IOPAD(0x870, PIN_INPUT | MUX_MODE1) /* mii2_crs.gpmc_wait0 */ + AM33XX_IOPAD(0x874, PIN_INPUT | MUX_MODE1) /* mii2_rxer.gpmc_wpn */ + AM33XX_IOPAD(0x878, PIN_INPUT | MUX_MODE1) /* mii2_col.gpmc_ben1 */ + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + /* eMMC */ + pinctrl-single,pins = < + AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3 */ + AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2 */ + AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1 */ + AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0 */ + AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk */ + AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd */ + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + /* SD cardcage */ + pinctrl-single,pins = < + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ + AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ + AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ + /* card change signal for frontpanel SD cardcage */ + AM33XX_IOPAD(0x890, PIN_INPUT | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */ + >; + }; + + lcd_pins_s0: lcd_pins_s0 { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */ + AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */ + AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */ + AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */ + AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */ + AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */ + AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */ + AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */ + AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */ + AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */ + AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */ + AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */ + AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */ + AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */ + AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */ + AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */ + AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */ + AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */ + AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */ + AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */ + >; + }; + + dcan0_pins: pinmux_dcan0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2) /* uart1_ctsn.d_can0_tx */ + AM33XX_IOPAD(0x97c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart1_rtsn.d_can0_rx */ + >; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + + rts-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; + rs485-rts-active-high; + rs485-rts-delay = <0 0>; + linux,rs485-enabled-at-boot-time; + + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; + + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + status = "okay"; + clock-frequency = <400000>; + + tps: tps@2d { + reg = <0x2d>; + }; + + m2_eeprom: m2_eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + status = "okay"; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + status = "okay"; + clock-frequency = <100000>; + + board_24aa025e48: board_24aa025e48@50 { + compatible = "microchip,24aa025e48"; + reg = <0x50>; + }; + + backplane_24aa025e48: backplane_24aa025e48@53 { + compatible = "microchip,24aa025e48"; + reg = <0x53>; + }; + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + reg = <0x60>; + psc0 = <0x97>; + pwm0 = <0x80>; + psc1 = <0x97>; + pwm1 = <0x10>; + + run.red@0 { + type = <PCA9532_TYPE_LED>; + }; + run.green@1 { + type = <PCA9532_TYPE_LED>; + default-state = "on"; + }; + s2.red@2 { + type = <PCA9532_TYPE_LED>; + }; + s2.green@3 { + type = <PCA9532_TYPE_LED>; + }; + s1.yellow@4 { + type = <PCA9532_TYPE_LED>; + }; + s1.green@5 { + type = <PCA9532_TYPE_LED>; + }; + }; + + pca9530: pca9530@61 { + compatible = "nxp,pca9530"; + reg = <0x61>; + + tft-panel@0 { + type = <PCA9532_TYPE_LED>; + linux,default-trigger = "backlight"; + default-state = "on"; + }; + }; + + mcp79400: mcp79400@6f { + compatible = "microchip,mcp7940x"; + reg = <0x6f>; + }; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + status = "okay"; + clock-frequency = <100000>; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + ti,pindir-d0-out-d1-in; + status = "okay"; + + cfaf240320a032t { + compatible = "orise,otm3225a"; + reg = <0>; + spi-max-frequency = <1000000>; + // SPI mode 3 + spi-cpol; + spi-cpha; + status = "okay"; + }; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&cppi41dma { + status = "okay"; +}; + +/* + * Disable soc's rtc as we have no VBAT for it. This makes the board + * rtc (Microchip MCP79400) the default rtc device 'rtc0'. + */ +&rtc { + status = "disabled"; +}; + +&lcdc { + status = "okay"; +}; + +&elm { + status = "okay"; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-name = "ldo_vrtc"; + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-name = "buck_vdd_ddr"; + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits */ + regulator-name = "buck_vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits */ + regulator-name = "buck_vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-name = "boost_res"; + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-name = "ldo_vdig1"; + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-name = "ldo_vdig2"; + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-name = "ldo_vpll"; + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-name = "ldo_vdac"; + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-name = "ldo_vaux1"; + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-name = "ldo_vaux2"; + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-name = "ldo_vaux33"; + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-name = "ldo_vmmc"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vbb_reg: regulator@13 { + regulator-name = "bat_vbb"; + }; + }; +}; + +&mac { + pinctrl-names = "default"; + pinctrl-0 = <&cpsw_default>; + dual_emac; /* no switch, two distinct MACs */ + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default"; + pinctrl-0 = <&davinci_mdio_default>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "mii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "mii"; + dual_emac_res_vlan = <2>; +}; + +&tscadc { + status = "okay"; + tsc { + ti,wires = <4>; + ti,x-plate-resistance = <200>; + ti,coordinate-readouts = <5>; + ti,wire-config = <0x01 0x10 0x22 0x33>; + ti,charge-delay = <0x400>; + }; + + adc { + ti,adc-channels = <4 5 6 7>; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + non-removable; +}; + +&mmc2 { + status = "okay"; + vmmc-supply = <&vmmc_reg>; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins>; + cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&dcan0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&dcan0_pins>; +}; diff --git a/arch/arm/dts/bcm283x-uboot.dtsi b/arch/arm/dts/bcm283x-uboot.dtsi index 8e4231ae6c9..21d038aebb2 100644 --- a/arch/arm/dts/bcm283x-uboot.dtsi +++ b/arch/arm/dts/bcm283x-uboot.dtsi @@ -20,3 +20,7 @@ skip-init; u-boot,dm-pre-reloc; }; + +&gpio { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/stm32429i-eval-u-boot.dtsi b/arch/arm/dts/stm32429i-eval-u-boot.dtsi new file mode 100644 index 00000000000..826c942e671 --- /dev/null +++ b/arch/arm/dts/stm32429i-eval-u-boot.dtsi @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <dt-bindings/memory/stm32-sdram.h> +/{ + clocks { + u-boot,dm-pre-reloc; + }; + + aliases { + /* Aliases for gpios so as to use sequence */ + gpio0 = &gpioa; + gpio1 = &gpiob; + gpio2 = &gpioc; + gpio3 = &gpiod; + gpio4 = &gpioe; + gpio5 = &gpiof; + gpio6 = &gpiog; + gpio7 = &gpioh; + gpio8 = &gpioi; + gpio9 = &gpioj; + gpio10 = &gpiok; + }; + + soc { + u-boot,dm-pre-reloc; + pin-controller { + u-boot,dm-pre-reloc; + }; + + fmc: fmc@A0000000 { + compatible = "st,stm32-fmc"; + reg = <0xA0000000 0x1000>; + clocks = <&rcc 0 STM32F4_AHB3_CLOCK(FMC)>; + st,syscfg = <&syscfg>; + pinctrl-0 = <&fmc_pins_d32>; + pinctrl-names = "default"; + st,mem_remap = <4>; + u-boot,dm-pre-reloc; + + /* + * Memory configuration from sdram + * MICRON MT48LC4M32B2B5-7 + */ + bank0: bank@0 { + st,sdram-control = /bits/ 8 <NO_COL_9 + NO_ROW_12 + MWIDTH_32 + BANKS_4 + CAS_3 + SDCLK_2 + RD_BURST_EN + RD_PIPE_DL_0>; + st,sdram-timing = /bits/ 8 <TMRD_2 + TXSR_6 + TRAS_4 + TRC_6 + TWR_2 + TRP_2 + TRCD_2>; + st,sdram-refcount = < 2812 >; + }; + }; + }; +}; + +&clk_hse { + u-boot,dm-pre-reloc; +}; + +&clk_lse { + u-boot,dm-pre-reloc; +}; + +&clk_i2s_ckin { + u-boot,dm-pre-reloc; +}; + +&pwrcfg { + u-boot,dm-pre-reloc; +}; + +&syscfg { + u-boot,dm-pre-reloc; +}; + +&rcc { + u-boot,dm-pre-reloc; +}; + +&gpioa { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpiob { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpioc { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpiod { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpioe { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpiof { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpiog { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpioh { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpioi { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpioj { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&gpiok { + compatible = "st,stm32-gpio"; + u-boot,dm-pre-reloc; +}; + +&pinctrl { + usart1_pins_a: usart1@0 { + u-boot,dm-pre-reloc; + pins1 { + u-boot,dm-pre-reloc; + }; + pins2 { + u-boot,dm-pre-reloc; + }; + }; + + fmc_pins_d32: fmc_d32@0 { + u-boot,dm-pre-reloc; + pins + { + pinmux = <STM32_PINMUX('I',10, AF12)>, /* D31 */ + <STM32_PINMUX('I', 9, AF12)>, /* D30 */ + <STM32_PINMUX('I', 7, AF12)>, /* D29 */ + <STM32_PINMUX('I', 6, AF12)>, /* D28 */ + <STM32_PINMUX('I', 3, AF12)>, /* D27 */ + <STM32_PINMUX('I', 2, AF12)>, /* D26 */ + <STM32_PINMUX('I', 1, AF12)>, /* D25 */ + <STM32_PINMUX('I', 0, AF12)>, /* D24 */ + <STM32_PINMUX('H',15, AF12)>, /* D23 */ + <STM32_PINMUX('H',14, AF12)>, /* D22 */ + <STM32_PINMUX('H',13, AF12)>, /* D21 */ + <STM32_PINMUX('H',12, AF12)>, /* D20 */ + <STM32_PINMUX('H',11, AF12)>, /* D19 */ + <STM32_PINMUX('H',10, AF12)>, /* D18 */ + <STM32_PINMUX('H', 9, AF12)>, /* D17 */ + <STM32_PINMUX('H', 8, AF12)>, /* D16 */ + + <STM32_PINMUX('D',10, AF12)>, /* D15 */ + <STM32_PINMUX('D', 9, AF12)>, /* D14 */ + <STM32_PINMUX('D', 8, AF12)>, /* D13 */ + <STM32_PINMUX('E',15, AF12)>, /* D12 */ + <STM32_PINMUX('E',14, AF12)>, /* D11 */ + <STM32_PINMUX('E',13, AF12)>, /* D10 */ + <STM32_PINMUX('E',12, AF12)>, /* D09 */ + <STM32_PINMUX('E',11, AF12)>, /* D08 */ + <STM32_PINMUX('E',10, AF12)>, /* D07 */ + <STM32_PINMUX('E', 9, AF12)>, /* D06 */ + <STM32_PINMUX('E', 8, AF12)>, /* D05 */ + <STM32_PINMUX('E', 7, AF12)>, /* D04 */ + <STM32_PINMUX('D', 1, AF12)>, /* D03 */ + <STM32_PINMUX('D', 0, AF12)>, /* D02 */ + <STM32_PINMUX('D',15, AF12)>, /* D01 */ + <STM32_PINMUX('D',14, AF12)>, /* D00 */ + + <STM32_PINMUX('E', 0, AF12)>, /* NBL0 */ + <STM32_PINMUX('E', 1, AF12)>, /* NBL1 */ + <STM32_PINMUX('I', 4, AF12)>, /* NBL2 */ + <STM32_PINMUX('I', 5, AF12)>, /* NBL3 */ + + <STM32_PINMUX('G', 5, AF12)>, /* A15-BA1 */ + <STM32_PINMUX('G', 4, AF12)>, /* A14-BA0 */ + <STM32_PINMUX('G', 3, AF12)>, /* A13 */ + <STM32_PINMUX('G', 2, AF12)>, /* A12 */ + <STM32_PINMUX('G', 1, AF12)>, /* A11 */ + <STM32_PINMUX('G', 0, AF12)>, /* A10 */ + <STM32_PINMUX('F',15, AF12)>, /* A09 */ + <STM32_PINMUX('F',14, AF12)>, /* A08 */ + <STM32_PINMUX('F',13, AF12)>, /* A07 */ + <STM32_PINMUX('F',12, AF12)>, /* A06 */ + <STM32_PINMUX('F', 5, AF12)>, /* A05 */ + <STM32_PINMUX('F', 4, AF12)>, /* A04 */ + <STM32_PINMUX('F', 3, AF12)>, /* A03 */ + <STM32_PINMUX('F', 2, AF12)>, /* A02 */ + <STM32_PINMUX('F', 1, AF12)>, /* A01 */ + <STM32_PINMUX('F', 0, AF12)>, /* A00 */ + + <STM32_PINMUX('H', 3, AF12)>, /* SDNE0 */ + <STM32_PINMUX('H', 5, AF12)>, /* SDNWE */ + <STM32_PINMUX('F',11, AF12)>, /* SDNRAS */ + <STM32_PINMUX('G',15, AF12)>, /* SDNCAS */ + <STM32_PINMUX('H', 2, AF12)>, /* SDCKE0 */ + <STM32_PINMUX('G', 8, AF12)>; /* SDCLK> */ + slew-rate = <2>; + u-boot,dm-pre-reloc; + }; + }; +}; diff --git a/arch/arm/dts/stm32429i-eval.dts b/arch/arm/dts/stm32429i-eval.dts new file mode 100644 index 00000000000..362ea4245e5 --- /dev/null +++ b/arch/arm/dts/stm32429i-eval.dts @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2015, STMicroelectronics - All Rights Reserved + * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +#include "stm32f429.dtsi" +#include "stm32f429-pinctrl.dtsi" +#include <dt-bindings/input/input.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "STMicroelectronics STM32429i-EVAL board"; + compatible = "st,stm32429i-eval", "st,stm32f429"; + + chosen { + bootargs = "root=/dev/ram"; + stdout-path = "serial0:115200n8"; + }; + + memory { + reg = <0x00000000 0x2000000>; + }; + + aliases { + serial0 = &usart1; + }; + + clocks { + clk_ext_camera: clk-ext-camera { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + soc { + dma-ranges = <0xc0000000 0x0 0x10000000>; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_vref: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "vref"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + leds { + compatible = "gpio-leds"; + green { + gpios = <&gpiog 6 1>; + linux,default-trigger = "heartbeat"; + }; + orange { + gpios = <&gpiog 7 1>; + }; + red { + gpios = <&gpiog 10 1>; + }; + blue { + gpios = <&gpiog 12 1>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + autorepeat; + button@0 { + label = "Wake up"; + linux,code = <KEY_WAKEUP>; + gpios = <&gpioa 0 0>; + }; + button@1 { + label = "Tamper"; + linux,code = <KEY_RESTART>; + gpios = <&gpioc 13 0>; + }; + }; + + usbotg_hs_phy: usbphy { + #phy-cells = <0>; + compatible = "usb-nop-xceiv"; + clocks = <&rcc 0 STM32F4_AHB1_CLOCK(OTGHSULPI)>; + clock-names = "main_clk"; + }; + + panel_rgb: panel-rgb { + compatible = "ampire,am-480272h3tmqw-t01h"; + status = "okay"; + port { + panel_in_rgb: endpoint { + remote-endpoint = <<dc_out_rgb>; + }; + }; + }; + + mmc_vcard: mmc_vcard { + compatible = "regulator-fixed"; + regulator-name = "mmc_vcard"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&adc { + pinctrl-names = "default"; + pinctrl-0 = <&adc3_in8_pin>; + vref-supply = <®_vref>; + status = "okay"; + adc3: adc@200 { + st,adc-channels = <8>; + status = "okay"; + }; +}; + +&clk_hse { + clock-frequency = <25000000>; +}; + +&crc { + status = "okay"; +}; + +&dcmi { + status = "okay"; + + port { + dcmi_0: endpoint { + remote-endpoint = <&ov2640_0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + pclk-sample = <1>; + }; + }; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_pins>; + pinctrl-names = "default"; + status = "okay"; + + ov2640: camera@30 { + compatible = "ovti,ov2640"; + reg = <0x30>; + resetb-gpios = <&stmpegpio 2 GPIO_ACTIVE_HIGH>; + pwdn-gpios = <&stmpegpio 0 GPIO_ACTIVE_LOW>; + clocks = <&clk_ext_camera>; + clock-names = "xvclk"; + status = "okay"; + + port { + ov2640_0: endpoint { + remote-endpoint = <&dcmi_0>; + }; + }; + }; + + stmpe1600: stmpe1600@42 { + compatible = "st,stmpe1600"; + reg = <0x42>; + interrupts = <8 3>; + interrupt-parent = <&gpioi>; + interrupt-controller; + wakeup-source; + + stmpegpio: stmpe_gpio { + compatible = "st,stmpe-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + }; +}; + +&iwdg { + status = "okay"; + timeout-sec = <32>; +}; + +<dc { + status = "okay"; + pinctrl-0 = <<dc_pins>; + pinctrl-names = "default"; + dma-ranges; + + port { + ltdc_out_rgb: endpoint { + remote-endpoint = <&panel_in_rgb>; + }; + }; +}; + +&mac { + status = "okay"; + pinctrl-0 = <ðernet_mii>; + pinctrl-names = "default"; + phy-mode = "mii"; + phy-handle = <&phy1>; + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; +}; + +&rtc { + status = "okay"; +}; + +&sdio { + status = "okay"; + vmmc-supply = <&mmc_vcard>; + cd-gpios = <&stmpegpio 15 GPIO_ACTIVE_HIGH>; + cd-inverted; + pinctrl-names = "default", "opendrain"; + pinctrl-0 = <&sdio_pins>; + pinctrl-1 = <&sdio_pins_od>; + bus-width = <4>; +}; + +&timers1 { + status = "okay"; + + pwm { + pinctrl-0 = <&pwm1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + timer@0 { + status = "okay"; + }; +}; + +&timers3 { + status = "okay"; + + pwm { + pinctrl-0 = <&pwm3_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + timer@2 { + status = "okay"; + }; +}; + +&usart1 { + pinctrl-0 = <&usart1_pins_a>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usbotg_hs { + dr_mode = "host"; + phys = <&usbotg_hs_phy>; + phy-names = "usb2-phy"; + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/arch/arm/dts/stm32f7-u-boot.dtsi b/arch/arm/dts/stm32f7-u-boot.dtsi index a56ae931210..9a9e4e5f371 100644 --- a/arch/arm/dts/stm32f7-u-boot.dtsi +++ b/arch/arm/dts/stm32f7-u-boot.dtsi @@ -26,3 +26,7 @@ &pwrcfg { u-boot,dm-pre-reloc; }; + +&clk_hse { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/stm32f746.dtsi b/arch/arm/dts/stm32f746.dtsi index 929bf82e4d6..46d148eab2c 100644 --- a/arch/arm/dts/stm32f746.dtsi +++ b/arch/arm/dts/stm32f746.dtsi @@ -65,6 +65,9 @@ compatible = "st,stm32-dwmac"; reg = <0x40028000 0x8000>; reg-names = "stmmaceth"; + clocks = <&rcc 0 STM32F7_AHB1_CLOCK(ETHMAC)>, + <&rcc 0 STM32F7_AHB1_CLOCK(ETHMACTX)>, + <&rcc 0 STM32F7_AHB1_CLOCK(ETHMACRX)>; interrupts = <61>, <62>; interrupt-names = "macirq", "eth_wake_irq"; snps,pbl = <8>; diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h index ae0faef353d..7b8f66a0346 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h @@ -21,9 +21,7 @@ enum periph_id { }; enum periph_clock { - SYSCFG_CLOCK_CFG, TIMER2_CLOCK_CFG, - STMMAC_CLOCK_CFG, }; #endif /* __ASM_ARM_ARCH_PERIPH_H */ diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c index fcc2a0e2146..83409a7ece9 100644 --- a/arch/arm/lib/bootm-fdt.c +++ b/arch/arm/lib/bootm-fdt.c @@ -34,7 +34,7 @@ __weak int fdt_update_ethernet_dt(void *blob) int arch_fixup_fdt(void *blob) { - int ret = 0; + __maybe_unused int ret = 0; #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_OF_LIBFDT) bd_t *bd = gd->bd; int bank; diff --git a/arch/arm/mach-bcm283x/include/mach/gpio.h b/arch/arm/mach-bcm283x/include/mach/gpio.h index daaee52f810..7b4ddc92464 100644 --- a/arch/arm/mach-bcm283x/include/mach/gpio.h +++ b/arch/arm/mach-bcm283x/include/mach/gpio.h @@ -61,6 +61,4 @@ struct bcm2835_gpio_platdata { unsigned long base; }; -int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio); - #endif /* _BCM2835_GPIO_H_ */ diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig index 7260d278775..9a9ccd7b0b8 100644 --- a/arch/arm/mach-omap2/am33xx/Kconfig +++ b/arch/arm/mach-omap2/am33xx/Kconfig @@ -185,6 +185,15 @@ config TARGET_THUBAN select DM_SERIAL select DM_GPIO +config TARGET_PDU001 + bool "Support PDU001" + select DM + select DM_SERIAL + help + Support for PDU001 platform developed by EETS GmbH. + The PDU001 is a processor and display unit developed around + the Computing-Module m2 from bytes at work AG. + endchoice endif diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c index ae86b69b9c7..ea0cabad972 100644 --- a/arch/arm/mach-omap2/am33xx/board.c +++ b/arch/arm/mach-omap2/am33xx/board.c @@ -353,6 +353,9 @@ void early_system_init(void) #ifdef CONFIG_TI_I2C_BOARD_DETECT do_board_detect(); #endif +#ifdef CONFIG_SPL_BUILD + spl_early_init(); +#endif #if defined(CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC) /* Enable RTC32K clock */ rtc32k_enable(); diff --git a/arch/arm/mach-omap2/sec-common.c b/arch/arm/mach-omap2/sec-common.c index 896cb7036fa..bd003cb5ee5 100644 --- a/arch/arm/mach-omap2/sec-common.c +++ b/arch/arm/mach-omap2/sec-common.c @@ -56,7 +56,7 @@ struct ppa_tee_load_info { u32 tee_arg0; /* argument to TEE jump function, in r0 */ }; -static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN); +static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN) __section(".data"); u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...) { diff --git a/arch/arm/mach-stm32/stm32f4/Kconfig b/arch/arm/mach-stm32/stm32f4/Kconfig index 7005c654629..e8fae4de402 100644 --- a/arch/arm/mach-stm32/stm32f4/Kconfig +++ b/arch/arm/mach-stm32/stm32f4/Kconfig @@ -3,10 +3,14 @@ if STM32F4 config TARGET_STM32F429_DISCOVERY bool "STM32F429 Discovery board" +config TARGET_STM32F429_EVALUATION + bool "STM32F429 Evaluation board" + config TARGET_STM32F469_DISCOVERY bool "STM32F469 Discovery board" source "board/st/stm32f429-discovery/Kconfig" +source "board/st/stm32f429-evaluation/Kconfig" source "board/st/stm32f469-discovery/Kconfig" endif diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h index 76faa22c8b4..b2ba31e623c 100644 --- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h +++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h @@ -18,7 +18,7 @@ #include <asm/mpc85xx_gpio.h> #endif -struct mpc85xx_gpio_plat { +struct mpc8xxx_gpio_plat { ulong addr; unsigned long size; uint ngpios; diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index baf38f8441a..57b11b83657 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -1206,11 +1206,6 @@ int fsl_qoriq_dsp_core_to_cluster(unsigned int core); #endif -#ifndef CONFIG_MACH_SPECIFIC -extern int _machine; -extern int have_of; -#endif /* CONFIG_MACH_SPECIFIC */ - /* what kind of prep workstation we are */ extern int _prep_type; /* @@ -1336,15 +1331,6 @@ int prt_83xx_rsr(void); #endif /* ndef ASSEMBLY*/ -#ifdef CONFIG_MACH_SPECIFIC -#if defined(CONFIG_WALNUT) -#define _machine _MACH_walnut -#define have_of 0 -#else -#error "Machine not defined correctly" -#endif -#endif /* CONFIG_MACH_SPECIFIC */ - #if defined(CONFIG_MPC85xx) #define EPAPR_MAGIC (0x45504150) #else diff --git a/board/eets/pdu001/Kconfig b/board/eets/pdu001/Kconfig new file mode 100644 index 00000000000..6217a8f99be --- /dev/null +++ b/board/eets/pdu001/Kconfig @@ -0,0 +1,66 @@ +# Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +if TARGET_PDU001 + +config SYS_BOARD + default "pdu001" + +config SYS_VENDOR + default "eets" + +config SYS_SOC + default "am33xx" + +config SYS_CONFIG_NAME + default "pdu001" + +config CONS_INDEX + int "UART used for console" + range 1 6 + default 4 + help + The AM335x SoC has a total of 6 UARTs (UART0 to UART5 as referenced + in documentation, etc) available to it. The best choice for the + PDU001 is UART3 as it is wired to the header K2; enter 4 here to + use UART3. UART0 is connected to the EIA-485 transceiver. If you + really need to use it, you are advised to remove the transceiver U14 + from the board. UART1 is wired to the backplane and therefore + accessible from there or by the backplane connector K1 of the PDU. + Any other UART then UART3 (enter 4 here), UART1 (enter 2 here) or + UART0 (enter 1 here) are not sensible since they are not wired to + any connector and therefore difficult to access. + +choice + prompt "State of Run LED" + default PDU001_RUN_LED_RED + help + The PDU001 has a bi-color (red/green) LED labeled 'Run' which + can be used to indicate the operating state of the board. By + default it will be lit red by U-Boot. Later in the start-up + process it can be changed to green (or heartbeat or anything else) + by the kernel or some other software. + +config RUN_LED_RED + bool + prompt "Red" + help + Lit Run LED red. + +config RUN_LED_GREEN + bool + prompt "Green" + help + Lit Run LED green. + +config RUN_LED_OFF + bool + prompt "Off" + help + Do not lit Run LED. + +endchoice + +endif diff --git a/board/eets/pdu001/MAINTAINERS b/board/eets/pdu001/MAINTAINERS new file mode 100644 index 00000000000..95295ddea9a --- /dev/null +++ b/board/eets/pdu001/MAINTAINERS @@ -0,0 +1,6 @@ +PDU001 BOARD +M: Felix Brack <fb@ltec.ch> +S: Maintained +F: board/eets/pdu001/ +F: include/configs/pdu001.h +F: configs/am335x_pdu001_defconfig diff --git a/board/eets/pdu001/Makefile b/board/eets/pdu001/Makefile new file mode 100644 index 00000000000..08c6d536d36 --- /dev/null +++ b/board/eets/pdu001/Makefile @@ -0,0 +1,13 @@ +# +# Makefile +# +# Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),) +obj-y := mux.o +endif + +obj-y += board.o diff --git a/board/eets/pdu001/README b/board/eets/pdu001/README new file mode 100644 index 00000000000..50e715446b6 --- /dev/null +++ b/board/eets/pdu001/README @@ -0,0 +1,35 @@ +# Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +Summary +======= + +This document covers the PDU001 target. + +Hardware +======== + +The PDU-001 (Processor and Display Unit) is a plugin card for 19" racks. It is +manufactured by EETS GmbH (https://www.eets.ch). The core of the board is a m2 +SOM from bytes at work (https://www.bytesatwork.ch) which in turn is based on +AM3352 SOC from TI (http://www.ti.com). + +Customization +============= + +As usual the console serial interface is set by CONFIG_CONS_INDEX. Best choice +is 4 here since UART3 is wired to the connector K2. +The Run LED on the PDU-001 can be turned on red by setting CONFIG_RUN_LED_RED +or green by setting CONFIG_RUN_LED_GREEN. Setting CONFIG_RUN_LED_OFF will turn +off the Run LED. + +Booting +======= + +The system boots from either eMMC or SD card cage. It will first try to boot +from the SD card cage. If this fails (missing or unbootable SD card) it will +try to boot from the internal eMMC. The root file system is always expected to +be located in the second partition of the device (eMMC or SD card) that pro- +vided the boot loader. diff --git a/board/eets/pdu001/board.c b/board/eets/pdu001/board.c new file mode 100644 index 00000000000..416bd937cf2 --- /dev/null +++ b/board/eets/pdu001/board.c @@ -0,0 +1,276 @@ +/* + * board.c + * + * Board functions for EETS PDU001 board + * + * Copyright (C) 2018, EETS GmbH, http://www.eets.ch/ + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <errno.h> +#include <spl.h> +#include <i2c.h> +#include <environment.h> +#include <watchdog.h> +#include <debug_uart.h> +#include <dm/ofnode.h> +#include <power/pmic.h> +#include <power/regulator.h> +#include <asm/arch/cpu.h> +#include <asm/arch/hardware.h> +#include <asm/arch/omap.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mmc_host_def.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/mem.h> +#include <asm/io.h> +#include <asm/emif.h> +#include <asm/gpio.h> +#include "board.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define I2C_ADDR_NODE_ID 0x50 +#define I2C_REG_NODE_ID_BASE 0xfa +#define NODE_ID_BYTE_COUNT 6 + +#define I2C_ADDR_LEDS 0x60 +#define I2C_REG_RUN_LED 0x06 +#define RUN_LED_OFF 0x0 +#define RUN_LED_RED 0x1 +#define RUN_LED_GREEN (0x1 << 2) + +#define VDD_MPU_REGULATOR "regulator@2" +#define VDD_CORE_REGULATOR "regulator@3" +#define DEFAULT_CORE_VOLTAGE 1137500 + +/* + * boot device save register + * ------------------------- + * The boot device can be quired by 'spl_boot_device()' in + * 'am33xx_spl_board_init'. However it can't be saved in the u-boot + * environment here. In turn 'spl_boot_device' can't be called in + * 'board_late_init' which allows writing to u-boot environment. + * To get the boot device from 'am33xx_spl_board_init' to + * 'board_late_init' we therefore use a scratch register from the RTC. + */ +#define CONFIG_SYS_RTC_SCRATCH0 0x60 +#define BOOT_DEVICE_SAVE_REGISTER (RTC_BASE + CONFIG_SYS_RTC_SCRATCH0) + +#ifdef CONFIG_SPL_BUILD +static void save_boot_device(void) +{ + *((u32 *)(BOOT_DEVICE_SAVE_REGISTER)) = spl_boot_device(); +} +#endif + +u32 boot_device(void) +{ + return *((u32 *)(BOOT_DEVICE_SAVE_REGISTER)); +} + +/* Store the boot device in the environment variable 'boot_device' */ +static void env_set_boot_device(void) +{ + switch (boot_device()) { + case BOOT_DEVICE_MMC1: { + env_set("boot_device", "emmc"); + break; + } + case BOOT_DEVICE_MMC2: { + env_set("boot_device", "sdcard"); + break; + } + default: { + env_set("boot_device", "unknown"); + break; + } + } +} + +static void set_run_led(struct udevice *dev) +{ + int val = RUN_LED_OFF; + + if (IS_ENABLED(CONFIG_RUN_LED_RED)) + val = RUN_LED_RED; + else if (IS_ENABLED(CONFIG_RUN_LED_GREEN)) + val = RUN_LED_GREEN; + + dm_i2c_reg_write(dev, I2C_REG_RUN_LED, val); +} + +/* Set 'serial#' to the EUI-48 value of board node ID chip */ +static void env_set_serial(struct udevice *dev) +{ + int val; + char serial[2 * NODE_ID_BYTE_COUNT + 1]; + int n; + + for (n = 0; n < sizeof(serial); n += 2) { + val = dm_i2c_reg_read(dev, I2C_REG_NODE_ID_BASE + n / 2); + sprintf(serial + n, "%02X", val); + } + serial[2 * NODE_ID_BYTE_COUNT] = '\0'; + env_set("serial#", serial); +} + +static void set_mpu_and_core_voltage(void) +{ + int mpu_vdd; + int sil_rev; + struct udevice *dev; + struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + + /* + * The PDU001 (more precisely the computing module m2) uses a + * TPS65910 PMIC. For all MPU frequencies we support we use a CORE + * voltage of 1.1375V. For MPU voltage we need to switch based on + * the frequency we are running at. + */ + + /* + * Depending on MPU clock and PG we will need a different VDD + * to drive at that speed. + */ + sil_rev = readl(&cdev->deviceid) >> 28; + mpu_vdd = am335x_get_mpu_vdd(sil_rev, dpll_mpu_opp100.m); + + /* first update the MPU voltage */ + if (!regulator_get_by_devname(VDD_MPU_REGULATOR, &dev)) { + if (regulator_set_value(dev, mpu_vdd)) + debug("failed to set MPU voltage\n"); + } else { + debug("invalid MPU voltage ragulator %s\n", VDD_MPU_REGULATOR); + } + + /* second update the CORE voltage */ + if (!regulator_get_by_devname(VDD_CORE_REGULATOR, &dev)) { + if (regulator_set_value(dev, DEFAULT_CORE_VOLTAGE)) + debug("failed to set CORE voltage\n"); + } else { + debug("invalid CORE voltage ragulator %s\n", + VDD_CORE_REGULATOR); + } +} + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +static const struct ddr_data ddr2_data = { + .datardsratio0 = MT47H128M16RT25E_RD_DQS, + .datafwsratio0 = MT47H128M16RT25E_PHY_FIFO_WE, + .datawrsratio0 = MT47H128M16RT25E_PHY_WR_DATA, +}; + +static const struct cmd_control ddr2_cmd_ctrl_data = { + .cmd0csratio = MT47H128M16RT25E_RATIO, + .cmd1csratio = MT47H128M16RT25E_RATIO, + .cmd2csratio = MT47H128M16RT25E_RATIO, +}; + +static const struct emif_regs ddr2_emif_reg_data = { + .sdram_config = MT47H128M16RT25E_EMIF_SDCFG, + .ref_ctrl = MT47H128M16RT25E_EMIF_SDREF, + .sdram_tim1 = MT47H128M16RT25E_EMIF_TIM1, + .sdram_tim2 = MT47H128M16RT25E_EMIF_TIM2, + .sdram_tim3 = MT47H128M16RT25E_EMIF_TIM3, + .emif_ddr_phy_ctlr_1 = MT47H128M16RT25E_EMIF_READ_LATENCY, +}; + +#define OSC (V_OSCK / 1000000) +const struct dpll_params dpll_ddr = { + 266, OSC - 1, 1, -1, -1, -1, -1}; +const struct dpll_params dpll_ddr_evm_sk = { + 303, OSC - 1, 1, -1, -1, -1, -1}; +const struct dpll_params dpll_ddr_bone_black = { + 400, OSC - 1, 1, -1, -1, -1, -1}; + +void am33xx_spl_board_init(void) +{ + struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + + /* Get the frequency */ + dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev); + + /* Set CORE Frequencies to OPP100 */ + do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); + + /* Set MPU Frequency to what we detected now that voltages are set */ + do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); + + /* save boot device for later use by 'board_late_init' */ + save_boot_device(); +} + +const struct dpll_params *get_dpll_ddr_params(void) +{ + enable_i2c0_pin_mux(); + i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); + + return &dpll_ddr; +} + +void set_mux_conf_regs(void) +{ + /* done first by the ROM and afterwards by the pin controller driver */ + enable_i2c0_pin_mux(); +} + +const struct ctrl_ioregs ioregs = { + .cm0ioctl = MT47H128M16RT25E_IOCTRL_VALUE, + .cm1ioctl = MT47H128M16RT25E_IOCTRL_VALUE, + .cm2ioctl = MT47H128M16RT25E_IOCTRL_VALUE, + .dt0ioctl = MT47H128M16RT25E_IOCTRL_VALUE, + .dt1ioctl = MT47H128M16RT25E_IOCTRL_VALUE, +}; + +void sdram_init(void) +{ + config_ddr(266, &ioregs, &ddr2_data, + &ddr2_cmd_ctrl_data, &ddr2_emif_reg_data, 0); +} +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +#ifdef CONFIG_DEBUG_UART +void board_debug_uart_init(void) +{ + /* done by pin controller driver if not debugging */ + enable_uart_pin_mux(CONFIG_DEBUG_UART_BASE); +} +#endif + +/* + * Basic board specific setup. Pinmux has been handled already. + */ +int board_init(void) +{ +#ifdef CONFIG_HW_WATCHDOG + hw_watchdog_init(); +#endif + + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + return 0; +} + +#ifdef CONFIG_BOARD_LATE_INIT +int board_late_init(void) +{ + struct udevice *dev; + + set_mpu_and_core_voltage(); + env_set_boot_device(); + + /* second I2C bus connects to node ID and front panel LED chip */ + if (!i2c_get_chip_for_busnum(1, I2C_ADDR_LEDS, 1, &dev)) + set_run_led(dev); + if (!i2c_get_chip_for_busnum(1, I2C_ADDR_NODE_ID, 1, &dev)) + env_set_serial(dev); + + return 0; +} +#endif diff --git a/board/eets/pdu001/board.h b/board/eets/pdu001/board.h new file mode 100644 index 00000000000..3474e6a85a8 --- /dev/null +++ b/board/eets/pdu001/board.h @@ -0,0 +1,38 @@ +/* + * board.h + * + * EETS GmbH PDU001 board information header + * + * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * We have two pin mux functions that must exist. First we need I2C0 to + * access the TPS65910 PMIC located on the M2 computing module. + * Second, if we want low-level debugging or a early UART (ie. before the + * pin controller driver is running), we need one of the UART ports UART0 to + * UART5 (usually UART3 since it is wired to K2). + * In case of I2C0 access we explicitly don't rely on the the ROM but we could + * do so as we use the primary mode (mode 0) for I2C0. + * All other multiplexing and pin configuration is done by the DT once it + * gets parsed by the pin controller driver. + * However we relay on the ROM to configure the pins of MMC0 (eMMC) as well + * as MMC1 (microSD card-cage) since these are our boot devices. + */ +void enable_uart0_pin_mux(void); +void enable_uart1_pin_mux(void); +void enable_uart2_pin_mux(void); +void enable_uart3_pin_mux(void); +void enable_uart4_pin_mux(void); +void enable_uart5_pin_mux(void); +void enable_uart_pin_mux(u32 addr); +void enable_i2c0_pin_mux(void); + +#endif diff --git a/board/eets/pdu001/mux.c b/board/eets/pdu001/mux.c new file mode 100644 index 00000000000..bf2c8df8344 --- /dev/null +++ b/board/eets/pdu001/mux.c @@ -0,0 +1,120 @@ +/* + * mux.c + * + * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/hardware.h> +#include <asm/arch/mux.h> +#include <asm/io.h> +#include <i2c.h> +#include "board.h" + +static struct module_pin_mux uart0_pin_mux[] = { + {OFFSET(uart0_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* UART0_RXD */ + {OFFSET(uart0_txd), (MODE(0) | PULLUDEN)}, /* UART0_TXD */ + {-1}, +}; + +static struct module_pin_mux uart1_pin_mux[] = { + {OFFSET(uart1_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)}, /* UART1_RXD */ + {OFFSET(uart1_txd), (MODE(0) | PULLUDEN)}, /* UART1_TXD */ + {-1}, +}; + +static struct module_pin_mux uart2_pin_mux[] = { + {OFFSET(spi0_sclk), (MODE(1) | PULLUP_EN | RXACTIVE)}, /* UART2_RXD */ + {OFFSET(spi0_d0), (MODE(1) | PULLUDEN)}, /* UART2_TXD */ + {-1}, +}; + +static struct module_pin_mux uart3_pin_mux[] = { + {OFFSET(spi0_cs1), (MODE(1) | PULLUP_EN | RXACTIVE)}, /* UART3_RXD */ + {OFFSET(ecap0_in_pwm0_out), (MODE(1) | PULLUDEN)}, /* UART3_TXD */ + {-1}, +}; + +static struct module_pin_mux uart4_pin_mux[] = { + {OFFSET(gpmc_wait0), (MODE(6) | PULLUP_EN | RXACTIVE)}, /* UART4_RXD */ + {OFFSET(gpmc_wpn), (MODE(6) | PULLUDEN)}, /* UART4_TXD */ + {-1}, +}; + +static struct module_pin_mux uart5_pin_mux[] = { + {OFFSET(lcd_data9), (MODE(4) | PULLUP_EN | RXACTIVE)}, /* UART5_RXD */ + {OFFSET(lcd_data8), (MODE(4) | PULLUDEN)}, /* UART5_TXD */ + {-1}, +}; + +static struct module_pin_mux i2c0_pin_mux[] = { + {OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | + PULLUDEN | SLEWCTRL)}, /* I2C_DATA */ + {OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | + PULLUDEN | SLEWCTRL)}, /* I2C_SCLK */ + {-1}, +}; + +void enable_uart0_pin_mux(void) +{ + configure_module_pin_mux(uart0_pin_mux); +} + +void enable_uart1_pin_mux(void) +{ + configure_module_pin_mux(uart1_pin_mux); +} + +void enable_uart2_pin_mux(void) +{ + configure_module_pin_mux(uart2_pin_mux); +} + +void enable_uart3_pin_mux(void) +{ + configure_module_pin_mux(uart3_pin_mux); +} + +void enable_uart4_pin_mux(void) +{ + configure_module_pin_mux(uart4_pin_mux); +} + +void enable_uart5_pin_mux(void) +{ + configure_module_pin_mux(uart5_pin_mux); +} + +void enable_uart_pin_mux(u32 addr) +{ + switch (addr) { + case CONFIG_SYS_NS16550_COM1: + enable_uart0_pin_mux(); + break; + case CONFIG_SYS_NS16550_COM2: + enable_uart1_pin_mux(); + break; + case CONFIG_SYS_NS16550_COM3: + enable_uart2_pin_mux(); + break; + case CONFIG_SYS_NS16550_COM4: + enable_uart3_pin_mux(); + break; + case CONFIG_SYS_NS16550_COM5: + enable_uart4_pin_mux(); + break; + case CONFIG_SYS_NS16550_COM6: + enable_uart5_pin_mux(); + break; + } +} + +void enable_i2c0_pin_mux(void) +{ + configure_module_pin_mux(i2c0_pin_mux); +} diff --git a/board/logicpd/omap3som/omap3logic.h b/board/logicpd/omap3som/omap3logic.h index 22d7760a806..73761191127 100644 --- a/board/logicpd/omap3som/omap3logic.h +++ b/board/logicpd/omap3som/omap3logic.h @@ -229,17 +229,17 @@ void set_muxconf_regs(void) MUX_VAL(CP(HSUSB0_DATA6), (IEN | PTD | DIS | M0)); /*HSUSB0_DATA6*/ MUX_VAL(CP(HSUSB0_DATA7), (IEN | PTD | DIS | M0)); /*HSUSB0_DATA7*/ - MUX_VAL(CP(I2C1_SCL), (IEN | PTU | EN | M0)); /*I2C1_SCL*/ - MUX_VAL(CP(I2C1_SDA), (IEN | PTU | EN | M0)); /*I2C1_SDA*/ + MUX_VAL(CP(I2C1_SCL), (IEN | EN | M0)); /*I2C1_SCL*/ + MUX_VAL(CP(I2C1_SDA), (IEN | EN | M0)); /*I2C1_SDA*/ - MUX_VAL(CP(I2C2_SCL), (IEN | PTU | EN | M0)); /*I2C2_SCL*/ - MUX_VAL(CP(I2C2_SDA), (IEN | PTU | EN | M0)); /*I2C2_SDA*/ + MUX_VAL(CP(I2C2_SCL), (IEN | EN | M0)); /*I2C2_SCL*/ + MUX_VAL(CP(I2C2_SDA), (IEN | EN | M0)); /*I2C2_SDA*/ - MUX_VAL(CP(I2C3_SCL), (IEN | PTU | EN | M0)); /*I2C3_SCL*/ - MUX_VAL(CP(I2C3_SDA), (IEN | PTU | EN | M0)); /*I2C3_SDA*/ + MUX_VAL(CP(I2C3_SCL), (IEN | EN | M0)); /*I2C3_SCL*/ + MUX_VAL(CP(I2C3_SDA), (IEN | EN | M0)); /*I2C3_SDA*/ - MUX_VAL(CP(I2C4_SCL), (IEN | PTU | EN | M0)); /*I2C4_SCL*/ - MUX_VAL(CP(I2C4_SDA), (IEN | PTU | EN | M0)); /*I2C4_SDA*/ + MUX_VAL(CP(I2C4_SCL), (IEN | EN | M0)); /*I2C4_SCL*/ + MUX_VAL(CP(I2C4_SDA), (IEN | EN | M0)); /*I2C4_SDA*/ MUX_VAL(CP(HDQ_SIO), (IEN | PTU | EN | M0)); /*HDQ_SIO*/ diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 3b7a54f519d..177f4af265e 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -24,6 +24,7 @@ #include <asm/armv8/mmu.h> #endif #include <watchdog.h> +#include <dm/pinctrl.h> DECLARE_GLOBAL_DATA_PTR; @@ -419,54 +420,11 @@ static void get_board_rev(void) printf("RPI %s (0x%x)\n", model->name, revision); } -#ifndef CONFIG_PL01X_SERIAL -static bool rpi_is_serial_active(void) -{ - int serial_gpio = 15; - struct udevice *dev; - - /* - * The RPi3 disables the mini uart by default. The easiest way to find - * out whether it is available is to check if the RX pin is muxed. - */ - - if (uclass_first_device(UCLASS_GPIO, &dev) || !dev) - return true; - - if (bcm2835_gpio_get_func_id(dev, serial_gpio) != BCM2835_GPIO_ALT5) - return false; - - return true; -} - -/* Disable mini-UART I/O if it's not pinmuxed to our pins. - * The firmware only enables it if explicitly done in config.txt: enable_uart=1 - */ -static void rpi_disable_inactive_uart(void) -{ - struct udevice *dev; - struct bcm283x_mu_serial_platdata *plat; - - if (uclass_get_device_by_driver(UCLASS_SERIAL, - DM_GET_DRIVER(serial_bcm283x_mu), - &dev) || !dev) - return; - - if (!rpi_is_serial_active()) { - plat = dev_get_platdata(dev); - plat->disabled = true; - } -} -#endif - int board_init(void) { #ifdef CONFIG_HW_WATCHDOG hw_watchdog_init(); #endif -#ifndef CONFIG_PL01X_SERIAL - rpi_disable_inactive_uart(); -#endif get_board_rev(); diff --git a/board/st/stm32f429-evaluation/Kconfig b/board/st/stm32f429-evaluation/Kconfig new file mode 100644 index 00000000000..ca4bb3d9c95 --- /dev/null +++ b/board/st/stm32f429-evaluation/Kconfig @@ -0,0 +1,19 @@ +if TARGET_STM32F429_EVALUATION + +config SYS_BOARD + string + default "stm32f429-evaluation" + +config SYS_VENDOR + string + default "st" + +config SYS_SOC + string + default "stm32f4" + +config SYS_CONFIG_NAME + string + default "stm32f429-evaluation" + +endif diff --git a/board/st/stm32f429-evaluation/MAINTAINERS b/board/st/stm32f429-evaluation/MAINTAINERS new file mode 100644 index 00000000000..8b7b312eee5 --- /dev/null +++ b/board/st/stm32f429-evaluation/MAINTAINERS @@ -0,0 +1,6 @@ +STM32F429-EVALUATION BOARD +M: Patrice Chotard <patrice.chotard@st.com> +S: Maintained +F: board/st/stm32f429-evaluation/ +F: include/configs/stm32f429-evaluation.h +F: configs/stm32f429-evaluation_defconfig diff --git a/board/st/stm32f429-evaluation/Makefile b/board/st/stm32f429-evaluation/Makefile new file mode 100644 index 00000000000..3efba3af411 --- /dev/null +++ b/board/st/stm32f429-evaluation/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2018, STMicroelectronics - All Rights Reserved +# Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := stm32f429-evaluation.o diff --git a/board/st/stm32f429-evaluation/stm32f429-evaluation.c b/board/st/stm32f429-evaluation/stm32f429-evaluation.c new file mode 100644 index 00000000000..25e020784d6 --- /dev/null +++ b/board/st/stm32f429-evaluation/stm32f429-evaluation.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> + +#include <asm/io.h> +#include <asm/arch/stm32.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + int rv; + struct udevice *dev; + + rv = uclass_get_device(UCLASS_RAM, 0, &dev); + if (rv) { + debug("DRAM init failed: %d\n", rv); + return rv; + } + + if (fdtdec_setup_memory_size() != 0) + rv = -EINVAL; + + return rv; +} + +int dram_init_banksize(void) +{ + fdtdec_setup_memory_banksize(); + + return 0; +} + +u32 get_board_rev(void) +{ + return 0; +} + +int board_early_init_f(void) +{ + return 0; +} + +int board_init(void) +{ + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + + return 0; +} + +#ifdef CONFIG_MISC_INIT_R +int misc_init_r(void) +{ + char serialno[25]; + u32 u_id_low, u_id_mid, u_id_high; + + if (!env_get("serial#")) { + u_id_low = readl(&STM32_U_ID->u_id_low); + u_id_mid = readl(&STM32_U_ID->u_id_mid); + u_id_high = readl(&STM32_U_ID->u_id_high); + sprintf(serialno, "%08x%08x%08x", + u_id_high, u_id_mid, u_id_low); + env_set("serial#", serialno); + } + + return 0; +} +#endif diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c index 2e8aa86e817..8da70281f97 100644 --- a/board/st/stm32f746-disco/stm32f746-disco.c +++ b/board/st/stm32f746-disco/stm32f746-disco.c @@ -69,24 +69,10 @@ int dram_init_banksize(void) return 0; } -#ifdef CONFIG_ETH_DESIGNWARE -static int stmmac_setup(void) -{ - clock_setup(SYSCFG_CLOCK_CFG); - /* Set >RMII mode */ - STM32_SYSCFG->pmc |= SYSCFG_PMC_MII_RMII_SEL; - clock_setup(STMMAC_CLOCK_CFG); - - return 0; -} - int board_early_init_f(void) { - stmmac_setup(); - return 0; } -#endif #ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_OS_BOOT @@ -163,5 +149,11 @@ int board_late_init(void) int board_init(void) { gd->bd->bi_boot_params = gd->bd->bi_dram[0].start + 0x100; + +#ifdef CONFIG_ETH_DESIGNWARE + /* Set >RMII mode */ + STM32_SYSCFG->pmc |= SYSCFG_PMC_MII_RMII_SEL; +#endif + return 0; } diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index 2c417e75459..16150ad30a2 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -580,6 +580,11 @@ int board_init(void) gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; gpmc_init(); + /* + * Call this to initialize *ctrl again + */ + hw_data_init(); + /* Clear all important bits for DSS errata that may need to be tweaked*/ mreqprio_0 = readl(&cdev->mreqprio_0) & MREQPRIO_0_SAB_INIT1_MASK & MREQPRIO_0_SAB_INIT0_MASK; diff --git a/cmd/elf.c b/cmd/elf.c index 5745a389dae..5b59fc6329d 100644 --- a/cmd/elf.c +++ b/cmd/elf.c @@ -240,11 +240,7 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * from the VxWorks BSP header files. * This will vary from board to board */ -#if defined(CONFIG_WALNUT) - tmp = (char *)CONFIG_SYS_NVRAM_BASE_ADDR + 0x500; - eth_env_get_enetaddr("ethaddr", (uchar *)build_buf); - memcpy(tmp, &build_buf[3], 3); -#elif defined(CONFIG_SYS_VXWORKS_MAC_PTR) +#if defined(CONFIG_SYS_VXWORKS_MAC_PTR) tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR; eth_env_get_enetaddr("ethaddr", (uchar *)build_buf); memcpy(tmp, build_buf, 6); diff --git a/common/autoboot.c b/common/autoboot.c index a0118650287..2eef7a04cc7 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -57,7 +57,7 @@ static int passwd_abort(uint64_t etime) const char *algo_name = "sha256"; u_int presskey_len = 0; int abort = 0; - int size; + int size = sizeof(sha); int ret; if (sha_env_str == NULL) diff --git a/common/board_f.c b/common/board_f.c index 1965bda1915..c6bc53e1bf0 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -49,7 +49,7 @@ #ifdef XTRN_DECLARE_GLOBAL_DATA_PTR #undef XTRN_DECLARE_GLOBAL_DATA_PTR #define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */ -DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR); +DECLARE_GLOBAL_DATA_PTR = (gd_t *)(CONFIG_SYS_INIT_GD_ADDR); #else DECLARE_GLOBAL_DATA_PTR; #endif @@ -136,7 +136,7 @@ static int display_text_info(void) #endif debug("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", - text_base, bss_start, bss_end); + text_base, bss_start, bss_end); #endif return 0; @@ -420,7 +420,7 @@ static int reserve_malloc(void) { gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN; debug("Reserving %dk for malloc() at: %08lx\n", - TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp); + TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp); return 0; } @@ -450,7 +450,7 @@ static int reserve_global_data(void) gd->start_addr_sp -= sizeof(gd_t); gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t)); debug("Reserving %zu Bytes for Global Data at: %08lx\n", - sizeof(gd_t), gd->start_addr_sp); + sizeof(gd_t), gd->start_addr_sp); return 0; } diff --git a/common/board_r.c b/common/board_r.c index 2baa47f3a0c..6349e86f71a 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -157,9 +157,9 @@ static int initr_reloc_global_data(void) #endif #ifdef CONFIG_OF_EMBED /* - * The fdt_blob needs to be moved to new relocation address - * incase of FDT blob is embedded with in image - */ + * The fdt_blob needs to be moved to new relocation address + * incase of FDT blob is embedded with in image + */ gd->fdt_blob += gd->reloc_off; #endif #ifdef CONFIG_EFI_LOADER @@ -351,14 +351,16 @@ static int initr_flash(void) print_size(flash_size, ""); #ifdef CONFIG_SYS_FLASH_CHECKSUM /* - * Compute and print flash CRC if flashchecksum is set to 'y' - * - * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX - */ + * Compute and print flash CRC if flashchecksum is set to 'y' + * + * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX + */ if (env_get_yesno("flashchecksum") == 1) { + const uchar *flash_base = (const uchar *)CONFIG_SYS_FLASH_BASE; + printf(" CRC: %08X", crc32(0, - (const unsigned char *) CONFIG_SYS_FLASH_BASE, - flash_size)); + flash_base, + flash_size)); } #endif /* CONFIG_SYS_FLASH_CHECKSUM */ putc('\n'); @@ -375,7 +377,6 @@ static int initr_flash(void) update_flash_size(flash_size); #endif - #if defined(CONFIG_OXC) || defined(CONFIG_RMU) /* flash mapped at end of memory map */ bd->bi_flashoffset = CONFIG_SYS_TEXT_BASE + flash_size; @@ -625,7 +626,7 @@ int initr_mem(void) char memsz[32]; pram = env_get_ulong("pram", 10, CONFIG_PRAM); - sprintf(memsz, "%ldk", (long int) ((gd->ram_size / 1024) - pram)); + sprintf(memsz, "%ldk", (long int)((gd->ram_size / 1024) - pram)); env_set("mem", memsz); return 0; @@ -678,7 +679,7 @@ static init_fnc_t init_sequence_r[] = { initr_caches, /* Note: For Freescale LS2 SoCs, new MMU table is created in DDR. * A temporary mapping of IFC high region is since removed, - * so environmental variables in NOR flash is not availble + * so environmental variables in NOR flash is not available * until board_init() is called below to remap IFC to high * region. */ @@ -741,7 +742,7 @@ static init_fnc_t init_sequence_r[] = { #if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do early PCI configuration _before_ the flash gets initialised, - * because PCU ressources are crucial for flash access on some boards. + * because PCU resources are crucial for flash access on some boards. */ initr_pci, #endif diff --git a/common/spl/Kconfig b/common/spl/Kconfig index d686b1ecbdf..65b3aff2448 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -118,6 +118,13 @@ config SPL_SEPARATE_BSS location is used. Normally we put the device tree at the end of BSS but with this option enabled, it goes at _image_binary_end. +config SPL_DISABLE_BANNER_PRINT + bool "Disable output of the SPL banner 'U-Boot SPL ...'" + help + If this option is enabled, SPL will not print the banner with version + info. Selecting this option could be useful to reduce SPL boot time + (e.g. approx. 6 ms slower, when output on i.MX6 with 115200 baud). + config SPL_DISPLAY_PRINT bool "Display a board-specific message in SPL" help @@ -757,6 +764,13 @@ config TPL if TPL +config TPL_BOARD_INIT + bool "Call board-specific initialization in TPL" + help + If this option is enabled, U-Boot will call the function + spl_board_init() from board_init_r(). This function should be + provided by the board. + config TPL_LDSCRIPT string "Linker script for the TPL stage" depends on TPL diff --git a/common/spl/spl.c b/common/spl/spl.c index 76c1963611c..2ebab8f0c28 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -407,7 +407,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) timer_init(); #endif -#ifdef CONFIG_SPL_BOARD_INIT +#if CONFIG_IS_ENABLED(BOARD_INIT) spl_board_init(); #endif @@ -477,8 +477,10 @@ void preloader_console_init(void) gd->have_console = 1; +#ifndef CONFIG_SPL_DISABLE_BANNER_PRINT puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \ U_BOOT_TIME ")\n"); +#endif #ifdef CONFIG_SPL_DISPLAY_PRINT spl_display_print(); #endif diff --git a/configs/am335x_pdu001_defconfig b/configs/am335x_pdu001_defconfig new file mode 100644 index 00000000000..31312b20141 --- /dev/null +++ b/configs/am335x_pdu001_defconfig @@ -0,0 +1,55 @@ +CONFIG_ARM=y +CONFIG_ARCH_OMAP2PLUS=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_AM33XX=y +CONFIG_TARGET_PDU001=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_LIBDISK_SUPPORT=y +# CONFIG_SPL_NAND_SUPPORT is not set +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SPL_FAT_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="am335x-pdu001" +CONFIG_LOCALVERSION="-EETS-1.0.0" +CONFIG_BOOTDELAY=1 +CONFIG_SPL=y +# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_YMODEM_SUPPORT=y +CONFIG_HUSH_PARSER=y +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_XIMG is not set +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_FAT=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_EMBED=y +CONFIG_SPL_DM=y +CONFIG_DM_GPIO=y +CONFIG_DM_I2C=y +CONFIG_MMC_OMAP_HS=y +CONFIG_MMC_SDHCI=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_TPS65910=y +CONFIG_DM_REGULATOR=y +CONFIG_SPL_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_TPS65910=y +CONFIG_SYS_NS16550=y +# CONFIG_USE_TINY_PRINTF is not set +# CONFIG_EFI_LOADER is not set diff --git a/configs/am43xx_evm_qspiboot_defconfig b/configs/am43xx_evm_qspiboot_defconfig index a56abc929fd..35a412ae3d8 100644 --- a/configs/am43xx_evm_qspiboot_defconfig +++ b/configs/am43xx_evm_qspiboot_defconfig @@ -2,7 +2,7 @@ CONFIG_ARM=y # CONFIG_SYS_THUMB_BUILD is not set CONFIG_ARCH_OMAP2PLUS=y CONFIG_AM43XX=y -CONFIG_ISW_ENTRY_ADDR=0x30000000 +CONFIG_SYS_TEXT_BASE=0x30000000 CONFIG_SYS_EXTRA_OPTIONS="SERIAL1,CONS_INDEX=1,QSPI,QSPI_BOOT" CONFIG_QSPI_BOOT=y CONFIG_SYS_CONSOLE_INFO_QUIET=y diff --git a/configs/rpi_0_w_defconfig b/configs/rpi_0_w_defconfig index 12482944af4..8ed7a58659a 100644 --- a/configs/rpi_0_w_defconfig +++ b/configs/rpi_0_w_defconfig @@ -32,3 +32,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_CONSOLE_SCROLL_LINES=10 CONFIG_PHYS_TO_BUS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +# CONFIG_PINCTRL_GENERIC is not set +CONFIG_PINCTRL_BCM283X=y diff --git a/configs/rpi_2_defconfig b/configs/rpi_2_defconfig index c45ffb65aff..b30e6e144c9 100644 --- a/configs/rpi_2_defconfig +++ b/configs/rpi_2_defconfig @@ -32,3 +32,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_CONSOLE_SCROLL_LINES=10 CONFIG_PHYS_TO_BUS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +# CONFIG_PINCTRL_GENERIC is not set +CONFIG_PINCTRL_BCM283X=y diff --git a/configs/rpi_3_32b_defconfig b/configs/rpi_3_32b_defconfig index f7aed357974..bb406440646 100644 --- a/configs/rpi_3_32b_defconfig +++ b/configs/rpi_3_32b_defconfig @@ -34,3 +34,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_CONSOLE_SCROLL_LINES=10 CONFIG_PHYS_TO_BUS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +# CONFIG_PINCTRL_GENERIC is not set +CONFIG_PINCTRL_BCM283X=y diff --git a/configs/rpi_3_defconfig b/configs/rpi_3_defconfig index 9416e3b8fe9..8306bc251db 100644 --- a/configs/rpi_3_defconfig +++ b/configs/rpi_3_defconfig @@ -34,3 +34,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_CONSOLE_SCROLL_LINES=10 CONFIG_PHYS_TO_BUS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +# CONFIG_PINCTRL_GENERIC is not set +CONFIG_PINCTRL_BCM283X=y diff --git a/configs/rpi_defconfig b/configs/rpi_defconfig index 3bfa745c2ee..a7a079ddabf 100644 --- a/configs/rpi_defconfig +++ b/configs/rpi_defconfig @@ -32,3 +32,7 @@ CONFIG_SYS_WHITE_ON_BLACK=y CONFIG_CONSOLE_SCROLL_LINES=10 CONFIG_PHYS_TO_BUS=y CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_FULL=y +# CONFIG_PINCTRL_GENERIC is not set +CONFIG_PINCTRL_BCM283X=y diff --git a/configs/stm32f429-evaluation_defconfig b/configs/stm32f429-evaluation_defconfig new file mode 100644 index 00000000000..0d12fdbb128 --- /dev/null +++ b/configs/stm32f429-evaluation_defconfig @@ -0,0 +1,31 @@ +CONFIG_ARM=y +CONFIG_STM32=y +CONFIG_SYS_MALLOC_F_LEN=0xF00 +CONFIG_STM32F4=y +CONFIG_TARGET_STM32F429_EVALUATION=y +CONFIG_DEFAULT_DEVICE_TREE="stm32429i-eval" +CONFIG_BOOTDELAY=3 +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot > " +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_BOOTEFI_HELLO_COMPILE is not set +CONFIG_CMD_IMLS=y +CONFIG_CMD_GPT=y +# CONFIG_RANDOM_UUID is not set +CONFIG_CMD_MMC=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +# CONFIG_DOS_PARTITION is not set +CONFIG_OF_CONTROL=y +CONFIG_OF_EMBED=y +# CONFIG_BLK is not set +CONFIG_DM_MMC=y +CONFIG_ARM_PL180_MMCI=y +CONFIG_MTD_NOR_FLASH=y diff --git a/drivers/clk/clk_stm32f.c b/drivers/clk/clk_stm32f.c index 63116e0bac3..06827fec752 100644 --- a/drivers/clk/clk_stm32f.c +++ b/drivers/clk/clk_stm32f.c @@ -59,7 +59,7 @@ #define RCC_PLLCFGR_PLLSAIP_MASK GENMASK(17, 16) #define RCC_PLLSAICFGR_PLLSAIN_SHIFT 6 #define RCC_PLLSAICFGR_PLLSAIP_SHIFT 16 -#define RCC_PLLSAICFGR_PLLSAIP_4 BIT(17) +#define RCC_PLLSAICFGR_PLLSAIP_4 BIT(16) #define RCC_PLLSAICFGR_PLLSAIQ_4 BIT(26) #define RCC_PLLSAICFGR_PLLSAIR_2 BIT(29) @@ -67,8 +67,6 @@ #define RCC_DCKCFGRX_SDMMC1SEL BIT(28) #define RCC_DCKCFGR2_SDMMC2SEL BIT(29) -#define RCC_APB2ENR_SAI1EN BIT(22) - /* * RCC AHB1ENR specific definitions */ @@ -86,17 +84,15 @@ * RCC APB2ENR specific definitions */ #define RCC_APB2ENR_SYSCFGEN BIT(14) +#define RCC_APB2ENR_SAI1EN BIT(22) enum periph_clock { - SYSCFG_CLOCK_CFG, TIMER2_CLOCK_CFG, - STMMAC_CLOCK_CFG, }; -struct stm32_clk_info stm32f4_clk_info = { +static const struct stm32_clk_info stm32f4_clk_info = { /* 180 MHz */ .sys_pll_psc = { - .pll_m = 8, .pll_n = 360, .pll_p = 2, .pll_q = 8, @@ -108,10 +104,9 @@ struct stm32_clk_info stm32f4_clk_info = { .v2 = false, }; -struct stm32_clk_info stm32f7_clk_info = { +static const struct stm32_clk_info stm32f7_clk_info = { /* 200 MHz */ .sys_pll_psc = { - .pll_m = 25, .pll_n = 400, .pll_p = 2, .pll_q = 8, @@ -126,7 +121,8 @@ struct stm32_clk_info stm32f7_clk_info = { struct stm32_clk { struct stm32_rcc_regs *base; struct stm32_pwr_regs *pwr_regs; - struct stm32_clk_info *info; + struct stm32_clk_info info; + unsigned long hse_rate; }; static int configure_clocks(struct udevice *dev) @@ -134,7 +130,7 @@ static int configure_clocks(struct udevice *dev) struct stm32_clk *priv = dev_get_priv(dev); struct stm32_rcc_regs *regs = priv->base; struct stm32_pwr_regs *pwr = priv->pwr_regs; - struct pll_psc sys_pll_psc = priv->info->sys_pll_psc; + struct pll_psc *sys_pll_psc = &priv->info.sys_pll_psc; u32 pllsaicfgr = 0; /* Reset RCC configuration */ @@ -152,20 +148,20 @@ static int configure_clocks(struct udevice *dev) ; setbits_le32(®s->cfgr, (( - sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT) - | (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT) - | (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT))); + sys_pll_psc->ahb_psc << RCC_CFGR_HPRE_SHIFT) + | (sys_pll_psc->apb1_psc << RCC_CFGR_PPRE1_SHIFT) + | (sys_pll_psc->apb2_psc << RCC_CFGR_PPRE2_SHIFT))); /* Configure the main PLL */ setbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLSRC); /* pll source HSE */ clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLM_MASK, - sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT); + sys_pll_psc->pll_m << RCC_PLLCFGR_PLLM_SHIFT); clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLN_MASK, - sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT); + sys_pll_psc->pll_n << RCC_PLLCFGR_PLLN_SHIFT); clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLP_MASK, - ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT); + ((sys_pll_psc->pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT); clrsetbits_le32(®s->pllcfgr, RCC_PLLCFGR_PLLQ_MASK, - sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT); + sys_pll_psc->pll_q << RCC_PLLCFGR_PLLQ_SHIFT); /* Configure the SAI PLL to get a 48 MHz source */ pllsaicfgr = RCC_PLLSAICFGR_PLLSAIR_2 | RCC_PLLSAICFGR_PLLSAIQ_4 | @@ -178,7 +174,7 @@ static int configure_clocks(struct udevice *dev) while (!(readl(®s->cr) & RCC_CR_PLLRDY)) ; - if (priv->info->v2) { /*stm32f7 case */ + if (priv->info.v2) { /*stm32f7 case */ /* select PLLSAI as 48MHz clock source */ setbits_le32(®s->dckcfgr2, RCC_DCKCFGRX_CK48MSEL); @@ -202,7 +198,7 @@ static int configure_clocks(struct udevice *dev) setbits_le32(®s->apb1enr, RCC_APB1ENR_PWREN); - if (priv->info->has_overdrive) { + if (priv->info.has_overdrive) { /* * Enable high performance mode * System frequency up to 200 MHz @@ -228,6 +224,11 @@ static int configure_clocks(struct udevice *dev) /* gate the SAI clock, needed for MMC 1&2 clocks */ setbits_le32(®s->apb2enr, RCC_APB2ENR_SAI1EN); +#ifdef CONFIG_ETH_DESIGNWARE + /* gate the SYSCFG clock, needed to set RMII ethernet interface */ + setbits_le32(®s->apb2enr, RCC_APB2ENR_SYSCFGEN); +#endif + return 0; } @@ -241,7 +242,7 @@ static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv, pllq = (readl(®s->pllcfgr) & RCC_PLLCFGR_PLLQ_MASK) >> RCC_PLLCFGR_PLLQ_SHIFT; - if (priv->info->v2) /*stm32f7 case */ + if (priv->info.v2) /*stm32f7 case */ pllsai = readl(®s->dckcfgr2) & RCC_DCKCFGRX_CK48MSEL; else pllsai = readl(®s->dckcfgr) & RCC_DCKCFGRX_CK48MSEL; @@ -253,7 +254,7 @@ static unsigned long stm32_clk_pll48clk_rate(struct stm32_clk *priv, >> RCC_PLLSAICFGR_PLLSAIN_SHIFT); pllsaip = ((((readl(®s->pllsaicfgr) & RCC_PLLCFGR_PLLSAIP_MASK) >> RCC_PLLSAICFGR_PLLSAIP_SHIFT) + 1) << 1); - return ((CONFIG_STM32_HSE_HZ / pllm) * pllsain) / pllsaip; + return ((priv->hse_rate / pllm) * pllsain) / pllsaip; } /* PLL48CLK is selected from PLLQ */ return sysclk / pllq; @@ -281,7 +282,7 @@ static unsigned long stm32_clk_get_rate(struct clk *clk) >> RCC_PLLCFGR_PLLN_SHIFT); pllp = ((((readl(®s->pllcfgr) & RCC_PLLCFGR_PLLP_MASK) >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1); - sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp; + sysclk = ((priv->hse_rate / pllm) * plln) / pllp; } else { return -EINVAL; } @@ -353,17 +354,9 @@ static int stm32_clk_enable(struct clk *clk) void clock_setup(int peripheral) { switch (peripheral) { - case SYSCFG_CLOCK_CFG: - setbits_le32(&STM32_RCC->apb2enr, RCC_APB2ENR_SYSCFGEN); - break; case TIMER2_CLOCK_CFG: setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN); break; - case STMMAC_CLOCK_CFG: - setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_EN); - setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_RX_EN); - setbits_le32(&STM32_RCC->ahb1enr, RCC_AHB1ENR_ETHMAC_TX_EN); - break; default: break; } @@ -372,6 +365,8 @@ void clock_setup(int peripheral) static int stm32_clk_probe(struct udevice *dev) { struct ofnode_phandle_args args; + struct udevice *fixed_clock_dev = NULL; + struct clk clk; int err; debug("%s\n", __func__); @@ -387,16 +382,51 @@ static int stm32_clk_probe(struct udevice *dev) switch (dev_get_driver_data(dev)) { case STM32F4: - priv->info = &stm32f4_clk_info; + memcpy(&priv->info, &stm32f4_clk_info, + sizeof(struct stm32_clk_info)); break; case STM32F7: - priv->info = &stm32f7_clk_info; + memcpy(&priv->info, &stm32f7_clk_info, + sizeof(struct stm32_clk_info)); break; default: return -EINVAL; } - if (priv->info->has_overdrive) { + /* retrieve HSE frequency (external oscillator) */ + err = uclass_get_device_by_name(UCLASS_CLK, "clk-hse", + &fixed_clock_dev); + + if (err) { + pr_err("Can't find fixed clock (%d)", err); + return err; + } + + err = clk_request(fixed_clock_dev, &clk); + if (err) { + pr_err("Can't request %s clk (%d)", fixed_clock_dev->name, + err); + return err; + } + + /* + * set pllm factor accordingly to the external oscillator + * frequency (HSE). For STM32F4 and STM32F7, we want VCO + * freq at 1MHz + * if input PLL frequency is 25Mhz, divide it by 25 + */ + clk.id = 0; + priv->hse_rate = clk_get_rate(&clk); + + if (priv->hse_rate < 1000000) { + pr_err("%s: unexpected HSE clock rate = %ld \"n", __func__, + priv->hse_rate); + return -EINVAL; + } + + priv->info.sys_pll_psc.pll_m = priv->hse_rate / 1000000; + + if (priv->info.has_overdrive) { err = dev_read_phandle_with_args(dev, "st,syscfg", NULL, 0, 0, &args); if (err) { diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b4e859e40cf..b121979dddd 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -276,11 +276,11 @@ config DM_PCA953X Now, max 24 bits chips and PCA953X compatible chips are supported -config MPC85XX_GPIO - bool "Freescale MPC85XX GPIO driver" +config MPC8XXX_GPIO + bool "Freescale MPC8XXX GPIO driver" depends on DM_GPIO help - This driver supports the built-in GPIO controller of MPC85XX CPUs. + This driver supports the built-in GPIO controller of MPC8XXX CPUs. Each GPIO bank is identified by its own entry in the device tree, i.e. @@ -298,7 +298,4 @@ config MPC85XX_GPIO Aside from the standard functions of input/output mode, and output value setting, the open-drain feature, which can configure individual GPIOs to work as open-drain outputs, is supported. - - The driver has been tested on MPC85XX, but it is likely that other - PowerQUICC III devices will work as well. endmenu diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 8525679091d..266c9588fff 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -38,7 +38,7 @@ obj-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o obj-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o obj-$(CONFIG_ALTERA_PIO) += altera_pio.o obj-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o -obj-$(CONFIG_MPC85XX_GPIO) += mpc85xx_gpio.o +obj-$(CONFIG_MPC8XXX_GPIO) += mpc8xxx_gpio.o obj-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o obj-$(CONFIG_OMAP_GPIO) += omap_gpio.o obj-$(CONFIG_DB8500_GPIO) += db8500_gpio.o diff --git a/drivers/gpio/bcm2835_gpio.c b/drivers/gpio/bcm2835_gpio.c index beaa21853a4..d68f8df32d5 100644 --- a/drivers/gpio/bcm2835_gpio.c +++ b/drivers/gpio/bcm2835_gpio.c @@ -7,6 +7,7 @@ #include <common.h> #include <dm.h> +#include <dm/pinctrl.h> #include <errno.h> #include <asm/gpio.h> #include <asm/io.h> @@ -14,6 +15,7 @@ struct bcm2835_gpios { struct bcm2835_gpio_regs *reg; + struct udevice *pinctrl; }; static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio) @@ -29,7 +31,7 @@ static int bcm2835_gpio_direction_input(struct udevice *dev, unsigned gpio) return 0; } -static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned gpio, +static int bcm2835_gpio_direction_output(struct udevice *dev, unsigned int gpio, int value) { struct bcm2835_gpios *gpios = dev_get_priv(dev); @@ -73,19 +75,12 @@ static int bcm2835_gpio_set_value(struct udevice *dev, unsigned gpio, return 0; } -int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned gpio) -{ - struct bcm2835_gpios *gpios = dev_get_priv(dev); - u32 val; - - val = readl(&gpios->reg->gpfsel[BCM2835_GPIO_FSEL_BANK(gpio)]); - - return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK); -} - static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset) { - int funcid = bcm2835_gpio_get_func_id(dev, offset); + struct bcm2835_gpios *priv = dev_get_priv(dev); + int funcid; + + funcid = pinctrl_get_gpio_mux(priv->pinctrl, 0, offset); switch (funcid) { case BCM2835_GPIO_OUTPUT: @@ -97,7 +92,6 @@ static int bcm2835_gpio_get_function(struct udevice *dev, unsigned offset) } } - static const struct dm_gpio_ops gpio_bcm2835_ops = { .direction_input = bcm2835_gpio_direction_input, .direction_output = bcm2835_gpio_direction_output, @@ -116,15 +110,13 @@ static int bcm2835_gpio_probe(struct udevice *dev) uc_priv->gpio_count = BCM2835_GPIO_COUNT; gpios->reg = (struct bcm2835_gpio_regs *)plat->base; + /* We know we're spawned by the pinctrl driver */ + gpios->pinctrl = dev->parent; + return 0; } #if CONFIG_IS_ENABLED(OF_CONTROL) -static const struct udevice_id bcm2835_gpio_id[] = { - {.compatible = "brcm,bcm2835-gpio"}, - {} -}; - static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev) { struct bcm2835_gpio_platdata *plat = dev_get_platdata(dev); @@ -142,7 +134,6 @@ static int bcm2835_gpio_ofdata_to_platdata(struct udevice *dev) U_BOOT_DRIVER(gpio_bcm2835) = { .name = "gpio_bcm2835", .id = UCLASS_GPIO, - .of_match = of_match_ptr(bcm2835_gpio_id), .ofdata_to_platdata = of_match_ptr(bcm2835_gpio_ofdata_to_platdata), .platdata_auto_alloc_size = sizeof(struct bcm2835_gpio_platdata), .ops = &gpio_bcm2835_ops, diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c deleted file mode 100644 index cfeb6e76328..00000000000 --- a/drivers/gpio/mpc85xx_gpio.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * (C) Copyright 2016 - * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de - * - * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is - * - * Copyright 2010 eXMeritus, A Boeing Company - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <dm.h> -#include <asm/gpio.h> -#include <mapmem.h> - -DECLARE_GLOBAL_DATA_PTR; - -struct ccsr_gpio { - u32 gpdir; - u32 gpodr; - u32 gpdat; - u32 gpier; - u32 gpimr; - u32 gpicr; -}; - -struct mpc85xx_gpio_data { - /* The bank's register base in memory */ - struct ccsr_gpio __iomem *base; - /* The address of the registers; used to identify the bank */ - ulong addr; - /* The GPIO count of the bank */ - uint gpio_count; - /* The GPDAT register cannot be used to determine the value of output - * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value - * for output pins */ - u32 dat_shadow; -}; - -inline u32 gpio_mask(unsigned gpio) { - return (1U << (31 - (gpio))); -} - -static inline u32 mpc85xx_gpio_get_val(struct ccsr_gpio *base, u32 mask) -{ - return in_be32(&base->gpdat) & mask; -} - -static inline u32 mpc85xx_gpio_get_dir(struct ccsr_gpio *base, u32 mask) -{ - return in_be32(&base->gpdir) & mask; -} - -static inline void mpc85xx_gpio_set_in(struct ccsr_gpio *base, u32 gpios) -{ - clrbits_be32(&base->gpdat, gpios); - /* GPDIR register 0 -> input */ - clrbits_be32(&base->gpdir, gpios); -} - -static inline void mpc85xx_gpio_set_low(struct ccsr_gpio *base, u32 gpios) -{ - clrbits_be32(&base->gpdat, gpios); - /* GPDIR register 1 -> output */ - setbits_be32(&base->gpdir, gpios); -} - -static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios) -{ - setbits_be32(&base->gpdat, gpios); - /* GPDIR register 1 -> output */ - setbits_be32(&base->gpdir, gpios); -} - -static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask) -{ - return in_be32(&base->gpodr) & mask; -} - -static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32 - gpios) -{ - /* GPODR register 1 -> open drain on */ - setbits_be32(&base->gpodr, gpios); -} - -static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base, - u32 gpios) -{ - /* GPODR register 0 -> open drain off (actively driven) */ - clrbits_be32(&base->gpodr, gpios); -} - -static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio) -{ - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - - mpc85xx_gpio_set_in(data->base, gpio_mask(gpio)); - return 0; -} - -static int mpc85xx_gpio_set_value(struct udevice *dev, unsigned gpio, - int value) -{ - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - - if (value) { - data->dat_shadow |= gpio_mask(gpio); - mpc85xx_gpio_set_high(data->base, gpio_mask(gpio)); - } else { - data->dat_shadow &= ~gpio_mask(gpio); - mpc85xx_gpio_set_low(data->base, gpio_mask(gpio)); - } - return 0; -} - -static int mpc85xx_gpio_direction_output(struct udevice *dev, unsigned gpio, - int value) -{ - return mpc85xx_gpio_set_value(dev, gpio, value); -} - -static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio) -{ - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - - if (!!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio))) { - /* Output -> use shadowed value */ - return !!(data->dat_shadow & gpio_mask(gpio)); - } else { - /* Input -> read value from GPDAT register */ - return !!mpc85xx_gpio_get_val(data->base, gpio_mask(gpio)); - } -} - -static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio) -{ - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - - return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio)); -} - -static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio, - int value) -{ - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - - if (value) { - mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio)); - } else { - mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio)); - } - return 0; -} - -static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio) -{ - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - int dir; - - dir = !!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio)); - return dir ? GPIOF_OUTPUT : GPIOF_INPUT; -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) { - struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev); - fdt_addr_t addr; - fdt_size_t size; - - addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, - dev_of_offset(dev), "reg", 0, &size, false); - - plat->addr = addr; - plat->size = size; - plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), - "ngpios", 32); - - return 0; -} -#endif - -static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev) -{ - struct mpc85xx_gpio_data *priv = dev_get_priv(dev); - struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev); - unsigned long size = plat->size; - - if (size == 0) - size = 0x100; - - priv->addr = plat->addr; - priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size); - - if (!priv->base) - return -ENOMEM; - - priv->gpio_count = plat->ngpios; - priv->dat_shadow = 0; - - return 0; -} - -static int mpc85xx_gpio_probe(struct udevice *dev) -{ - struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); - struct mpc85xx_gpio_data *data = dev_get_priv(dev); - char name[32], *str; - - mpc85xx_gpio_platdata_to_priv(dev); - - snprintf(name, sizeof(name), "MPC@%lx_", data->addr); - str = strdup(name); - - if (!str) - return -ENOMEM; - - uc_priv->bank_name = str; - uc_priv->gpio_count = data->gpio_count; - - return 0; -} - -static const struct dm_gpio_ops gpio_mpc85xx_ops = { - .direction_input = mpc85xx_gpio_direction_input, - .direction_output = mpc85xx_gpio_direction_output, - .get_value = mpc85xx_gpio_get_value, - .set_value = mpc85xx_gpio_set_value, - .get_open_drain = mpc85xx_gpio_get_open_drain, - .set_open_drain = mpc85xx_gpio_set_open_drain, - .get_function = mpc85xx_gpio_get_function, -}; - -static const struct udevice_id mpc85xx_gpio_ids[] = { - { .compatible = "fsl,pq3-gpio" }, - { /* sentinel */ } -}; - -U_BOOT_DRIVER(gpio_mpc85xx) = { - .name = "gpio_mpc85xx", - .id = UCLASS_GPIO, - .ops = &gpio_mpc85xx_ops, -#if CONFIG_IS_ENABLED(OF_CONTROL) - .ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat), - .of_match = mpc85xx_gpio_ids, -#endif - .probe = mpc85xx_gpio_probe, - .priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data), -}; diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c new file mode 100644 index 00000000000..326fd1672d0 --- /dev/null +++ b/drivers/gpio/mpc8xxx_gpio.c @@ -0,0 +1,271 @@ +/* + * (C) Copyright 2016 + * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de + * + * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is + * + * Copyright 2010 eXMeritus, A Boeing Company + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <mapmem.h> +#include <asm/gpio.h> + +struct ccsr_gpio { + u32 gpdir; + u32 gpodr; + u32 gpdat; + u32 gpier; + u32 gpimr; + u32 gpicr; +}; + +struct mpc8xxx_gpio_data { + /* The bank's register base in memory */ + struct ccsr_gpio __iomem *base; + /* The address of the registers; used to identify the bank */ + ulong addr; + /* The GPIO count of the bank */ + uint gpio_count; + /* The GPDAT register cannot be used to determine the value of output + * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value + * for output pins + */ + u32 dat_shadow; + ulong type; +}; + +enum { + MPC8XXX_GPIO_TYPE, + MPC5121_GPIO_TYPE, +}; + +inline u32 gpio_mask(uint gpio) +{ + return (1U << (31 - (gpio))); +} + +static inline u32 mpc8xxx_gpio_get_val(struct ccsr_gpio *base, u32 mask) +{ + return in_be32(&base->gpdat) & mask; +} + +static inline u32 mpc8xxx_gpio_get_dir(struct ccsr_gpio *base, u32 mask) +{ + return in_be32(&base->gpdir) & mask; +} + +static inline void mpc8xxx_gpio_set_in(struct ccsr_gpio *base, u32 gpios) +{ + clrbits_be32(&base->gpdat, gpios); + /* GPDIR register 0 -> input */ + clrbits_be32(&base->gpdir, gpios); +} + +static inline void mpc8xxx_gpio_set_low(struct ccsr_gpio *base, u32 gpios) +{ + clrbits_be32(&base->gpdat, gpios); + /* GPDIR register 1 -> output */ + setbits_be32(&base->gpdir, gpios); +} + +static inline void mpc8xxx_gpio_set_high(struct ccsr_gpio *base, u32 gpios) +{ + setbits_be32(&base->gpdat, gpios); + /* GPDIR register 1 -> output */ + setbits_be32(&base->gpdir, gpios); +} + +static inline int mpc8xxx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask) +{ + return in_be32(&base->gpodr) & mask; +} + +static inline void mpc8xxx_gpio_open_drain_on(struct ccsr_gpio *base, u32 + gpios) +{ + /* GPODR register 1 -> open drain on */ + setbits_be32(&base->gpodr, gpios); +} + +static inline void mpc8xxx_gpio_open_drain_off(struct ccsr_gpio *base, + u32 gpios) +{ + /* GPODR register 0 -> open drain off (actively driven) */ + clrbits_be32(&base->gpodr, gpios); +} + +static int mpc8xxx_gpio_direction_input(struct udevice *dev, uint gpio) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + mpc8xxx_gpio_set_in(data->base, gpio_mask(gpio)); + return 0; +} + +static int mpc8xxx_gpio_set_value(struct udevice *dev, uint gpio, int value) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + if (value) { + data->dat_shadow |= gpio_mask(gpio); + mpc8xxx_gpio_set_high(data->base, gpio_mask(gpio)); + } else { + data->dat_shadow &= ~gpio_mask(gpio); + mpc8xxx_gpio_set_low(data->base, gpio_mask(gpio)); + } + return 0; +} + +static int mpc8xxx_gpio_direction_output(struct udevice *dev, uint gpio, + int value) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + /* GPIO 28..31 are input only on MPC5121 */ + if (data->type == MPC5121_GPIO_TYPE && gpio >= 28) + return -EINVAL; + + return mpc8xxx_gpio_set_value(dev, gpio, value); +} + +static int mpc8xxx_gpio_get_value(struct udevice *dev, uint gpio) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + if (!!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio))) { + /* Output -> use shadowed value */ + return !!(data->dat_shadow & gpio_mask(gpio)); + } + + /* Input -> read value from GPDAT register */ + return !!mpc8xxx_gpio_get_val(data->base, gpio_mask(gpio)); +} + +static int mpc8xxx_gpio_get_open_drain(struct udevice *dev, uint gpio) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + return !!mpc8xxx_gpio_open_drain_val(data->base, gpio_mask(gpio)); +} + +static int mpc8xxx_gpio_set_open_drain(struct udevice *dev, uint gpio, + int value) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + + if (value) + mpc8xxx_gpio_open_drain_on(data->base, gpio_mask(gpio)); + else + mpc8xxx_gpio_open_drain_off(data->base, gpio_mask(gpio)); + + return 0; +} + +static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio) +{ + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + int dir; + + dir = !!mpc8xxx_gpio_get_dir(data->base, gpio_mask(gpio)); + return dir ? GPIOF_OUTPUT : GPIOF_INPUT; +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) +static int mpc8xxx_gpio_ofdata_to_platdata(struct udevice *dev) +{ + struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev); + fdt_addr_t addr; + u32 reg[2]; + + dev_read_u32_array(dev, "reg", reg, 2); + addr = dev_translate_address(dev, reg); + + plat->addr = addr; + plat->size = reg[1]; + plat->ngpios = dev_read_u32_default(dev, "ngpios", 32); + + return 0; +} +#endif + +static int mpc8xxx_gpio_platdata_to_priv(struct udevice *dev) +{ + struct mpc8xxx_gpio_data *priv = dev_get_priv(dev); + struct mpc8xxx_gpio_plat *plat = dev_get_platdata(dev); + unsigned long size = plat->size; + ulong driver_data = dev_get_driver_data(dev); + + if (size == 0) + size = 0x100; + + priv->addr = plat->addr; + priv->base = map_sysmem(plat->addr, size); + + if (!priv->base) + return -ENOMEM; + + priv->gpio_count = plat->ngpios; + priv->dat_shadow = 0; + + priv->type = driver_data; + + return 0; +} + +static int mpc8xxx_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct mpc8xxx_gpio_data *data = dev_get_priv(dev); + char name[32], *str; + + mpc8xxx_gpio_platdata_to_priv(dev); + + snprintf(name, sizeof(name), "MPC@%lx_", data->addr); + str = strdup(name); + + if (!str) + return -ENOMEM; + + uc_priv->bank_name = str; + uc_priv->gpio_count = data->gpio_count; + + return 0; +} + +static const struct dm_gpio_ops gpio_mpc8xxx_ops = { + .direction_input = mpc8xxx_gpio_direction_input, + .direction_output = mpc8xxx_gpio_direction_output, + .get_value = mpc8xxx_gpio_get_value, + .set_value = mpc8xxx_gpio_set_value, + .get_open_drain = mpc8xxx_gpio_get_open_drain, + .set_open_drain = mpc8xxx_gpio_set_open_drain, + .get_function = mpc8xxx_gpio_get_function, +}; + +static const struct udevice_id mpc8xxx_gpio_ids[] = { + { .compatible = "fsl,pq3-gpio", .data = MPC8XXX_GPIO_TYPE }, + { .compatible = "fsl,mpc8308-gpio", .data = MPC8XXX_GPIO_TYPE }, + { .compatible = "fsl,mpc8349-gpio", .data = MPC8XXX_GPIO_TYPE }, + { .compatible = "fsl,mpc8572-gpio", .data = MPC8XXX_GPIO_TYPE}, + { .compatible = "fsl,mpc8610-gpio", .data = MPC8XXX_GPIO_TYPE}, + { .compatible = "fsl,mpc5121-gpio", .data = MPC5121_GPIO_TYPE, }, + { .compatible = "fsl,qoriq-gpio", .data = MPC8XXX_GPIO_TYPE }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(gpio_mpc8xxx) = { + .name = "gpio_mpc8xxx", + .id = UCLASS_GPIO, + .ops = &gpio_mpc8xxx_ops, +#if CONFIG_IS_ENABLED(OF_CONTROL) + .ofdata_to_platdata = mpc8xxx_gpio_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct mpc8xxx_gpio_plat), + .of_match = mpc8xxx_gpio_ids, +#endif + .probe = mpc8xxx_gpio_probe, + .priv_auto_alloc_size = sizeof(struct mpc8xxx_gpio_data), +}; diff --git a/drivers/gpio/pca953x_gpio.c b/drivers/gpio/pca953x_gpio.c index 791d1d15166..a8a5a89c05c 100644 --- a/drivers/gpio/pca953x_gpio.c +++ b/drivers/gpio/pca953x_gpio.c @@ -50,8 +50,6 @@ enum { #define MAX_BANK 5 #define BANK_SZ 8 -DECLARE_GLOBAL_DATA_PTR; - /* * struct pca953x_info - Data for pca953x * @@ -123,7 +121,8 @@ static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val) ret = dm_i2c_read(dev, reg << 1, val, info->bank_count); } else if (info->gpio_count == 40) { /* Auto increment */ - ret = dm_i2c_read(dev, (reg << 3) | 0x80, val, info->bank_count); + ret = dm_i2c_read(dev, (reg << 3) | 0x80, val, + info->bank_count); } else { dev_err(dev, "Unsupported now\n"); return -EINVAL; @@ -143,7 +142,7 @@ static int pca953x_is_output(struct udevice *dev, int offset) return !(info->reg_direction[bank] & (1 << off)); } -static int pca953x_get_value(struct udevice *dev, unsigned offset) +static int pca953x_get_value(struct udevice *dev, uint offset) { int ret; u8 val = 0; @@ -157,8 +156,7 @@ static int pca953x_get_value(struct udevice *dev, unsigned offset) return (val >> off) & 0x1; } -static int pca953x_set_value(struct udevice *dev, unsigned offset, - int value) +static int pca953x_set_value(struct udevice *dev, uint offset, int value) { struct pca953x_info *info = dev_get_platdata(dev); int bank = offset / BANK_SZ; @@ -180,7 +178,7 @@ static int pca953x_set_value(struct udevice *dev, unsigned offset, return 0; } -static int pca953x_set_direction(struct udevice *dev, unsigned offset, int dir) +static int pca953x_set_direction(struct udevice *dev, uint offset, int dir) { struct pca953x_info *info = dev_get_platdata(dev); int bank = offset / BANK_SZ; @@ -202,13 +200,12 @@ static int pca953x_set_direction(struct udevice *dev, unsigned offset, int dir) return 0; } -static int pca953x_direction_input(struct udevice *dev, unsigned offset) +static int pca953x_direction_input(struct udevice *dev, uint offset) { return pca953x_set_direction(dev, offset, PCA953X_DIRECTION_IN); } -static int pca953x_direction_output(struct udevice *dev, unsigned offset, - int value) +static int pca953x_direction_output(struct udevice *dev, uint offset, int value) { /* Configure output value. */ pca953x_set_value(dev, offset, value); @@ -219,7 +216,7 @@ static int pca953x_direction_output(struct udevice *dev, unsigned offset, return 0; } -static int pca953x_get_function(struct udevice *dev, unsigned offset) +static int pca953x_get_function(struct udevice *dev, uint offset) { if (pca953x_is_output(dev, offset)) return GPIOF_OUTPUT; @@ -231,7 +228,7 @@ static int pca953x_xlate(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args) { desc->offset = args->args[0]; - desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; + desc->flags = args->args[1] & (GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0); return 0; } @@ -254,7 +251,7 @@ static int pca953x_probe(struct udevice *dev) ulong driver_data; int ret; - addr = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", 0); + addr = dev_read_addr(dev); if (addr == 0) return -ENODEV; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index bc29611d783..a1b21fd1bd0 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -261,6 +261,20 @@ config MMC_UNIPHIER This selects support for the Matsushita SD/MMC Host Controller on SocioNext UniPhier and Renesas RCar SoCs. +config MMC_BCM2835 + bool "BCM2835 family custom SD/MMC Host Controller support" + depends on ARCH_BCM283X + depends on BLK && DM_MMC + depends on OF_CONTROL + default y + help + This selects support for the custom SD host controller in the BCM2835 + family of devices. + + If you have a BCM2835 platform with SD or MMC devices, say Y here. + + If unsure, say N. + config MMC_SANDBOX bool "Sandbox MMC support" depends on SANDBOX diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 64b6f21c613..42113e26032 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -64,3 +64,4 @@ obj-$(CONFIG_MMC_SDHCI_ZYNQ) += zynq_sdhci.o obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o +obj-$(CONFIG_MMC_BCM2835) += bcm2835_sdhost.o diff --git a/drivers/mmc/bcm2835_sdhost.c b/drivers/mmc/bcm2835_sdhost.c new file mode 100644 index 00000000000..1bf52a30196 --- /dev/null +++ b/drivers/mmc/bcm2835_sdhost.c @@ -0,0 +1,979 @@ +/* + * bcm2835 sdhost driver. + * + * The 2835 has two SD controllers: The Arasan sdhci controller + * (supported by the iproc driver) and a custom sdhost controller + * (supported by this driver). + * + * The sdhci controller supports both sdcard and sdio. The sdhost + * controller supports the sdcard only, but has better performance. + * Also note that the rpi3 has sdio wifi, so driving the sdcard with + * the sdhost controller allows to use the sdhci controller for wifi + * support. + * + * The configuration is done by devicetree via pin muxing. Both + * SD controller are available on the same pins (2 pin groups = pin 22 + * to 27 + pin 48 to 53). So it's possible to use both SD controllers + * at the same time with different pin groups. + * + * This code was ported to U-Boot by + * Alexander Graf <agraf@suse.de> + * and is based on drivers/mmc/host/bcm2835.c in Linux which is written by + * Phil Elwell <phil@raspberrypi.org> + * Copyright (C) 2015-2016 Raspberry Pi (Trading) Ltd. + * which is based on + * mmc-bcm2835.c by Gellert Weisz + * which is, in turn, based on + * sdhci-bcm2708.c by Broadcom + * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko + * sdhci.c and sdhci-pci.c by Pierre Ossman + * + * SPDX-License-Identifier: GPL-2.0 + */ +#include <clk.h> +#include <common.h> +#include <dm.h> +#include <mmc.h> +#include <asm/arch/msg.h> +#include <asm/unaligned.h> +#include <linux/compat.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/sizes.h> +#include <mach/gpio.h> +#include <power/regulator.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define msleep(a) udelay(a * 1000) + +#define SDCMD 0x00 /* Command to SD card - 16 R/W */ +#define SDARG 0x04 /* Argument to SD card - 32 R/W */ +#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */ +#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */ +#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */ +#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */ +#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */ +#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */ +#define SDHSTS 0x20 /* SD host status - 11 R/W */ +#define SDVDD 0x30 /* SD card power control - 1 R/W */ +#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */ +#define SDHCFG 0x38 /* Host configuration - 2 R/W */ +#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */ +#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */ +#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */ + +#define SDCMD_NEW_FLAG 0x8000 +#define SDCMD_FAIL_FLAG 0x4000 +#define SDCMD_BUSYWAIT 0x800 +#define SDCMD_NO_RESPONSE 0x400 +#define SDCMD_LONG_RESPONSE 0x200 +#define SDCMD_WRITE_CMD 0x80 +#define SDCMD_READ_CMD 0x40 +#define SDCMD_CMD_MASK 0x3f + +#define SDCDIV_MAX_CDIV 0x7ff + +#define SDHSTS_BUSY_IRPT 0x400 +#define SDHSTS_BLOCK_IRPT 0x200 +#define SDHSTS_SDIO_IRPT 0x100 +#define SDHSTS_REW_TIME_OUT 0x80 +#define SDHSTS_CMD_TIME_OUT 0x40 +#define SDHSTS_CRC16_ERROR 0x20 +#define SDHSTS_CRC7_ERROR 0x10 +#define SDHSTS_FIFO_ERROR 0x08 +#define SDHSTS_DATA_FLAG 0x01 + +#define SDHSTS_CLEAR_MASK (SDHSTS_BUSY_IRPT | \ + SDHSTS_BLOCK_IRPT | \ + SDHSTS_SDIO_IRPT | \ + SDHSTS_REW_TIME_OUT | \ + SDHSTS_CMD_TIME_OUT | \ + SDHSTS_CRC16_ERROR | \ + SDHSTS_CRC7_ERROR | \ + SDHSTS_FIFO_ERROR) + +#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC7_ERROR | \ + SDHSTS_CRC16_ERROR | \ + SDHSTS_REW_TIME_OUT | \ + SDHSTS_FIFO_ERROR) + +#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT | \ + SDHSTS_TRANSFER_ERROR_MASK) + +#define SDHCFG_BUSY_IRPT_EN BIT(10) +#define SDHCFG_BLOCK_IRPT_EN BIT(8) +#define SDHCFG_SDIO_IRPT_EN BIT(5) +#define SDHCFG_DATA_IRPT_EN BIT(4) +#define SDHCFG_SLOW_CARD BIT(3) +#define SDHCFG_WIDE_EXT_BUS BIT(2) +#define SDHCFG_WIDE_INT_BUS BIT(1) +#define SDHCFG_REL_CMD_LINE BIT(0) + +#define SDVDD_POWER_OFF 0 +#define SDVDD_POWER_ON 1 + +#define SDEDM_FORCE_DATA_MODE BIT(19) +#define SDEDM_CLOCK_PULSE BIT(20) +#define SDEDM_BYPASS BIT(21) + +#define SDEDM_FIFO_FILL_SHIFT 4 +#define SDEDM_FIFO_FILL_MASK 0x1f +static u32 edm_fifo_fill(u32 edm) +{ + return (edm >> SDEDM_FIFO_FILL_SHIFT) & SDEDM_FIFO_FILL_MASK; +} + +#define SDEDM_WRITE_THRESHOLD_SHIFT 9 +#define SDEDM_READ_THRESHOLD_SHIFT 14 +#define SDEDM_THRESHOLD_MASK 0x1f + +#define SDEDM_FSM_MASK 0xf +#define SDEDM_FSM_IDENTMODE 0x0 +#define SDEDM_FSM_DATAMODE 0x1 +#define SDEDM_FSM_READDATA 0x2 +#define SDEDM_FSM_WRITEDATA 0x3 +#define SDEDM_FSM_READWAIT 0x4 +#define SDEDM_FSM_READCRC 0x5 +#define SDEDM_FSM_WRITECRC 0x6 +#define SDEDM_FSM_WRITEWAIT1 0x7 +#define SDEDM_FSM_POWERDOWN 0x8 +#define SDEDM_FSM_POWERUP 0x9 +#define SDEDM_FSM_WRITESTART1 0xa +#define SDEDM_FSM_WRITESTART2 0xb +#define SDEDM_FSM_GENPULSES 0xc +#define SDEDM_FSM_WRITEWAIT2 0xd +#define SDEDM_FSM_STARTPOWDOWN 0xf + +#define SDDATA_FIFO_WORDS 16 + +#define FIFO_READ_THRESHOLD 4 +#define FIFO_WRITE_THRESHOLD 4 +#define SDDATA_FIFO_PIO_BURST 8 + +#define SDHST_TIMEOUT_MAX_USEC 100000 + +struct bcm2835_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +struct bcm2835_host { + void __iomem *ioaddr; + u32 phys_addr; + + int clock; /* Current clock speed */ + unsigned int max_clk; /* Max possible freq */ + unsigned int blocks; /* remaining PIO blocks */ + int irq; /* Device IRQ */ + + u32 ns_per_fifo_word; + + /* cached registers */ + u32 hcfg; + u32 cdiv; + + struct mmc_cmd *cmd; /* Current command */ + struct mmc_data *data; /* Current data request */ + bool data_complete:1;/* Data finished before cmd */ + bool use_busy:1; /* Wait for busy interrupt */ + bool wait_data_complete:1; /* Wait for data */ + + /* for threaded irq handler */ + bool irq_block; + bool irq_busy; + bool irq_data; + + struct udevice *dev; + struct mmc *mmc; + struct bcm2835_plat *plat; +}; + +static void bcm2835_dumpregs(struct bcm2835_host *host) +{ + dev_dbg(dev, "=========== REGISTER DUMP ===========\n"); + dev_dbg(dev, "SDCMD 0x%08x\n", readl(host->ioaddr + SDCMD)); + dev_dbg(dev, "SDARG 0x%08x\n", readl(host->ioaddr + SDARG)); + dev_dbg(dev, "SDTOUT 0x%08x\n", readl(host->ioaddr + SDTOUT)); + dev_dbg(dev, "SDCDIV 0x%08x\n", readl(host->ioaddr + SDCDIV)); + dev_dbg(dev, "SDRSP0 0x%08x\n", readl(host->ioaddr + SDRSP0)); + dev_dbg(dev, "SDRSP1 0x%08x\n", readl(host->ioaddr + SDRSP1)); + dev_dbg(dev, "SDRSP2 0x%08x\n", readl(host->ioaddr + SDRSP2)); + dev_dbg(dev, "SDRSP3 0x%08x\n", readl(host->ioaddr + SDRSP3)); + dev_dbg(dev, "SDHSTS 0x%08x\n", readl(host->ioaddr + SDHSTS)); + dev_dbg(dev, "SDVDD 0x%08x\n", readl(host->ioaddr + SDVDD)); + dev_dbg(dev, "SDEDM 0x%08x\n", readl(host->ioaddr + SDEDM)); + dev_dbg(dev, "SDHCFG 0x%08x\n", readl(host->ioaddr + SDHCFG)); + dev_dbg(dev, "SDHBCT 0x%08x\n", readl(host->ioaddr + SDHBCT)); + dev_dbg(dev, "SDHBLC 0x%08x\n", readl(host->ioaddr + SDHBLC)); + dev_dbg(dev, "===========================================\n"); +} + +static void bcm2835_reset_internal(struct bcm2835_host *host) +{ + u32 temp; + + writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD); + writel(0, host->ioaddr + SDCMD); + writel(0, host->ioaddr + SDARG); + /* Set timeout to a big enough value so we don't hit it */ + writel(0xf00000, host->ioaddr + SDTOUT); + writel(0, host->ioaddr + SDCDIV); + /* Clear status register */ + writel(SDHSTS_CLEAR_MASK, host->ioaddr + SDHSTS); + writel(0, host->ioaddr + SDHCFG); + writel(0, host->ioaddr + SDHBCT); + writel(0, host->ioaddr + SDHBLC); + + /* Limit fifo usage due to silicon bug */ + temp = readl(host->ioaddr + SDEDM); + temp &= ~((SDEDM_THRESHOLD_MASK << SDEDM_READ_THRESHOLD_SHIFT) | + (SDEDM_THRESHOLD_MASK << SDEDM_WRITE_THRESHOLD_SHIFT)); + temp |= (FIFO_READ_THRESHOLD << SDEDM_READ_THRESHOLD_SHIFT) | + (FIFO_WRITE_THRESHOLD << SDEDM_WRITE_THRESHOLD_SHIFT); + writel(temp, host->ioaddr + SDEDM); + /* Wait for FIFO threshold to populate */ + msleep(20); + writel(SDVDD_POWER_ON, host->ioaddr + SDVDD); + /* Wait for all components to go through power on cycle */ + msleep(20); + host->clock = 0; + writel(host->hcfg, host->ioaddr + SDHCFG); + writel(host->cdiv, host->ioaddr + SDCDIV); +} + +static int bcm2835_finish_command(struct bcm2835_host *host); + +static void bcm2835_wait_transfer_complete(struct bcm2835_host *host) +{ + int timediff; + u32 alternate_idle; + + alternate_idle = (host->data->flags & MMC_DATA_READ) ? + SDEDM_FSM_READWAIT : SDEDM_FSM_WRITESTART1; + + timediff = 0; + + while (1) { + u32 edm, fsm; + + edm = readl(host->ioaddr + SDEDM); + fsm = edm & SDEDM_FSM_MASK; + + if ((fsm == SDEDM_FSM_IDENTMODE) || + (fsm == SDEDM_FSM_DATAMODE)) + break; + if (fsm == alternate_idle) { + writel(edm | SDEDM_FORCE_DATA_MODE, + host->ioaddr + SDEDM); + break; + } + + /* Error out after 100000 register reads (~1s) */ + if (timediff++ == 100000) { + dev_err(host->dev, + "wait_transfer_complete - still waiting after %d retries\n", + timediff); + bcm2835_dumpregs(host); + return; + } + } +} + +static int bcm2835_transfer_block_pio(struct bcm2835_host *host, bool is_read) +{ + struct mmc_data *data = host->data; + size_t blksize = data->blocksize; + int copy_words; + u32 hsts = 0; + u32 *buf; + + if (blksize % sizeof(u32)) + return -EINVAL; + + buf = is_read ? (u32 *)data->dest : (u32 *)data->src; + + if (is_read) + data->dest += blksize; + else + data->src += blksize; + + copy_words = blksize / sizeof(u32); + + /* + * Copy all contents from/to the FIFO as far as it reaches, + * then wait for it to fill/empty again and rewind. + */ + while (copy_words) { + int burst_words, words; + u32 edm; + + burst_words = min(SDDATA_FIFO_PIO_BURST, copy_words); + edm = readl(host->ioaddr + SDEDM); + if (is_read) + words = edm_fifo_fill(edm); + else + words = SDDATA_FIFO_WORDS - edm_fifo_fill(edm); + + if (words < burst_words) { + int fsm_state = (edm & SDEDM_FSM_MASK); + + if ((is_read && + (fsm_state != SDEDM_FSM_READDATA && + fsm_state != SDEDM_FSM_READWAIT && + fsm_state != SDEDM_FSM_READCRC)) || + (!is_read && + (fsm_state != SDEDM_FSM_WRITEDATA && + fsm_state != SDEDM_FSM_WRITESTART1 && + fsm_state != SDEDM_FSM_WRITESTART2))) { + hsts = readl(host->ioaddr + SDHSTS); + printf("fsm %x, hsts %08x\n", fsm_state, hsts); + if (hsts & SDHSTS_ERROR_MASK) + break; + } + + continue; + } else if (words > copy_words) { + words = copy_words; + } + + copy_words -= words; + + /* Copy current chunk to/from the FIFO */ + while (words) { + if (is_read) + *(buf++) = readl(host->ioaddr + SDDATA); + else + writel(*(buf++), host->ioaddr + SDDATA); + words--; + } + } + + return 0; +} + +static int bcm2835_transfer_pio(struct bcm2835_host *host) +{ + u32 sdhsts; + bool is_read; + int ret = 0; + + is_read = (host->data->flags & MMC_DATA_READ) != 0; + ret = bcm2835_transfer_block_pio(host, is_read); + + if (host->wait_data_complete) + bcm2835_wait_transfer_complete(host); + + sdhsts = readl(host->ioaddr + SDHSTS); + if (sdhsts & (SDHSTS_CRC16_ERROR | + SDHSTS_CRC7_ERROR | + SDHSTS_FIFO_ERROR)) { + printf("%s transfer error - HSTS %08x\n", + is_read ? "read" : "write", sdhsts); + ret = -EILSEQ; + } else if ((sdhsts & (SDHSTS_CMD_TIME_OUT | + SDHSTS_REW_TIME_OUT))) { + printf("%s timeout error - HSTS %08x\n", + is_read ? "read" : "write", sdhsts); + ret = -ETIMEDOUT; + } + + return ret; +} + +static void bcm2835_set_transfer_irqs(struct bcm2835_host *host) +{ + u32 all_irqs = SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN | + SDHCFG_BUSY_IRPT_EN; + + host->hcfg = (host->hcfg & ~all_irqs) | + SDHCFG_DATA_IRPT_EN | + SDHCFG_BUSY_IRPT_EN; + + writel(host->hcfg, host->ioaddr + SDHCFG); +} + +static +void bcm2835_prepare_data(struct bcm2835_host *host, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + WARN_ON(host->data); + + host->data = data; + if (!data) + return; + + host->wait_data_complete = cmd->cmdidx != MMC_CMD_READ_MULTIPLE_BLOCK; + host->data_complete = false; + + /* Use PIO */ + host->blocks = data->blocks; + + bcm2835_set_transfer_irqs(host); + + writel(data->blocksize, host->ioaddr + SDHBCT); + writel(data->blocks, host->ioaddr + SDHBLC); +} + +static u32 bcm2835_read_wait_sdcmd(struct bcm2835_host *host) +{ + u32 value; + int ret; + int timeout_us = SDHST_TIMEOUT_MAX_USEC; + + ret = readl_poll_timeout(host->ioaddr + SDCMD, value, + !(value & SDCMD_NEW_FLAG), timeout_us); + if (ret == -ETIMEDOUT) + printf("%s: timeout (%d us)\n", __func__, timeout_us); + + return value; +} + +static int bcm2835_send_command(struct bcm2835_host *host, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + u32 sdcmd, sdhsts; + + WARN_ON(host->cmd); + + if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) { + printf("unsupported response type!\n"); + return -EINVAL; + } + + sdcmd = bcm2835_read_wait_sdcmd(host); + if (sdcmd & SDCMD_NEW_FLAG) { + printf("previous command never completed.\n"); + bcm2835_dumpregs(host); + return -EBUSY; + } + + host->cmd = cmd; + + /* Clear any error flags */ + sdhsts = readl(host->ioaddr + SDHSTS); + if (sdhsts & SDHSTS_ERROR_MASK) + writel(sdhsts, host->ioaddr + SDHSTS); + + bcm2835_prepare_data(host, cmd, data); + + writel(cmd->cmdarg, host->ioaddr + SDARG); + + sdcmd = cmd->cmdidx & SDCMD_CMD_MASK; + + host->use_busy = false; + if (!(cmd->resp_type & MMC_RSP_PRESENT)) { + sdcmd |= SDCMD_NO_RESPONSE; + } else { + if (cmd->resp_type & MMC_RSP_136) + sdcmd |= SDCMD_LONG_RESPONSE; + if (cmd->resp_type & MMC_RSP_BUSY) { + sdcmd |= SDCMD_BUSYWAIT; + host->use_busy = true; + } + } + + if (data) { + if (data->flags & MMC_DATA_WRITE) + sdcmd |= SDCMD_WRITE_CMD; + if (data->flags & MMC_DATA_READ) + sdcmd |= SDCMD_READ_CMD; + } + + writel(sdcmd | SDCMD_NEW_FLAG, host->ioaddr + SDCMD); + + return 0; +} + +static int bcm2835_transfer_complete(struct bcm2835_host *host) +{ + int ret = 0; + + WARN_ON(!host->data_complete); + + host->data = NULL; + + return ret; +} + +static void bcm2835_finish_data(struct bcm2835_host *host) +{ + host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN); + writel(host->hcfg, host->ioaddr + SDHCFG); + + host->data_complete = true; + + if (host->cmd) { + /* Data managed to finish before the + * command completed. Make sure we do + * things in the proper order. + */ + dev_dbg(dev, "Finished early - HSTS %08x\n", + readl(host->ioaddr + SDHSTS)); + } else { + bcm2835_transfer_complete(host); + } +} + +static int bcm2835_finish_command(struct bcm2835_host *host) +{ + struct mmc_cmd *cmd = host->cmd; + u32 sdcmd; + int ret = 0; + + sdcmd = bcm2835_read_wait_sdcmd(host); + + /* Check for errors */ + if (sdcmd & SDCMD_NEW_FLAG) { + printf("command never completed.\n"); + bcm2835_dumpregs(host); + return -EIO; + } else if (sdcmd & SDCMD_FAIL_FLAG) { + u32 sdhsts = readl(host->ioaddr + SDHSTS); + + /* Clear the errors */ + writel(SDHSTS_ERROR_MASK, host->ioaddr + SDHSTS); + + if (!(sdhsts & SDHSTS_CRC7_ERROR) || + (host->cmd->cmdidx != MMC_CMD_SEND_OP_COND)) { + if (sdhsts & SDHSTS_CMD_TIME_OUT) { + ret = -ETIMEDOUT; + } else { + printf("unexpected command %d error\n", + host->cmd->cmdidx); + bcm2835_dumpregs(host); + ret = -EILSEQ; + } + + return ret; + } + } + + if (cmd->resp_type & MMC_RSP_PRESENT) { + if (cmd->resp_type & MMC_RSP_136) { + int i; + + for (i = 0; i < 4; i++) { + cmd->response[3 - i] = + readl(host->ioaddr + SDRSP0 + i * 4); + } + } else { + cmd->response[0] = readl(host->ioaddr + SDRSP0); + } + } + + /* Processed actual command. */ + host->cmd = NULL; + if (host->data && host->data_complete) + ret = bcm2835_transfer_complete(host); + + return ret; +} + +static int bcm2835_check_cmd_error(struct bcm2835_host *host, u32 intmask) +{ + int ret = -EINVAL; + + if (!(intmask & SDHSTS_ERROR_MASK)) + return 0; + + if (!host->cmd) + return -EINVAL; + + printf("sdhost_busy_irq: intmask %08x\n", intmask); + if (intmask & SDHSTS_CRC7_ERROR) { + ret = -EILSEQ; + } else if (intmask & (SDHSTS_CRC16_ERROR | + SDHSTS_FIFO_ERROR)) { + ret = -EILSEQ; + } else if (intmask & (SDHSTS_REW_TIME_OUT | SDHSTS_CMD_TIME_OUT)) { + ret = -ETIMEDOUT; + } + bcm2835_dumpregs(host); + return ret; +} + +static int bcm2835_check_data_error(struct bcm2835_host *host, u32 intmask) +{ + int ret = 0; + + if (!host->data) + return 0; + if (intmask & (SDHSTS_CRC16_ERROR | SDHSTS_FIFO_ERROR)) + ret = -EILSEQ; + if (intmask & SDHSTS_REW_TIME_OUT) + ret = -ETIMEDOUT; + + if (ret) + printf("%s:%d %d\n", __func__, __LINE__, ret); + + return ret; +} + +static void bcm2835_busy_irq(struct bcm2835_host *host) +{ + if (WARN_ON(!host->cmd)) { + bcm2835_dumpregs(host); + return; + } + + if (WARN_ON(!host->use_busy)) { + bcm2835_dumpregs(host); + return; + } + host->use_busy = false; + + bcm2835_finish_command(host); +} + +static void bcm2835_data_irq(struct bcm2835_host *host, u32 intmask) +{ + int ret; + + /* + * There are no dedicated data/space available interrupt + * status bits, so it is necessary to use the single shared + * data/space available FIFO status bits. It is therefore not + * an error to get here when there is no data transfer in + * progress. + */ + if (!host->data) + return; + + ret = bcm2835_check_data_error(host, intmask); + if (ret) + goto finished; + + if (host->data->flags & MMC_DATA_WRITE) { + /* Use the block interrupt for writes after the first block */ + host->hcfg &= ~(SDHCFG_DATA_IRPT_EN); + host->hcfg |= SDHCFG_BLOCK_IRPT_EN; + writel(host->hcfg, host->ioaddr + SDHCFG); + bcm2835_transfer_pio(host); + } else { + bcm2835_transfer_pio(host); + host->blocks--; + if ((host->blocks == 0)) + goto finished; + } + return; + +finished: + host->hcfg &= ~(SDHCFG_DATA_IRPT_EN | SDHCFG_BLOCK_IRPT_EN); + writel(host->hcfg, host->ioaddr + SDHCFG); +} + +static void bcm2835_data_threaded_irq(struct bcm2835_host *host) +{ + if (!host->data) + return; + if ((host->blocks == 0)) + bcm2835_finish_data(host); +} + +static void bcm2835_block_irq(struct bcm2835_host *host) +{ + if (WARN_ON(!host->data)) { + bcm2835_dumpregs(host); + return; + } + + WARN_ON(!host->blocks); + if ((--host->blocks == 0)) + bcm2835_finish_data(host); + else + bcm2835_transfer_pio(host); +} + +static irqreturn_t bcm2835_irq(int irq, void *dev_id) +{ + irqreturn_t result = IRQ_NONE; + struct bcm2835_host *host = dev_id; + u32 intmask; + + intmask = readl(host->ioaddr + SDHSTS); + + writel(SDHSTS_BUSY_IRPT | + SDHSTS_BLOCK_IRPT | + SDHSTS_SDIO_IRPT | + SDHSTS_DATA_FLAG, + host->ioaddr + SDHSTS); + + if (intmask & SDHSTS_BLOCK_IRPT) { + bcm2835_check_data_error(host, intmask); + host->irq_block = true; + result = IRQ_WAKE_THREAD; + } + + if (intmask & SDHSTS_BUSY_IRPT) { + if (!bcm2835_check_cmd_error(host, intmask)) { + host->irq_busy = true; + result = IRQ_WAKE_THREAD; + } else { + result = IRQ_HANDLED; + } + } + + /* There is no true data interrupt status bit, so it is + * necessary to qualify the data flag with the interrupt + * enable bit. + */ + if ((intmask & SDHSTS_DATA_FLAG) && + (host->hcfg & SDHCFG_DATA_IRPT_EN)) { + bcm2835_data_irq(host, intmask); + host->irq_data = true; + result = IRQ_WAKE_THREAD; + } + + return result; +} + +static irqreturn_t bcm2835_threaded_irq(int irq, void *dev_id) +{ + struct bcm2835_host *host = dev_id; + + if (host->irq_block) { + host->irq_block = false; + bcm2835_block_irq(host); + } + + if (host->irq_busy) { + host->irq_busy = false; + bcm2835_busy_irq(host); + } + + if (host->irq_data) { + host->irq_data = false; + bcm2835_data_threaded_irq(host); + } + + return IRQ_HANDLED; +} + +static void bcm2835_irq_poll(struct bcm2835_host *host) +{ + u32 intmask; + + while (1) { + intmask = readl(host->ioaddr + SDHSTS); + if (intmask & (SDHSTS_BUSY_IRPT | SDHSTS_BLOCK_IRPT | + SDHSTS_SDIO_IRPT | SDHSTS_DATA_FLAG)) { + bcm2835_irq(0, host); + bcm2835_threaded_irq(0, host); + return; + } + } +} + +static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) +{ + int div; + + /* The SDCDIV register has 11 bits, and holds (div - 2). But + * in data mode the max is 50MHz wihout a minimum, and only + * the bottom 3 bits are used. Since the switch over is + * automatic (unless we have marked the card as slow...), + * chosen values have to make sense in both modes. Ident mode + * must be 100-400KHz, so can range check the requested + * clock. CMD15 must be used to return to data mode, so this + * can be monitored. + * + * clock 250MHz -> 0->125MHz, 1->83.3MHz, 2->62.5MHz, 3->50.0MHz + * 4->41.7MHz, 5->35.7MHz, 6->31.3MHz, 7->27.8MHz + * + * 623->400KHz/27.8MHz + * reset value (507)->491159/50MHz + * + * BUT, the 3-bit clock divisor in data mode is too small if + * the core clock is higher than 250MHz, so instead use the + * SLOW_CARD configuration bit to force the use of the ident + * clock divisor at all times. + */ + + if (clock < 100000) { + /* Can't stop the clock, but make it as slow as possible + * to show willing + */ + host->cdiv = SDCDIV_MAX_CDIV; + writel(host->cdiv, host->ioaddr + SDCDIV); + return; + } + + div = host->max_clk / clock; + if (div < 2) + div = 2; + if ((host->max_clk / div) > clock) + div++; + div -= 2; + + if (div > SDCDIV_MAX_CDIV) + div = SDCDIV_MAX_CDIV; + + clock = host->max_clk / (div + 2); + host->mmc->clock = clock; + + /* Calibrate some delays */ + + host->ns_per_fifo_word = (1000000000 / clock) * + ((host->mmc->card_caps & MMC_MODE_4BIT) ? 8 : 32); + + host->cdiv = div; + writel(host->cdiv, host->ioaddr + SDCDIV); + + /* Set the timeout to 500ms */ + writel(host->mmc->clock / 2, host->ioaddr + SDTOUT); +} + +static inline int is_power_of_2(u64 x) +{ + return !(x & (x - 1)); +} + +static int bcm2835_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct bcm2835_host *host = dev_get_priv(dev); + u32 edm, fsm; + int ret = 0; + + if (data && !is_power_of_2(data->blocksize)) { + printf("unsupported block size (%d bytes)\n", data->blocksize); + + if (cmd) + return -EINVAL; + } + + edm = readl(host->ioaddr + SDEDM); + fsm = edm & SDEDM_FSM_MASK; + + if ((fsm != SDEDM_FSM_IDENTMODE) && + (fsm != SDEDM_FSM_DATAMODE) && + (cmd && cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION)) { + printf("previous command (%d) not complete (EDM %08x)\n", + readl(host->ioaddr + SDCMD) & SDCMD_CMD_MASK, edm); + bcm2835_dumpregs(host); + + if (cmd) + return -EILSEQ; + + return 0; + } + + if (cmd) { + ret = bcm2835_send_command(host, cmd, data); + if (!ret && !host->use_busy) + ret = bcm2835_finish_command(host); + } + + /* Wait for completion of busy signal or data transfer */ + while (host->use_busy || host->data) + bcm2835_irq_poll(host); + + return ret; +} + +static int bcm2835_set_ios(struct udevice *dev) +{ + struct bcm2835_host *host = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + + if (!mmc->clock || mmc->clock != host->clock) { + bcm2835_set_clock(host, mmc->clock); + host->clock = mmc->clock; + } + + /* set bus width */ + host->hcfg &= ~SDHCFG_WIDE_EXT_BUS; + if (mmc->bus_width == 4) + host->hcfg |= SDHCFG_WIDE_EXT_BUS; + + host->hcfg |= SDHCFG_WIDE_INT_BUS; + + /* Disable clever clock switching, to cope with fast core clocks */ + host->hcfg |= SDHCFG_SLOW_CARD; + + writel(host->hcfg, host->ioaddr + SDHCFG); + + return 0; +} + +static void bcm2835_add_host(struct bcm2835_host *host) +{ + struct mmc_config *cfg = &host->plat->cfg; + + cfg->f_max = host->max_clk; + cfg->f_min = host->max_clk / SDCDIV_MAX_CDIV; + cfg->b_max = 65535; + + dev_dbg(dev, "f_max %d, f_min %d\n", + cfg->f_max, cfg->f_min); + + /* host controller capabilities */ + cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; + + /* report supported voltage ranges */ + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + + /* Set interrupt enables */ + host->hcfg = SDHCFG_BUSY_IRPT_EN; + + bcm2835_reset_internal(host); +} + +static int bcm2835_probe(struct udevice *dev) +{ + struct bcm2835_plat *plat = dev_get_platdata(dev); + struct bcm2835_host *host = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + + host->dev = dev; + host->mmc = mmc; + host->plat = plat; + upriv->mmc = &plat->mmc; + plat->cfg.name = dev->name; + + host->phys_addr = devfdt_get_addr(dev); + if (host->phys_addr == FDT_ADDR_T_NONE) + return -EINVAL; + + host->ioaddr = devm_ioremap(dev, host->phys_addr, SZ_256); + if (!host->ioaddr) + return -ENOMEM; + + host->max_clk = bcm2835_get_mmc_clock(); + + bcm2835_add_host(host); + + dev_dbg(dev, "%s -> OK\n", __func__); + + return 0; +} + +static const struct udevice_id bcm2835_match[] = { + { .compatible = "brcm,bcm2835-sdhost" }, + { } +}; + +static const struct dm_mmc_ops bcm2835_ops = { + .send_cmd = bcm2835_send_cmd, + .set_ios = bcm2835_set_ios, +}; + +static int bcm2835_bind(struct udevice *dev) +{ + struct bcm2835_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + +U_BOOT_DRIVER(bcm2835_sdhost) = { + .name = "bcm2835-sdhost", + .id = UCLASS_MMC, + .of_match = bcm2835_match, + .bind = bcm2835_bind, + .probe = bcm2835_probe, + .priv_auto_alloc_size = sizeof(struct bcm2835_host), + .platdata_auto_alloc_size = sizeof(struct bcm2835_plat), + .ops = &bcm2835_ops, +}; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7e8e4b0b276..0a4dd3c0cfd 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -306,5 +306,6 @@ source "drivers/pinctrl/renesas/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/exynos/Kconfig" source "drivers/pinctrl/mvebu/Kconfig" +source "drivers/pinctrl/broadcom/Kconfig" endmenu diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 8c04028dfbc..c7135d29f86 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o +obj-y += broadcom/ diff --git a/drivers/pinctrl/broadcom/Kconfig b/drivers/pinctrl/broadcom/Kconfig new file mode 100644 index 00000000000..4056782213d --- /dev/null +++ b/drivers/pinctrl/broadcom/Kconfig @@ -0,0 +1,7 @@ +config PINCTRL_BCM283X + depends on ARCH_BCM283X && PINCTRL_FULL && OF_CONTROL + default y + bool "Broadcom 283x family pin control driver" + help + Support pin multiplexing and pin configuration control on + Broadcom's 283x family of SoCs. diff --git a/drivers/pinctrl/broadcom/Makefile b/drivers/pinctrl/broadcom/Makefile new file mode 100644 index 00000000000..2a1e550f88e --- /dev/null +++ b/drivers/pinctrl/broadcom/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2018 Alexander Graf <agraf@suse.de> +# +# SPDX-License-Identifier: GPL-2.0 +# https://spdx.org/licenses + +obj-$(CONFIG_PINCTRL_BCM283X) += pinctrl-bcm283x.o diff --git a/drivers/pinctrl/broadcom/pinctrl-bcm283x.c b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c new file mode 100644 index 00000000000..6fbd6efbd2f --- /dev/null +++ b/drivers/pinctrl/broadcom/pinctrl-bcm283x.c @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2018 Alexander Graf <agraf@suse.de> + * + * Based on drivers/pinctrl/mvebu/pinctrl-mvebu.c and + * drivers/gpio/bcm2835_gpio.c + * + * This driver gets instantiated by the GPIO driver, because both devices + * share the same device node. + * + * SPDX-License-Identifier: GPL-2.0 + * https://spdx.org/licenses + */ + +#include <common.h> +#include <config.h> +#include <errno.h> +#include <dm.h> +#include <dm/pinctrl.h> +#include <dm/root.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/gpio.h> + +struct bcm283x_pinctrl_priv { + u32 *base_reg; +}; + +#define MAX_PINS_PER_BANK 16 + +static void bcm2835_gpio_set_func_id(struct udevice *dev, unsigned int gpio, + int func) +{ + struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev); + int reg_offset; + int field_offset; + + reg_offset = BCM2835_GPIO_FSEL_BANK(gpio); + field_offset = BCM2835_GPIO_FSEL_SHIFT(gpio); + + clrsetbits_le32(&priv->base_reg[reg_offset], + BCM2835_GPIO_FSEL_MASK << field_offset, + (func & BCM2835_GPIO_FSEL_MASK) << field_offset); +} + +static int bcm2835_gpio_get_func_id(struct udevice *dev, unsigned int gpio) +{ + struct bcm283x_pinctrl_priv *priv = dev_get_priv(dev); + u32 val; + + val = readl(&priv->base_reg[BCM2835_GPIO_FSEL_BANK(gpio)]); + + return (val >> BCM2835_GPIO_FSEL_SHIFT(gpio) & BCM2835_GPIO_FSEL_MASK); +} + +/* + * bcm283x_pinctrl_set_state: configure pin functions. + * @dev: the pinctrl device to be configured. + * @config: the state to be configured. + * @return: 0 in success + */ +int bcm283x_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + u32 pin_arr[MAX_PINS_PER_BANK]; + u32 function; + int i, len, pin_count = 0; + + if (!dev_read_prop(config, "brcm,pins", &len) || !len || + len & 0x3 || dev_read_u32_array(config, "brcm,pins", pin_arr, + len / sizeof(u32))) { + debug("Failed reading pins array for pinconfig %s (%d)\n", + config->name, len); + return -EINVAL; + } + + pin_count = len / sizeof(u32); + + function = dev_read_u32_default(config, "brcm,function", -1); + if (function < 0) { + debug("Failed reading function for pinconfig %s (%d)\n", + config->name, function); + return -EINVAL; + } + + for (i = 0; i < pin_count; i++) + bcm2835_gpio_set_func_id(dev, pin_arr[i], function); + + return 0; +} + +static int bcm283x_pinctrl_get_gpio_mux(struct udevice *dev, int banknum, + int index) +{ + if (banknum != 0) + return -EINVAL; + + return bcm2835_gpio_get_func_id(dev, index); +} + +static const struct udevice_id bcm2835_pinctrl_id[] = { + {.compatible = "brcm,bcm2835-gpio"}, + {} +}; + +int bcm283x_pinctl_probe(struct udevice *dev) +{ + struct bcm283x_pinctrl_priv *priv; + int ret; + struct udevice *pdev; + + priv = dev_get_priv(dev); + if (!priv) { + debug("%s: Failed to get private\n", __func__); + return -EINVAL; + } + + priv->base_reg = dev_read_addr_ptr(dev); + if (priv->base_reg == (void *)FDT_ADDR_T_NONE) { + debug("%s: Failed to get base address\n", __func__); + return -EINVAL; + } + + /* Create GPIO device as well */ + ret = device_bind(dev, lists_driver_lookup_name("gpio_bcm2835"), + "gpio_bcm2835", NULL, dev_of_offset(dev), &pdev); + if (ret) { + /* + * While we really want the pinctrl driver to work to make + * devices go where they should go, the GPIO controller is + * not quite as crucial as it's only rarely used, so don't + * fail here. + */ + printf("Failed to bind GPIO driver\n"); + } + + return 0; +} + +static struct pinctrl_ops bcm283x_pinctrl_ops = { + .set_state = bcm283x_pinctrl_set_state, + .get_gpio_mux = bcm283x_pinctrl_get_gpio_mux, +}; + +U_BOOT_DRIVER(pinctrl_bcm283x) = { + .name = "bcm283x_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = of_match_ptr(bcm2835_pinctrl_id), + .priv_auto_alloc_size = sizeof(struct bcm283x_pinctrl_priv), + .ops = &bcm283x_pinctrl_ops, + .probe = bcm283x_pinctl_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7b20b479646..3ffedba5256 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -388,6 +388,22 @@ config ATMEL_USART configured in the device tree, and input clock frequency can be got from the clk node. +config BCM283X_MU_SERIAL + bool "Support for BCM283x Mini-UART" + depends on DM_SERIAL && ARCH_BCM283X + default y + help + Select this to enable Mini-UART support on BCM283X family of SoCs. + +config BCM283X_PL011_SERIAL + bool "Support for BCM283x PL011 UART" + depends on PL01X_SERIAL && ARCH_BCM283X + default y + help + Select this to enable an overriding PL011 driver for BCM283X SoCs + that supports automatic disable, so that it only gets used when + the UART is actually muxed. + config BCM6345_SERIAL bool "Support for BCM6345 UART" depends on DM_SERIAL && ARCH_BMIPS @@ -447,6 +463,24 @@ config INTEL_MID_SERIAL Select this to enable a UART for Intel MID platforms. This uses the ns16550 driver as a library. +config PL010_SERIAL + bool "ARM PL010 driver" + depends on !DM_SERIAL + help + Select this to enable a UART for platforms using PL010. + +config PL011_SERIAL + bool "ARM PL011 driver" + depends on !DM_SERIAL + help + Select this to enable a UART for platforms using PL011. + +config PL01X_SERIAL + bool "ARM PL010 and PL011 driver" + depends on DM_SERIAL + help + Select this to enable a UART for platforms using PL010 or PL011. + config ROCKCHIP_SERIAL bool "Rockchip on-chip UART support" depends on DM_SERIAL && SPL_OF_PLATDATA diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 5ef603ab152..cac9a8b3121 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_STI_ASC_SERIAL) += serial_sti_asc.o obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o +obj-$(CONFIG_BCM283X_PL011_SERIAL) += serial_bcm283x_pl011.o obj-$(CONFIG_MSM_SERIAL) += serial_msm.o obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index c702304e79b..6f9ce689cff 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -339,9 +339,9 @@ static int ns16550_serial_pending(struct udevice *dev, bool input) struct NS16550 *const com_port = dev_get_priv(dev); if (input) - return serial_in(&com_port->lsr) & UART_LSR_DR ? 1 : 0; + return (serial_in(&com_port->lsr) & UART_LSR_DR) ? 1 : 0; else - return serial_in(&com_port->lsr) & UART_LSR_THRE ? 0 : 1; + return (serial_in(&com_port->lsr) & UART_LSR_THRE) ? 0 : 1; } static int ns16550_serial_getc(struct udevice *dev) diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 2e5116f7cee..68ca2d09d1b 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -74,6 +74,7 @@ static void serial_find_console_or_panic(void) { const void *blob = gd->fdt_blob; struct udevice *dev; + int ret; if (CONFIG_IS_ENABLED(OF_PLATDATA)) { uclass_first_device(UCLASS_SERIAL, &dev); @@ -104,8 +105,8 @@ static void serial_find_console_or_panic(void) * from 1!). * * Failing that, get the device with sequence number 0, or in - * extremis just the first serial device we can find. But we - * insist on having a console (even if it is silent). + * extremis just the first working serial device we can find. + * But we insist on having a console (even if it is silent). */ #ifdef CONFIG_CONS_INDEX #define INDEX (CONFIG_CONS_INDEX - 1) @@ -113,10 +114,22 @@ static void serial_find_console_or_panic(void) #define INDEX 0 #endif if (!uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) || - !uclass_get_device(UCLASS_SERIAL, INDEX, &dev) || - (!uclass_first_device(UCLASS_SERIAL, &dev) && dev)) { - gd->cur_serial_dev = dev; - return; + !uclass_get_device(UCLASS_SERIAL, INDEX, &dev)) { + if (dev->flags & DM_FLAG_ACTIVATED) { + gd->cur_serial_dev = dev; + return; + } + } + + /* Search for any working device */ + for (ret = uclass_first_device_check(UCLASS_SERIAL, &dev); + dev; + ret = uclass_next_device_check(&dev)) { + if (!ret) { + /* Device did succeed probing */ + gd->cur_serial_dev = dev; + return; + } } #undef INDEX } diff --git a/drivers/serial/serial_bcm283x_mu.c b/drivers/serial/serial_bcm283x_mu.c index 41c26b3d931..40029fadbcb 100644 --- a/drivers/serial/serial_bcm283x_mu.c +++ b/drivers/serial/serial_bcm283x_mu.c @@ -19,13 +19,12 @@ #include <dm.h> #include <errno.h> #include <watchdog.h> +#include <asm/gpio.h> #include <asm/io.h> #include <serial.h> #include <dm/platform_data/serial_bcm283x_mu.h> +#include <dm/pinctrl.h> #include <linux/compiler.h> -#include <fdtdec.h> - -DECLARE_GLOBAL_DATA_PTR; struct bcm283x_mu_regs { u32 io; @@ -59,7 +58,7 @@ static int bcm283x_mu_serial_setbrg(struct udevice *dev, int baudrate) struct bcm283x_mu_regs *regs = priv->regs; u32 divider; - if (plat->disabled || plat->skip_init) + if (plat->skip_init) return 0; divider = plat->clock / (baudrate * 8); @@ -75,9 +74,6 @@ static int bcm283x_mu_serial_probe(struct udevice *dev) struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev); struct bcm283x_mu_priv *priv = dev_get_priv(dev); - if (plat->disabled) - return -ENODEV; - priv->regs = (struct bcm283x_mu_regs *)plat->base; return 0; @@ -85,14 +81,10 @@ static int bcm283x_mu_serial_probe(struct udevice *dev) static int bcm283x_mu_serial_getc(struct udevice *dev) { - struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev); struct bcm283x_mu_priv *priv = dev_get_priv(dev); struct bcm283x_mu_regs *regs = priv->regs; u32 data; - if (plat->disabled) - return -EAGAIN; - /* Wait until there is data in the FIFO */ if (!(readl(®s->lsr) & BCM283X_MU_LSR_RX_READY)) return -EAGAIN; @@ -104,13 +96,9 @@ static int bcm283x_mu_serial_getc(struct udevice *dev) static int bcm283x_mu_serial_putc(struct udevice *dev, const char data) { - struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev); struct bcm283x_mu_priv *priv = dev_get_priv(dev); struct bcm283x_mu_regs *regs = priv->regs; - if (plat->disabled) - return 0; - /* Wait until there is space in the FIFO */ if (!(readl(®s->lsr) & BCM283X_MU_LSR_TX_EMPTY)) return -EAGAIN; @@ -123,14 +111,10 @@ static int bcm283x_mu_serial_putc(struct udevice *dev, const char data) static int bcm283x_mu_serial_pending(struct udevice *dev, bool input) { - struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev); struct bcm283x_mu_priv *priv = dev_get_priv(dev); struct bcm283x_mu_regs *regs = priv->regs; unsigned int lsr; - if (plat->disabled) - return 0; - lsr = readl(®s->lsr); if (input) { @@ -154,21 +138,50 @@ static const struct udevice_id bcm283x_mu_serial_id[] = { {} }; +/* + * Check if this serial device is muxed + * + * The serial device will only work properly if it has been muxed to the serial + * pins by firmware. Check whether that happened here. + * + * @return true if serial device is muxed, false if not + */ +static bool bcm283x_is_serial_muxed(void) +{ + int serial_gpio = 15; + struct udevice *dev; + + if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev) + return false; + + if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT5) + return false; + + return true; +} + static int bcm283x_mu_serial_ofdata_to_platdata(struct udevice *dev) { struct bcm283x_mu_serial_platdata *plat = dev_get_platdata(dev); fdt_addr_t addr; + /* Don't spawn the device if it's not muxed */ + if (!bcm283x_is_serial_muxed()) + return -ENODEV; + addr = devfdt_get_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; plat->base = addr; - plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "clock", - 1); - plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), - "skip-init"); - plat->disabled = false; + plat->clock = dev_read_u32_default(dev, "clock", 1); + + /* + * TODO: Reinitialization doesn't always work for now, just skip + * init always - we know we're already initialized + */ + plat->skip_init = true; + return 0; } #endif diff --git a/drivers/serial/serial_bcm283x_pl011.c b/drivers/serial/serial_bcm283x_pl011.c new file mode 100644 index 00000000000..bfd39f84f35 --- /dev/null +++ b/drivers/serial/serial_bcm283x_pl011.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 Alexander Graf <agraf@suse.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <asm/gpio.h> +#include <dm/pinctrl.h> +#include <dm/platform_data/serial_pl01x.h> +#include "serial_pl01x_internal.h" + +/* + * Check if this serial device is muxed + * + * The serial device will only work properly if it has been muxed to the serial + * pins by firmware. Check whether that happened here. + * + * @return true if serial device is muxed, false if not + */ +static bool bcm283x_is_serial_muxed(void) +{ + int serial_gpio = 15; + struct udevice *dev; + + if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev) + return false; + + if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT0) + return false; + + return true; +} + +static int bcm283x_pl011_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct pl01x_serial_platdata *plat = dev_get_platdata(dev); + int ret; + + /* Don't spawn the device if it's not muxed */ + if (!bcm283x_is_serial_muxed()) + return -ENODEV; + + ret = pl01x_serial_ofdata_to_platdata(dev); + if (ret) + return ret; + + /* + * TODO: Reinitialization doesn't always work for now, just skip + * init always - we know we're already initialized + */ + plat->skip_init = true; + + return 0; +} + +static const struct udevice_id bcm283x_pl011_serial_id[] = { + {.compatible = "brcm,bcm2835-pl011", .data = TYPE_PL011}, + {} +}; + +U_BOOT_DRIVER(bcm283x_pl011_uart) = { + .name = "bcm283x_pl011", + .id = UCLASS_SERIAL, + .of_match = of_match_ptr(bcm283x_pl011_serial_id), + .ofdata_to_platdata = of_match_ptr(bcm283x_pl011_serial_ofdata_to_platdata), + .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata), + .probe = pl01x_serial_probe, + .ops = &pl01x_serial_ops, + .flags = DM_FLAG_PRE_RELOC, + .priv_auto_alloc_size = sizeof(struct pl01x_priv), +}; diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 4ec0f29c429..23d9d839cbc 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -20,7 +20,6 @@ #include <dm/platform_data/serial_pl01x.h> #include <linux/compiler.h> #include "serial_pl01x_internal.h" -#include <fdtdec.h> DECLARE_GLOBAL_DATA_PTR; @@ -274,11 +273,6 @@ __weak struct serial_device *default_serial_console(void) #ifdef CONFIG_DM_SERIAL -struct pl01x_priv { - struct pl01x_regs *regs; - enum pl01x_type type; -}; - static int pl01x_serial_setbrg(struct udevice *dev, int baudrate) { struct pl01x_serial_platdata *plat = dev_get_platdata(dev); @@ -292,7 +286,7 @@ static int pl01x_serial_setbrg(struct udevice *dev, int baudrate) return 0; } -static int pl01x_serial_probe(struct udevice *dev) +int pl01x_serial_probe(struct udevice *dev) { struct pl01x_serial_platdata *plat = dev_get_platdata(dev); struct pl01x_priv *priv = dev_get_priv(dev); @@ -330,7 +324,7 @@ static int pl01x_serial_pending(struct udevice *dev, bool input) return fr & UART_PL01x_FR_TXFF ? 0 : 1; } -static const struct dm_serial_ops pl01x_serial_ops = { +const struct dm_serial_ops pl01x_serial_ops = { .putc = pl01x_serial_putc, .pending = pl01x_serial_pending, .getc = pl01x_serial_getc, @@ -344,7 +338,7 @@ static const struct udevice_id pl01x_serial_id[] ={ {} }; -static int pl01x_serial_ofdata_to_platdata(struct udevice *dev) +int pl01x_serial_ofdata_to_platdata(struct udevice *dev) { struct pl01x_serial_platdata *plat = dev_get_platdata(dev); fdt_addr_t addr; @@ -354,11 +348,10 @@ static int pl01x_serial_ofdata_to_platdata(struct udevice *dev) return -EINVAL; plat->base = addr; - plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "clock", - 1); + plat->clock = dev_read_u32_default(dev, "clock", 1); plat->type = dev_get_driver_data(dev); - plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), - "skip-init"); + plat->skip_init = dev_read_bool(dev, "skip-init"); + return 0; } #endif diff --git a/drivers/serial/serial_pl01x_internal.h b/drivers/serial/serial_pl01x_internal.h index 288a4f19f56..c56dd54c7b8 100644 --- a/drivers/serial/serial_pl01x_internal.h +++ b/drivers/serial/serial_pl01x_internal.h @@ -38,7 +38,20 @@ struct pl01x_regs { u32 pl011_lcrh; /* 0x2C Line control register */ u32 pl011_cr; /* 0x30 Control register */ }; -#endif + +#ifdef CONFIG_DM_SERIAL + +int pl01x_serial_ofdata_to_platdata(struct udevice *dev); +int pl01x_serial_probe(struct udevice *dev); +extern const struct dm_serial_ops pl01x_serial_ops; + +struct pl01x_priv { + struct pl01x_regs *regs; + enum pl01x_type type; +}; + +#endif /* CONFIG_DM_SERIAL */ +#endif /* !__ASSEMBLY__ */ #define UART_PL01x_RSR_OE 0x08 #define UART_PL01x_RSR_BE 0x04 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 79df888fcec..7f9ba24cfe7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -14,7 +14,6 @@ endif obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o obj-$(CONFIG_USB_ATMEL) += ohci-at91.o obj-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o -obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c deleted file mode 100644 index 32874d73de8..00000000000 --- a/drivers/usb/host/isp116x-hcd.c +++ /dev/null @@ -1,1323 +0,0 @@ -/* - * ISP116x HCD (Host Controller Driver) for u-boot. - * - * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it> - * - * SPDX-License-Identifier: GPL-2.0+ - * - * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c" - * (original copyright message follows): - * - * (C) Copyright 2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * This code is based on linux driver for sl811hs chip, source at - * drivers/usb/host/sl811.c: - * - * SL811 Host Controller Interface driver for USB. - * - * Copyright (c) 2003/06, Courage Co., Ltd. - * - * Based on: - * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, - * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, - * Adam Richter, Gregory P. Smith; - * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> - * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> - * - * [[GNU/GPL disclaimer]] - * - * and in part from AU1x00 OHCI HCD driver "u-boot/arch/mips/cpu/au1x00_usb_ohci.c" - * (original copyright message follows): - * - * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00. - * - * (C) Copyright 2003 - * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> - * - * [[GNU/GPL disclaimer]] - * - * Note: Part of this code has been derived from linux - */ - -#include <common.h> -#include <asm/io.h> -#include <usb.h> -#include <malloc.h> -#include <linux/list.h> - -/* - * ISP116x chips require certain delays between accesses to its - * registers. The following timing options exist. - * - * 1. Configure your memory controller (the best) - * 2. Use ndelay (easiest, poorest). For that, enable the following macro. - * - * Value is in microseconds. - */ -#ifdef ISP116X_HCD_USE_UDELAY -#define UDELAY 1 -#endif - -/* - * On some (slowly?) machines an extra delay after data packing into - * controller's FIFOs is required, * otherwise you may get the following - * error: - * - * uboot> usb start - * (Re)start USB... - * USB: scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT - * isp116x: isp116x_submit_job: ****** FIFO not ready! ****** - * - * USB device not responding, giving up (status=4) - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * isp116x: isp116x_submit_job: ****** FIFO not empty! ****** - * 3 USB Device(s) found - * scanning bus for storage devices... 0 Storage Device(s) found - * - * Value is in milliseconds. - */ -#ifdef ISP116X_HCD_USE_EXTRA_DELAY -#define EXTRA_DELAY 2 -#endif - -/* - * Enable the following defines if you wish enable debugging messages. - */ -#undef DEBUG /* enable debugging messages */ -#undef TRACE /* enable tracing code */ -#undef VERBOSE /* verbose debugging messages */ - -#include "isp116x.h" - -#define DRIVER_VERSION "08 Jan 2007" -static const char hcd_name[] = "isp116x-hcd"; - -struct isp116x isp116x_dev; -struct isp116x_platform_data isp116x_board; -static int got_rhsc; /* root hub status change */ -struct usb_device *devgone; /* device which was disconnected */ -static int rh_devnum; /* address of Root Hub endpoint */ - -/* ------------------------------------------------------------------------- */ - -static int isp116x_reset(struct isp116x *isp116x); - -/* --- Debugging functions ------------------------------------------------- */ - -#define isp116x_show_reg(d, r) { \ - if ((r) < 0x20) { \ - DBG("%-12s[%02x]: %08x", #r, \ - r, isp116x_read_reg32(d, r)); \ - } else { \ - DBG("%-12s[%02x]: %04x", #r, \ - r, isp116x_read_reg16(d, r)); \ - } \ -} - -#define isp116x_show_regs(d) { \ - isp116x_show_reg(d, HCREVISION); \ - isp116x_show_reg(d, HCCONTROL); \ - isp116x_show_reg(d, HCCMDSTAT); \ - isp116x_show_reg(d, HCINTSTAT); \ - isp116x_show_reg(d, HCINTENB); \ - isp116x_show_reg(d, HCFMINTVL); \ - isp116x_show_reg(d, HCFMREM); \ - isp116x_show_reg(d, HCFMNUM); \ - isp116x_show_reg(d, HCLSTHRESH); \ - isp116x_show_reg(d, HCRHDESCA); \ - isp116x_show_reg(d, HCRHDESCB); \ - isp116x_show_reg(d, HCRHSTATUS); \ - isp116x_show_reg(d, HCRHPORT1); \ - isp116x_show_reg(d, HCRHPORT2); \ - isp116x_show_reg(d, HCHWCFG); \ - isp116x_show_reg(d, HCDMACFG); \ - isp116x_show_reg(d, HCXFERCTR); \ - isp116x_show_reg(d, HCuPINT); \ - isp116x_show_reg(d, HCuPINTENB); \ - isp116x_show_reg(d, HCCHIPID); \ - isp116x_show_reg(d, HCSCRATCH); \ - isp116x_show_reg(d, HCITLBUFLEN); \ - isp116x_show_reg(d, HCATLBUFLEN); \ - isp116x_show_reg(d, HCBUFSTAT); \ - isp116x_show_reg(d, HCRDITL0LEN); \ - isp116x_show_reg(d, HCRDITL1LEN); \ -} - -#if defined(TRACE) - -static int isp116x_get_current_frame_number(struct usb_device *usb_dev) -{ - struct isp116x *isp116x = &isp116x_dev; - - return isp116x_read_reg32(isp116x, HCFMNUM); -} - -static void dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, char *str) -{ -#if defined(VERBOSE) - int i; -#endif - - DBG("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d stat:%#lx", - str, - isp116x_get_current_frame_number(dev), - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? 'O' : 'I', - usb_pipetype(pipe) < 2 ? - (usb_pipeint(pipe) ? - "INTR" : "ISOC") : - (usb_pipecontrol(pipe) ? "CTRL" : "BULK"), len, dev->status); -#if defined(VERBOSE) - if (len > 0 && buffer) { - printf(__FILE__ ": data(%d):", len); - for (i = 0; i < 16 && i < len; i++) - printf(" %02x", ((__u8 *) buffer)[i]); - printf("%s\n", i < len ? "..." : ""); - } -#endif -} - -#define PTD_DIR_STR(ptd) ({char __c; \ - switch(PTD_GET_DIR(ptd)){ \ - case 0: __c = 's'; break; \ - case 1: __c = 'o'; break; \ - default: __c = 'i'; break; \ - }; __c;}) - -/* - Dump PTD info. The code documents the format - perfectly, right :) -*/ -static inline void dump_ptd(struct ptd *ptd) -{ -#if defined(VERBOSE) - int k; -#endif - - DBG("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x", - PTD_GET_CC(ptd), - PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), - PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), - PTD_GET_TOGGLE(ptd), - PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)); -#if defined(VERBOSE) - printf("isp116x: %s: PTD(byte): ", __FUNCTION__); - for (k = 0; k < sizeof(struct ptd); ++k) - printf("%02x ", ((u8 *) ptd)[k]); - printf("\n"); -#endif -} - -static inline void dump_ptd_data(struct ptd *ptd, u8 * buf, int type) -{ -#if defined(VERBOSE) - int k; - - if (type == 0 /* 0ut data */ ) { - printf("isp116x: %s: out data: ", __FUNCTION__); - for (k = 0; k < PTD_GET_LEN(ptd); ++k) - printf("%02x ", ((u8 *) buf)[k]); - printf("\n"); - } - if (type == 1 /* 1n data */ ) { - printf("isp116x: %s: in data: ", __FUNCTION__); - for (k = 0; k < PTD_GET_COUNT(ptd); ++k) - printf("%02x ", ((u8 *) buf)[k]); - printf("\n"); - } - - if (PTD_GET_LAST(ptd)) - DBG("--- last PTD ---"); -#endif -} - -#else - -#define dump_msg(dev, pipe, buffer, len, str) do { } while (0) -#define dump_pkt(dev, pipe, buffer, len, setup, str, small) do {} while (0) - -#define dump_ptd(ptd) do {} while (0) -#define dump_ptd_data(ptd, buf, type) do {} while (0) - -#endif - -/* --- Virtual Root Hub ---------------------------------------------------- */ - -#include <usbroothubdes.h> - -/* - * Hub class-specific descriptor is constructed dynamically - */ - -/* --- Virtual root hub management functions ------------------------------- */ - -static int rh_check_port_status(struct isp116x *isp116x) -{ - u32 temp, ndp, i; - int res; - - res = -1; - temp = isp116x_read_reg32(isp116x, HCRHSTATUS); - ndp = (temp & RH_A_NDP); - for (i = 0; i < ndp; i++) { - temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - -/* --- HC management functions --------------------------------------------- */ - -/* Write len bytes to fifo, pad till 32-bit boundary - */ -static void write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, int len) -{ - u8 *dp = (u8 *) buf; - u16 *dp2 = (u16 *) buf; - u16 w; - int quot = len % 4; - - if ((unsigned long)dp2 & 1) { - /* not aligned */ - for (; len > 1; len -= 2) { - w = *dp++; - w |= *dp++ << 8; - isp116x_raw_write_data16(isp116x, w); - } - if (len) - isp116x_write_data16(isp116x, (u16) * dp); - } else { - /* aligned */ - for (; len > 1; len -= 2) - isp116x_raw_write_data16(isp116x, *dp2++); - if (len) - isp116x_write_data16(isp116x, 0xff & *((u8 *) dp2)); - } - if (quot == 1 || quot == 2) - isp116x_raw_write_data16(isp116x, 0); -} - -/* Read len bytes from fifo and then read till 32-bit boundary - */ -static void read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, int len) -{ - u8 *dp = (u8 *) buf; - u16 *dp2 = (u16 *) buf; - u16 w; - int quot = len % 4; - - if ((unsigned long)dp2 & 1) { - /* not aligned */ - for (; len > 1; len -= 2) { - w = isp116x_raw_read_data16(isp116x); - *dp++ = w & 0xff; - *dp++ = (w >> 8) & 0xff; - } - if (len) - *dp = 0xff & isp116x_read_data16(isp116x); - } else { - /* aligned */ - for (; len > 1; len -= 2) - *dp2++ = isp116x_raw_read_data16(isp116x); - if (len) - *(u8 *) dp2 = 0xff & isp116x_read_data16(isp116x); - } - if (quot == 1 || quot == 2) - isp116x_raw_read_data16(isp116x); -} - -/* Write PTD's and data for scheduled transfers into the fifo ram. - * Fifo must be empty and ready */ -static void pack_fifo(struct isp116x *isp116x, struct usb_device *dev, - unsigned long pipe, struct ptd *ptd, int n, void *data, - int len) -{ - int buflen = n * sizeof(struct ptd) + len; - int i, done; - - DBG("--- pack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); - - isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); - isp116x_write_reg16(isp116x, HCXFERCTR, buflen); - isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET); - - done = 0; - for (i = 0; i < n; i++) { - DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); - - dump_ptd(&ptd[i]); - isp116x_write_data16(isp116x, ptd[i].count); - isp116x_write_data16(isp116x, ptd[i].mps); - isp116x_write_data16(isp116x, ptd[i].len); - isp116x_write_data16(isp116x, ptd[i].faddr); - - dump_ptd_data(&ptd[i], (__u8 *) data + done, 0); - write_ptddata_to_fifo(isp116x, - (__u8 *) data + done, - PTD_GET_LEN(&ptd[i])); - - done += PTD_GET_LEN(&ptd[i]); - } -} - -/* Read the processed PTD's and data from fifo ram back to URBs' buffers. - * Fifo must be full and done */ -static int unpack_fifo(struct isp116x *isp116x, struct usb_device *dev, - unsigned long pipe, struct ptd *ptd, int n, void *data, - int len) -{ - int buflen = n * sizeof(struct ptd) + len; - int i, done, cc, ret; - - isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT); - isp116x_write_reg16(isp116x, HCXFERCTR, buflen); - isp116x_write_addr(isp116x, HCATLPORT); - - ret = TD_CC_NOERROR; - done = 0; - for (i = 0; i < n; i++) { - DBG("i=%d - done=%d - len=%d", i, done, PTD_GET_LEN(&ptd[i])); - - ptd[i].count = isp116x_read_data16(isp116x); - ptd[i].mps = isp116x_read_data16(isp116x); - ptd[i].len = isp116x_read_data16(isp116x); - ptd[i].faddr = isp116x_read_data16(isp116x); - dump_ptd(&ptd[i]); - - read_ptddata_from_fifo(isp116x, - (__u8 *) data + done, - PTD_GET_LEN(&ptd[i])); - dump_ptd_data(&ptd[i], (__u8 *) data + done, 1); - - done += PTD_GET_LEN(&ptd[i]); - - cc = PTD_GET_CC(&ptd[i]); - - /* Data underrun means basically that we had more buffer space than - * the function had data. It is perfectly normal but upper levels have - * to know how much we actually transferred. - */ - if (cc == TD_NOTACCESSED || - (cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN))) - ret = cc; - } - - DBG("--- unpack buffer %p - %d bytes (fifo %d) ---", data, len, buflen); - - return ret; -} - -/* Interrupt handling - */ -static int isp116x_interrupt(struct isp116x *isp116x) -{ - u16 irqstat; - u32 intstat; - int ret = 0; - - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - irqstat = isp116x_read_reg16(isp116x, HCuPINT); - isp116x_write_reg16(isp116x, HCuPINT, irqstat); - DBG("------ irqstat %x ------", irqstat); - - if (irqstat & HCuPINT_ATL) { - DBG("------ HCuPINT_ATL ------"); - udelay(500); - ret = 1; - } - - if (irqstat & HCuPINT_OPR) { - intstat = isp116x_read_reg32(isp116x, HCINTSTAT); - isp116x_write_reg32(isp116x, HCINTSTAT, intstat); - DBG("------ HCuPINT_OPR %x ------", intstat); - - if (intstat & HCINT_UE) { - ERR("unrecoverable error, controller disabled"); - - /* FIXME: be optimistic, hope that bug won't repeat - * often. Make some non-interrupt context restart the - * controller. Count and limit the retries though; - * either hardware or software errors can go forever... - */ - isp116x_reset(isp116x); - ret = -1; - return -1; - } - - if (intstat & HCINT_RHSC) { - got_rhsc = 1; - ret = 1; - /* When root hub or any of its ports is going - to come out of suspend, it may take more - than 10ms for status bits to stabilize. */ - mdelay(20); - } - - if (intstat & HCINT_SO) { - ERR("schedule overrun"); - ret = -1; - } - - irqstat &= ~HCuPINT_OPR; - } - - return ret; -} - -/* With one PTD we can transfer almost 1K in one go; - * HC does the splitting into endpoint digestible transactions - */ -struct ptd ptd[1]; - -static inline int max_transfer_len(struct usb_device *dev, unsigned long pipe) -{ - unsigned mpck = usb_maxpacket(dev, pipe); - - /* One PTD can transfer 1023 bytes but try to always - * transfer multiples of endpoint buffer size - */ - return 1023 / mpck * mpck; -} - -/* Do an USB transfer - */ -static int isp116x_submit_job(struct usb_device *dev, unsigned long pipe, - int dir, void *buffer, int len) -{ - struct isp116x *isp116x = &isp116x_dev; - int type = usb_pipetype(pipe); - int epnum = usb_pipeendpoint(pipe); - int max = usb_maxpacket(dev, pipe); - int dir_out = usb_pipeout(pipe); - int speed_low = (dev->speed == USB_SPEED_LOW); - int i, done = 0, stat, timeout, cc; - - /* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */ - int retries = 500; - - DBG("------------------------------------------------"); - dump_msg(dev, pipe, buffer, len, "SUBMIT"); - DBG("------------------------------------------------"); - - if (len >= 1024) { - ERR("Too big job"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - if (isp116x->disabled) { - ERR("EPIPE"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - /* device pulled? Shortcut the action. */ - if (devgone == dev) { - ERR("ENODEV"); - dev->status = USB_ST_CRC_ERR; - return USB_ST_CRC_ERR; - } - - if (!max) { - ERR("pipesize for pipe %lx is zero", pipe); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - if (type == PIPE_ISOCHRONOUS) { - ERR("isochronous transfers not supported"); - dev->status = USB_ST_CRC_ERR; - return -1; - } - - /* FIFO not empty? */ - if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL) { - ERR("****** FIFO not empty! ******"); - dev->status = USB_ST_BUF_ERR; - return -1; - } - - retry: - isp116x_write_reg32(isp116x, HCINTSTAT, 0xff); - - /* Prepare the PTD data */ - ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | - PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out)); - ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK; - ptd->len = PTD_LEN(len) | PTD_DIR(dir); - ptd->faddr = PTD_FA(usb_pipedevice(pipe)); - -retry_same: - /* Pack data into FIFO ram */ - pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len); -#ifdef EXTRA_DELAY - mdelay(EXTRA_DELAY); -#endif - - /* Start the data transfer */ - - /* Allow more time for a BULK device to react - some are slow */ - if (usb_pipebulk(pipe)) - timeout = 5000; - else - timeout = 100; - - /* Wait for it to complete */ - for (;;) { - /* Check whether the controller is done */ - stat = isp116x_interrupt(isp116x); - - if (stat < 0) { - dev->status = USB_ST_CRC_ERR; - break; - } - if (stat > 0) - break; - - /* Check the timeout */ - if (--timeout) - udelay(1); - else { - ERR("CTL:TIMEOUT "); - stat = USB_ST_CRC_ERR; - break; - } - } - - /* We got an Root Hub Status Change interrupt */ - if (got_rhsc) { - isp116x_show_regs(isp116x); - - got_rhsc = 0; - - /* Abuse timeout */ - timeout = rh_check_port_status(isp116x); - if (timeout >= 0) { - /* - * FIXME! NOTE! AAAARGH! - * This is potentially dangerous because it assumes - * that only one device is ever plugged in! - */ - devgone = dev; - } - } - - /* Ok, now we can read transfer status */ - - /* FIFO not ready? */ - if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE)) { - ERR("****** FIFO not ready! ******"); - dev->status = USB_ST_BUF_ERR; - return -1; - } - - /* Unpack data from FIFO ram */ - cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len); - - i = PTD_GET_COUNT(ptd); - done += i; - buffer += i; - len -= i; - - /* There was some kind of real problem; Prepare the PTD again - * and retry from the failed transaction on - */ - if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN) { - if (retries >= 100) { - retries -= 100; - /* The chip will have toggled the toggle bit for the failed - * transaction too. We have to toggle it back. - */ - usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd)); - goto retry; - } - } - /* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed - * the transactions from the first on for the whole frame. It may be busy and we retry - * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the - * PTD didn't make it because the function was busy or the frame ended before the PTD - * finished. We prepare the rest of the data and try again. - */ - else if (cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) || (cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd))) { - if (retries) { - --retries; - if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd)) goto retry_same; - usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd)); - goto retry; - } - } - - if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN) { - DBG("****** completition code error %x ******", cc); - switch (cc) { - case TD_CC_BITSTUFFING: - dev->status = USB_ST_BIT_ERR; - break; - case TD_CC_STALL: - dev->status = USB_ST_STALLED; - break; - case TD_BUFFEROVERRUN: - case TD_BUFFERUNDERRUN: - dev->status = USB_ST_BUF_ERR; - break; - default: - dev->status = USB_ST_CRC_ERR; - } - return -cc; - } - else usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd)); - - dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)"); - - dev->status = 0; - return done; -} - -/* Adapted from au1x00_usb_ohci.c - */ -static int isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len, - struct devrequest *cmd) -{ - struct isp116x *isp116x = &isp116x_dev; - u32 tmp = 0; - - int leni = transfer_len; - int len = 0; - int stat = 0; - u32 datab[4]; - u8 *data_buf = (u8 *) datab; - u16 bmRType_bReq; - u16 wValue; - u16 wIndex; - u16 wLength; - - if (usb_pipeint(pipe)) { - INFO("Root-Hub submit IRQ: NOT implemented"); - return 0; - } - - bmRType_bReq = cmd->requesttype | (cmd->request << 8); - wValue = swap_16(cmd->value); - wIndex = swap_16(cmd->index); - wLength = swap_16(cmd->length); - - DBG("--- HUB ----------------------------------------"); - DBG("submit rh urb, req=%x val=%#x index=%#x len=%d", - bmRType_bReq, wValue, wIndex, wLength); - dump_msg(dev, pipe, buffer, transfer_len, "RH"); - DBG("------------------------------------------------"); - - switch (bmRType_bReq) { - case RH_GET_STATUS: - DBG("RH_GET_STATUS"); - - *(__u16 *) data_buf = swap_16(1); - len = 2; - break; - - case RH_GET_STATUS | RH_INTERFACE: - DBG("RH_GET_STATUS | RH_INTERFACE"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_ENDPOINT: - DBG("RH_GET_STATUS | RH_ENDPOINT"); - - *(__u16 *) data_buf = swap_16(0); - len = 2; - break; - - case RH_GET_STATUS | RH_CLASS: - DBG("RH_GET_STATUS | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHSTATUS); - - *(__u32 *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE)); - len = 4; - break; - - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - DBG("RH_GET_STATUS | RH_OTHER | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1); - *(__u32 *) data_buf = swap_32(tmp); - isp116x_show_regs(isp116x); - len = 4; - break; - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - DBG("RH_CLEAR_FEATURE | RH_ENDPOINT"); - - switch (wValue) { - case RH_ENDPOINT_STALL: - DBG("C_HUB_ENDPOINT_STALL"); - len = 0; - break; - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - DBG("RH_CLEAR_FEATURE | RH_CLASS"); - - switch (wValue) { - case RH_C_HUB_LOCAL_POWER: - DBG("C_HUB_LOCAL_POWER"); - len = 0; - break; - - case RH_C_HUB_OVER_CURRENT: - DBG("C_HUB_OVER_CURRENT"); - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); - len = 0; - break; - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - DBG("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS"); - - switch (wValue) { - case RH_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_CCS); - len = 0; - break; - - case RH_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_POCI); - len = 0; - break; - - case RH_PORT_POWER: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_LSDA); - len = 0; - break; - - case RH_C_PORT_CONNECTION: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_CSC); - len = 0; - break; - - case RH_C_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PESC); - len = 0; - break; - - case RH_C_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PSSC); - len = 0; - break; - - case RH_C_PORT_OVER_CURRENT: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_POCI); - len = 0; - break; - - case RH_C_PORT_RESET: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRSC); - len = 0; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - isp116x_show_regs(isp116x); - - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - DBG("RH_SET_FEATURE | RH_OTHER | RH_CLASS"); - - switch (wValue) { - case RH_PORT_SUSPEND: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PSS); - len = 0; - break; - - case RH_PORT_RESET: - /* Spin until any current reset finishes */ - while (1) { - tmp = - isp116x_read_reg32(isp116x, - HCRHPORT1 + wIndex - 1); - if (!(tmp & RH_PS_PRS)) - break; - mdelay(1); - } - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PRS); - mdelay(10); - - len = 0; - break; - - case RH_PORT_POWER: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PPS); - len = 0; - break; - - case RH_PORT_ENABLE: - isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1, - RH_PS_PES); - len = 0; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - isp116x_show_regs(isp116x); - - break; - - case RH_SET_ADDRESS: - DBG("RH_SET_ADDRESS"); - - rh_devnum = wValue; - len = 0; - break; - - case RH_GET_DESCRIPTOR: - DBG("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength); - - switch (wValue) { - case (USB_DT_DEVICE << 8): /* device descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_dev_des), - wLength)); - data_buf = root_hub_dev_des; - break; - - case (USB_DT_CONFIG << 8): /* configuration descriptor */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_config_des), - wLength)); - data_buf = root_hub_config_des; - break; - - case ((USB_DT_STRING << 8) | 0x00): /* string 0 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index0), - wLength)); - data_buf = root_hub_str_index0; - break; - - case ((USB_DT_STRING << 8) | 0x01): /* string 1 descriptors */ - len = min_t(unsigned int, - leni, min_t(unsigned int, - sizeof(root_hub_str_index1), - wLength)); - data_buf = root_hub_str_index1; - break; - - default: - ERR("invalid wValue"); - stat = USB_ST_STALLED; - } - - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - DBG("RH_GET_DESCRIPTOR | RH_CLASS"); - - tmp = isp116x_read_reg32(isp116x, HCRHDESCA); - - data_buf[0] = 0x09; /* min length; */ - data_buf[1] = 0x29; - data_buf[2] = tmp & RH_A_NDP; - data_buf[3] = 0; - if (tmp & RH_A_PSM) /* per-port power switching? */ - data_buf[3] |= 0x01; - if (tmp & RH_A_NOCP) /* no overcurrent reporting? */ - data_buf[3] |= 0x10; - else if (tmp & RH_A_OCPM) /* per-port overcurrent rep? */ - data_buf[3] |= 0x08; - - /* Corresponds to data_buf[4-7] */ - datab[1] = 0; - data_buf[5] = (tmp & RH_A_POTPGT) >> 24; - - tmp = isp116x_read_reg32(isp116x, HCRHDESCB); - - data_buf[7] = tmp & RH_B_DR; - if (data_buf[2] < 7) - data_buf[8] = 0xff; - else { - data_buf[0] += 2; - data_buf[8] = (tmp & RH_B_DR) >> 8; - data_buf[10] = data_buf[9] = 0xff; - } - - len = min_t(unsigned int, leni, - min_t(unsigned int, data_buf[0], wLength)); - break; - - case RH_GET_CONFIGURATION: - DBG("RH_GET_CONFIGURATION"); - - *(__u8 *) data_buf = 0x01; - len = 1; - break; - - case RH_SET_CONFIGURATION: - DBG("RH_SET_CONFIGURATION"); - - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC); - len = 0; - break; - - default: - ERR("*** *** *** unsupported root hub command *** *** ***"); - stat = USB_ST_STALLED; - } - - len = min_t(int, len, leni); - if (buffer != data_buf) - memcpy(buffer, data_buf, len); - - dev->act_len = len; - dev->status = stat; - DBG("dev act_len %d, status %d", dev->act_len, dev->status); - - dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)"); - - return stat; -} - -/* --- Transfer functions -------------------------------------------------- */ - -int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, int interval) -{ - DBG("dev=%p pipe=%#lx buf=%p size=%d int=%d", - dev, pipe, buffer, len, interval); - - return -1; -} - -int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len, struct devrequest *setup) -{ - int devnum = usb_pipedevice(pipe); - int epnum = usb_pipeendpoint(pipe); - int max = max_transfer_len(dev, pipe); - int dir_in = usb_pipein(pipe); - int done, ret; - - /* Control message is for the HUB? */ - if (devnum == rh_devnum) - return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup); - - /* Ok, no HUB message so send the message to the device */ - - /* Setup phase */ - DBG("--- SETUP PHASE --------------------------------"); - usb_settoggle(dev, epnum, 1, 0); - ret = isp116x_submit_job(dev, pipe, - PTD_DIR_SETUP, - setup, sizeof(struct devrequest)); - if (ret < 0) { - DBG("control setup phase error (ret = %d", ret); - return -1; - } - - /* Data phase */ - DBG("--- DATA PHASE ---------------------------------"); - done = 0; - usb_settoggle(dev, epnum, !dir_in, 1); - while (done < len) { - ret = isp116x_submit_job(dev, pipe, - dir_in ? PTD_DIR_IN : PTD_DIR_OUT, - (__u8 *) buffer + done, - max > len - done ? len - done : max); - if (ret < 0) { - DBG("control data phase error (ret = %d)", ret); - return -1; - } - done += ret; - - if (dir_in && ret < max) /* short packet */ - break; - } - - /* Status phase */ - DBG("--- STATUS PHASE -------------------------------"); - usb_settoggle(dev, epnum, !dir_in, 1); - ret = isp116x_submit_job(dev, pipe, - !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0); - if (ret < 0) { - DBG("control status phase error (ret = %d", ret); - return -1; - } - - dev->act_len = done; - - dump_msg(dev, pipe, buffer, len, "DEV(ret)"); - - return done; -} - -int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int len) -{ - int dir_out = usb_pipeout(pipe); - int max = max_transfer_len(dev, pipe); - int done, ret; - - DBG("--- BULK ---------------------------------------"); - DBG("dev=%ld pipe=%ld buf=%p size=%d dir_out=%d", - usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out); - - done = 0; - while (done < len) { - ret = isp116x_submit_job(dev, pipe, - !dir_out ? PTD_DIR_IN : PTD_DIR_OUT, - (__u8 *) buffer + done, - max > len - done ? len - done : max); - if (ret < 0) { - DBG("error on bulk message (ret = %d)", ret); - return -1; - } - - done += ret; - - if (!dir_out && ret < max) /* short packet */ - break; - } - - dev->act_len = done; - - return 0; -} - -/* --- Basic functions ----------------------------------------------------- */ - -static int isp116x_sw_reset(struct isp116x *isp116x) -{ - int retries = 15; - int ret = 0; - - DBG(""); - - isp116x->disabled = 1; - - isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC); - isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR); - while (--retries) { - /* It usually resets within 1 ms */ - mdelay(1); - if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) - break; - } - if (!retries) { - ERR("software reset timeout"); - ret = -1; - } - return ret; -} - -static int isp116x_reset(struct isp116x *isp116x) -{ - unsigned long t; - u16 clkrdy = 0; - int ret, timeout = 15 /* ms */ ; - - DBG(""); - - ret = isp116x_sw_reset(isp116x); - if (ret) - return ret; - - for (t = 0; t < timeout; t++) { - clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY; - if (clkrdy) - break; - mdelay(1); - } - if (!clkrdy) { - ERR("clock not ready after %dms", timeout); - /* After sw_reset the clock won't report to be ready, if - H_WAKEUP pin is high. */ - ERR("please make sure that the H_WAKEUP pin is pulled low!"); - ret = -1; - } - return ret; -} - -static void isp116x_stop(struct isp116x *isp116x) -{ - u32 val; - - DBG(""); - - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - - /* Switch off ports' power, some devices don't come up - after next 'start' without this */ - val = isp116x_read_reg32(isp116x, HCRHDESCA); - val &= ~(RH_A_NPS | RH_A_PSM); - isp116x_write_reg32(isp116x, HCRHDESCA, val); - isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); - - isp116x_sw_reset(isp116x); -} - -/* - * Configure the chip. The chip must be successfully reset by now. - */ -static int isp116x_start(struct isp116x *isp116x) -{ - struct isp116x_platform_data *board = isp116x->board; - u32 val; - - DBG(""); - - /* Clear interrupt status and disable all interrupt sources */ - isp116x_write_reg16(isp116x, HCuPINT, 0xff); - isp116x_write_reg16(isp116x, HCuPINTENB, 0); - - isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); - isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); - - /* Hardware configuration */ - val = HCHWCFG_DBWIDTH(1); - if (board->sel15Kres) - val |= HCHWCFG_15KRSEL; - /* Remote wakeup won't work without working clock */ - if (board->remote_wakeup_enable) - val |= HCHWCFG_CLKNOTSTOP; - if (board->oc_enable) - val |= HCHWCFG_ANALOG_OC; - isp116x_write_reg16(isp116x, HCHWCFG, val); - - /* --- Root hub configuration */ - val = (25 << 24) & RH_A_POTPGT; - /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to - be always set. Yet, instead, we request individual port - power switching. */ - val |= RH_A_PSM; - /* Report overcurrent per port */ - val |= RH_A_OCPM; - isp116x_write_reg32(isp116x, HCRHDESCA, val); - isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); - - val = RH_B_PPCM; - isp116x_write_reg32(isp116x, HCRHDESCB, val); - isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB); - - val = 0; - if (board->remote_wakeup_enable) - val |= RH_HS_DRWE; - isp116x_write_reg32(isp116x, HCRHSTATUS, val); - isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); - - isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf); - - /* Go operational */ - val = HCCONTROL_USB_OPER; - if (board->remote_wakeup_enable) - val |= HCCONTROL_RWE; - isp116x_write_reg32(isp116x, HCCONTROL, val); - - /* Disable ports to avoid race in device enumeration */ - isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS); - isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS); - - isp116x_show_regs(isp116x); - - isp116x->disabled = 0; - - return 0; -} - -/* --- Init functions ------------------------------------------------------ */ - -int isp116x_check_id(struct isp116x *isp116x) -{ - int val; - - val = isp116x_read_reg16(isp116x, HCCHIPID); - if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC) { - ERR("invalid chip ID %04x", val); - return -1; - } - - return 0; -} - -int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - got_rhsc = rh_devnum = 0; - - /* Init device registers addr */ - isp116x->addr_reg = (u16 *) ISP116X_HCD_ADDR; - isp116x->data_reg = (u16 *) ISP116X_HCD_DATA; - - /* Setup specific board settings */ -#ifdef ISP116X_HCD_SEL15kRES - isp116x_board.sel15Kres = 1; -#endif -#ifdef ISP116X_HCD_OC_ENABLE - isp116x_board.oc_enable = 1; -#endif -#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE - isp116x_board.remote_wakeup_enable = 1; -#endif - isp116x->board = &isp116x_board; - - /* Try to get ISP116x silicon chip ID */ - if (isp116x_check_id(isp116x) < 0) - return -1; - - isp116x->disabled = 1; - isp116x->sleeping = 0; - - isp116x_reset(isp116x); - isp116x_start(isp116x); - - return 0; -} - -int usb_lowlevel_stop(int index) -{ - struct isp116x *isp116x = &isp116x_dev; - - DBG(""); - - if (!isp116x->disabled) - isp116x_stop(isp116x); - - return 0; -} diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h deleted file mode 100644 index 5b7afaf42c9..00000000000 --- a/drivers/usb/host/isp116x.h +++ /dev/null @@ -1,476 +0,0 @@ -/* - * ISP116x register declarations and HCD data structures - * - * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it> - * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it> - * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee> - * Portions: - * Copyright (C) 2004 Lothar Wassmann - * Copyright (C) 2004 Psion Teklogix - * Copyright (C) 2004 David Brownell - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifdef DEBUG -#define DBG(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#else -#define DBG(fmt, args...) do {} while (0) -#endif - -#ifdef VERBOSE -# define VDBG DBG -#else -# define VDBG(fmt, args...) do {} while (0) -#endif - -#define ERR(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#define WARN(fmt, args...) \ - printf("isp116x: %s: " fmt "\n" , __FUNCTION__ , ## args) -#define INFO(fmt, args...) \ - printf("isp116x: " fmt "\n" , ## args) - -/* ------------------------------------------------------------------------- */ - -/* us of 1ms frame */ -#define MAX_LOAD_LIMIT 850 - -/* Full speed: max # of bytes to transfer for a single urb - at a time must be < 1024 && must be multiple of 64. - 832 allows transfering 4kiB within 5 frames. */ -#define MAX_TRANSFER_SIZE_FULLSPEED 832 - -/* Low speed: there is no reason to schedule in very big - chunks; often the requested long transfers are for - string descriptors containing short strings. */ -#define MAX_TRANSFER_SIZE_LOWSPEED 64 - -/* Bytetime (us), a rough indication of how much time it - would take to transfer a byte of useful data over USB */ -#define BYTE_TIME_FULLSPEED 1 -#define BYTE_TIME_LOWSPEED 20 - -/* Buffer sizes */ -#define ISP116x_BUF_SIZE 4096 -#define ISP116x_ITL_BUFSIZE 0 -#define ISP116x_ATL_BUFSIZE ((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE)) - -#define ISP116x_WRITE_OFFSET 0x80 - -/* --- ISP116x registers/bits ---------------------------------------------- */ - -#define HCREVISION 0x00 -#define HCCONTROL 0x01 -#define HCCONTROL_HCFS (3 << 6) /* host controller - functional state */ -#define HCCONTROL_USB_RESET (0 << 6) -#define HCCONTROL_USB_RESUME (1 << 6) -#define HCCONTROL_USB_OPER (2 << 6) -#define HCCONTROL_USB_SUSPEND (3 << 6) -#define HCCONTROL_RWC (1 << 9) /* remote wakeup connected */ -#define HCCONTROL_RWE (1 << 10) /* remote wakeup enable */ -#define HCCMDSTAT 0x02 -#define HCCMDSTAT_HCR (1 << 0) /* host controller reset */ -#define HCCMDSTAT_SOC (3 << 16) /* scheduling overrun count */ -#define HCINTSTAT 0x03 -#define HCINT_SO (1 << 0) /* scheduling overrun */ -#define HCINT_WDH (1 << 1) /* writeback of done_head */ -#define HCINT_SF (1 << 2) /* start frame */ -#define HCINT_RD (1 << 3) /* resume detect */ -#define HCINT_UE (1 << 4) /* unrecoverable error */ -#define HCINT_FNO (1 << 5) /* frame number overflow */ -#define HCINT_RHSC (1 << 6) /* root hub status change */ -#define HCINT_OC (1 << 30) /* ownership change */ -#define HCINT_MIE (1 << 31) /* master interrupt enable */ -#define HCINTENB 0x04 -#define HCINTDIS 0x05 -#define HCFMINTVL 0x0d -#define HCFMREM 0x0e -#define HCFMNUM 0x0f -#define HCLSTHRESH 0x11 -#define HCRHDESCA 0x12 -#define RH_A_NDP (0x3 << 0) /* # downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* overcurrent protection - mode */ -#define RH_A_NOCP (1 << 12) /* no overcurrent protection */ -#define RH_A_POTPGT (0xff << 24) /* power on -> power good - time */ -#define HCRHDESCB 0x13 -#define RH_B_DR (0xffff << 0) /* device removable flags */ -#define RH_B_PPCM (0xffff << 16) /* port power control mask */ -#define HCRHSTATUS 0x14 -#define RH_HS_LPS (1 << 0) /* local power status */ -#define RH_HS_OCI (1 << 1) /* over current indicator */ -#define RH_HS_DRWE (1 << 15) /* device remote wakeup - enable */ -#define RH_HS_LPSC (1 << 16) /* local power status change */ -#define RH_HS_OCIC (1 << 17) /* over current indicator - change */ -#define RH_HS_CRWE (1 << 31) /* clear remote wakeup - enable */ -#define HCRHPORT1 0x15 -#define RH_PS_CCS (1 << 0) /* current connect status */ -#define RH_PS_PES (1 << 1) /* port enable status */ -#define RH_PS_PSS (1 << 2) /* port suspend status */ -#define RH_PS_POCI (1 << 3) /* port over current - indicator */ -#define RH_PS_PRS (1 << 4) /* port reset status */ -#define RH_PS_PPS (1 << 8) /* port power status */ -#define RH_PS_LSDA (1 << 9) /* low speed device attached */ -#define RH_PS_CSC (1 << 16) /* connect status change */ -#define RH_PS_PESC (1 << 17) /* port enable status change */ -#define RH_PS_PSSC (1 << 18) /* port suspend status - change */ -#define RH_PS_OCIC (1 << 19) /* over current indicator - change */ -#define RH_PS_PRSC (1 << 20) /* port reset status change */ -#define HCRHPORT_CLRMASK (0x1f << 16) -#define HCRHPORT2 0x16 -#define HCHWCFG 0x20 -#define HCHWCFG_15KRSEL (1 << 12) -#define HCHWCFG_CLKNOTSTOP (1 << 11) -#define HCHWCFG_ANALOG_OC (1 << 10) -#define HCHWCFG_DACK_MODE (1 << 8) -#define HCHWCFG_EOT_POL (1 << 7) -#define HCHWCFG_DACK_POL (1 << 6) -#define HCHWCFG_DREQ_POL (1 << 5) -#define HCHWCFG_DBWIDTH_MASK (0x03 << 3) -#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK) -#define HCHWCFG_INT_POL (1 << 2) -#define HCHWCFG_INT_TRIGGER (1 << 1) -#define HCHWCFG_INT_ENABLE (1 << 0) -#define HCDMACFG 0x21 -#define HCDMACFG_BURST_LEN_MASK (0x03 << 5) -#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK) -#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0) -#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1) -#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2) -#define HCDMACFG_DMA_ENABLE (1 << 4) -#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1) -#define HCDMACFG_CTR_SEL (1 << 2) -#define HCDMACFG_ITLATL_SEL (1 << 1) -#define HCDMACFG_DMA_RW_SELECT (1 << 0) -#define HCXFERCTR 0x22 -#define HCuPINT 0x24 -#define HCuPINT_SOF (1 << 0) -#define HCuPINT_ATL (1 << 1) -#define HCuPINT_AIIEOT (1 << 2) -#define HCuPINT_OPR (1 << 4) -#define HCuPINT_SUSP (1 << 5) -#define HCuPINT_CLKRDY (1 << 6) -#define HCuPINTENB 0x25 -#define HCCHIPID 0x27 -#define HCCHIPID_MASK 0xff00 -#define HCCHIPID_MAGIC 0x6100 -#define HCSCRATCH 0x28 -#define HCSWRES 0x29 -#define HCSWRES_MAGIC 0x00f6 -#define HCITLBUFLEN 0x2a -#define HCATLBUFLEN 0x2b -#define HCBUFSTAT 0x2c -#define HCBUFSTAT_ITL0_FULL (1 << 0) -#define HCBUFSTAT_ITL1_FULL (1 << 1) -#define HCBUFSTAT_ATL_FULL (1 << 2) -#define HCBUFSTAT_ITL0_DONE (1 << 3) -#define HCBUFSTAT_ITL1_DONE (1 << 4) -#define HCBUFSTAT_ATL_DONE (1 << 5) -#define HCRDITL0LEN 0x2d -#define HCRDITL1LEN 0x2e -#define HCITLPORT 0x40 -#define HCATLPORT 0x41 - -/* PTD accessor macros. */ -#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0) -#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK) -#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10) -#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK) -#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11) -#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK) -#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12) -#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK) -#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0) -#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK) -#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10) -#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK) -#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11) -#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK) -#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12) -#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK) -#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0) -#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK) -#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10) -#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK) -#define PTD_GET_B5_5(p) (((p)->len & PTD_B5_5_MSK) >> 13) -#define PTD_B5_5(v) (((v) << 13) & PTD_B5_5_MSK) -#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0) -#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK) -#define PTD_GET_FMT(p) (((p)->faddr & PTD_FMT_MSK) >> 7) -#define PTD_FMT(v) (((v) << 7) & PTD_FMT_MSK) - -/* Hardware transfer status codes -- CC from ptd->count */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_DEVNOTRESP 0x05 -#define TD_PIDCHECKFAIL 0x06 -#define TD_UNEXPECTEDPID 0x07 -#define TD_DATAOVERRUN 0x08 -#define TD_DATAUNDERRUN 0x09 - /* 0x0A, 0x0B reserved for hardware */ -#define TD_BUFFEROVERRUN 0x0C -#define TD_BUFFERUNDERRUN 0x0D - /* 0x0E, 0x0F reserved for HCD */ -#define TD_NOTACCESSED 0x0F - -/* ------------------------------------------------------------------------- */ - -#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ -#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) - -/* Philips transfer descriptor */ -struct ptd { - u16 count; -#define PTD_COUNT_MSK (0x3ff << 0) -#define PTD_TOGGLE_MSK (1 << 10) -#define PTD_ACTIVE_MSK (1 << 11) -#define PTD_CC_MSK (0xf << 12) - u16 mps; -#define PTD_MPS_MSK (0x3ff << 0) -#define PTD_SPD_MSK (1 << 10) -#define PTD_LAST_MSK (1 << 11) -#define PTD_EP_MSK (0xf << 12) - u16 len; -#define PTD_LEN_MSK (0x3ff << 0) -#define PTD_DIR_MSK (3 << 10) -#define PTD_DIR_SETUP (0) -#define PTD_DIR_OUT (1) -#define PTD_DIR_IN (2) -#define PTD_B5_5_MSK (1 << 13) - u16 faddr; -#define PTD_FA_MSK (0x7f << 0) -#define PTD_FMT_MSK (1 << 7) -} __attribute__ ((packed, aligned(2))); - -struct isp116x_ep { - struct usb_device *udev; - struct ptd ptd; - - u8 maxpacket; - u8 epnum; - u8 nextpid; - - u16 length; /* of current packet */ - unsigned char *data; /* to databuf */ - - u16 error_count; -}; - -/* URB struct */ -#define N_URB_TD 48 -#define URB_DEL 1 -typedef struct { - struct isp116x_ep *ed; - void *transfer_buffer; /* (in) associated data buffer */ - int actual_length; /* (return) actual transfer length */ - unsigned long pipe; /* (in) pipe information */ -#if 0 - int state; -#endif -} urb_priv_t; - -struct isp116x_platform_data { - /* Enable internal resistors on downstream ports */ - unsigned sel15Kres:1; - /* On-chip overcurrent detection */ - unsigned oc_enable:1; - /* Enable wakeup by devices on usb bus (e.g. wakeup - by attachment/detachment or by device activity - such as moving a mouse). When chosen, this option - prevents stopping internal clock, increasing - thereby power consumption in suspended state. */ - unsigned remote_wakeup_enable:1; -}; - -struct isp116x { - u16 *addr_reg; - u16 *data_reg; - - struct isp116x_platform_data *board; - - struct dentry *dentry; - unsigned long stat1, stat2, stat4, stat8, stat16; - - /* Status flags */ - unsigned disabled:1; - unsigned sleeping:1; - - /* Root hub registers */ - u32 rhdesca; - u32 rhdescb; - u32 rhstatus; - u32 rhport[2]; - - /* Schedule for the current frame */ - struct isp116x_ep *atl_active; - int atl_buflen; - int atl_bufshrt; - int atl_last_dir; - int atl_finishing; -}; - -/* ------------------------------------------------- */ - -/* Inter-io delay (ns). The chip is picky about access timings; it - * expects at least: - * 150ns delay between consecutive accesses to DATA_REG, - * 300ns delay between access to ADDR_REG and DATA_REG - * OE, WE MUST NOT be changed during these intervals - */ -#if defined(UDELAY) -#define isp116x_delay(h,d) udelay(d) -#else -#define isp116x_delay(h,d) do {} while (0) -#endif - -static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) -{ - writew(reg & 0xff, isp116x->addr_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline void isp116x_write_data16(struct isp116x *isp116x, u16 val) -{ - writew(val, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline void isp116x_raw_write_data16(struct isp116x *isp116x, u16 val) -{ - __raw_writew(val, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline u16 isp116x_read_data16(struct isp116x *isp116x) -{ - u16 val; - - val = readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - return val; -} - -static inline u16 isp116x_raw_read_data16(struct isp116x *isp116x) -{ - u16 val; - - val = __raw_readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - return val; -} - -static inline void isp116x_write_data32(struct isp116x *isp116x, u32 val) -{ - writew(val & 0xffff, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - writew(val >> 16, isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); -} - -static inline u32 isp116x_read_data32(struct isp116x *isp116x) -{ - u32 val; - - val = (u32) readw(isp116x->data_reg); - isp116x_delay(isp116x, UDELAY); - val |= ((u32) readw(isp116x->data_reg)) << 16; - isp116x_delay(isp116x, UDELAY); - return val; -} - -/* Let's keep register access functions out of line. Hint: - we wait at least 150 ns at every access. -*/ -static u16 isp116x_read_reg16(struct isp116x *isp116x, unsigned reg) -{ - isp116x_write_addr(isp116x, reg); - return isp116x_read_data16(isp116x); -} - -static u32 isp116x_read_reg32(struct isp116x *isp116x, unsigned reg) -{ - isp116x_write_addr(isp116x, reg); - return isp116x_read_data32(isp116x); -} - -static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg, - unsigned val) -{ - isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); - isp116x_write_data16(isp116x, (u16) (val & 0xffff)); -} - -static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg, - unsigned val) -{ - isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET); - isp116x_write_data32(isp116x, (u32) val); -} - -/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */ - -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 - -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e0ca2cb0d4c..9dbb18343aa 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -20,7 +20,6 @@ #define R8A66597_DPRINT(...) #endif -static const char hcd_name[] = "r8a66597_hcd"; static struct r8a66597 gr8a66597; static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index a59ff5a8bbf..b1b4498fba5 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -9,6 +9,7 @@ #include "btrfs.h" #include <linux/lzo.h> #include <u-boot/zlib.h> +#include <asm/unaligned.h> static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) { @@ -19,7 +20,7 @@ static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) if (clen < 4) return -1; - tot_len = le32_to_cpu(*(u32 *) cbuf); + tot_len = le32_to_cpu(get_unaligned((u32 *)cbuf)); cbuf += 4; clen -= 4; tot_len -= 4; @@ -32,7 +33,7 @@ static u32 decompress_lzo(const u8 *cbuf, u32 clen, u8 *dbuf, u32 dlen) res = 0; while (tot_len > 4) { - in_len = le32_to_cpu(*(u32 *) cbuf); + in_len = le32_to_cpu(get_unaligned((u32 *)cbuf)); cbuf += 4; clen -= 4; diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c index f8a50e532ae..cde3abd3dfb 100644 --- a/fs/btrfs/hash.c +++ b/fs/btrfs/hash.c @@ -8,6 +8,7 @@ #include "btrfs.h" #include <u-boot/crc.h> +#include <asm/unaligned.h> static u32 btrfs_crc32c_table[256]; @@ -34,5 +35,5 @@ u32 btrfs_csum_data(char *data, u32 seed, size_t len) void btrfs_csum_final(u32 crc, void *result) { - *((u32 *) result) = cpu_to_le32(~crc); + put_unaligned(cpu_to_le32(~crc), (u32 *)result); } diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h index d0469ef2e33..32f288b706d 100644 --- a/include/asm-generic/atomic-long.h +++ b/include/asm-generic/atomic-long.h @@ -66,6 +66,7 @@ static inline void atomic_long_sub(long i, atomic_long_t *l) atomic64_sub(i, v); } +#ifndef __UBOOT__ static inline int atomic_long_sub_and_test(long i, atomic_long_t *l) { atomic64_t *v = (atomic64_t *)l; @@ -135,6 +136,7 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u) (atomic64_cmpxchg((atomic64_t *)(l), (old), (new))) #define atomic_long_xchg(v, new) \ (atomic64_xchg((atomic64_t *)(v), (new))) +#endif /* __UBOOT__ */ #else /* BITS_PER_LONG == 64 */ diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 5c469a23fa7..f567cebd381 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -71,10 +71,15 @@ #ifdef CONFIG_CMD_UBIFS #define BOOTENV_SHARED_UBIFS \ "ubifs_boot=" \ - "if ubi part UBI && ubifsmount ubi${devnum}:boot; then " \ - "setenv devtype ubi; " \ - "setenv bootpart 0; " \ - "run scan_dev_for_boot; " \ + "env exists bootubipart || " \ + "env set bootubipart UBI; " \ + "env exists bootubivol || " \ + "env set bootubivol boot; " \ + "if ubi part ${bootubipart} && " \ + "ubifsmount ubi${devnum}:${bootubivol}; " \ + "then " \ + "setenv devtype ubi; " \ + "run scan_dev_for_boot; " \ "fi\0" #define BOOTENV_DEV_UBIFS BOOTENV_DEV_BLKDEV #define BOOTENV_DEV_NAME_UBIFS BOOTENV_DEV_NAME_BLKDEV @@ -125,7 +130,7 @@ "${kernel_addr_r} efi/boot/"BOOTEFI_NAME"; " \ "if fdt addr ${fdt_addr_r}; then " \ "bootefi ${kernel_addr_r} ${fdt_addr_r};" \ - "else " \ + "else " \ "bootefi ${kernel_addr_r} ${fdtcontroladdr};" \ "fi\0" \ \ diff --git a/include/configs/am43xx_evm.h b/include/configs/am43xx_evm.h index 77f8e7689c8..726dbba74d7 100644 --- a/include/configs/am43xx_evm.h +++ b/include/configs/am43xx_evm.h @@ -115,9 +115,6 @@ #endif #ifdef CONFIG_QSPI_BOOT -#ifndef CONFIG_SYS_TEXT_BASE -#define CONFIG_SYS_TEXT_BASE CONFIG_ISW_ENTRY_ADDR -#endif #define CONFIG_SYS_REDUNDAND_ENVIRONMENT #define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED #define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64 KB sectors */ diff --git a/include/configs/edb93xx.h b/include/configs/edb93xx.h index 8fcc791ab47..fcad7c46dd8 100644 --- a/include/configs/edb93xx.h +++ b/include/configs/edb93xx.h @@ -80,7 +80,6 @@ #define CONFIG_SYS_CBSIZE 1024 /* Console I/O buffer size */ /* Serial port hardware configuration */ -#define CONFIG_PL010_SERIAL #define CONFIG_CONS_INDEX 0 #define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, \ 115200, 230400} diff --git a/include/configs/highbank.h b/include/configs/highbank.h index a5a524008b4..726ae8a2149 100644 --- a/include/configs/highbank.h +++ b/include/configs/highbank.h @@ -22,7 +22,6 @@ */ #define CONFIG_SYS_MALLOC_LEN (512 * 1024) -#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK 150000000 #define CONFIG_PL01x_PORTS { (void *)(0xFFF36000) } #define CONFIG_CONS_INDEX 0 diff --git a/include/configs/hikey.h b/include/configs/hikey.h index 130c7694bf4..8679b6b14ff 100644 --- a/include/configs/hikey.h +++ b/include/configs/hikey.h @@ -50,9 +50,6 @@ /* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + SZ_8M) -/* Serial port PL010/PL011 through the device model */ -#define CONFIG_PL01X_SERIAL - #ifdef CONFIG_CMD_USB #define CONFIG_USB_DWC2_REG_ADDR 0xF72C0000 /*#define CONFIG_DWC2_DFLT_SPEED_FULL*/ diff --git a/include/configs/integrator-common.h b/include/configs/integrator-common.h index edc798b117f..f66d9547481 100644 --- a/include/configs/integrator-common.h +++ b/include/configs/integrator-common.h @@ -15,8 +15,6 @@ #define CONFIG_SYS_LONGHELP #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024) /* Size of malloc() pool */ -/* Serial port PL010/PL011 through the device model */ -#define CONFIG_PL01X_SERIAL #define CONFIG_CONS_INDEX 0 #define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */ diff --git a/include/configs/mxs.h b/include/configs/mxs.h index 804b9e199c7..3a27c150603 100644 --- a/include/configs/mxs.h +++ b/include/configs/mxs.h @@ -108,7 +108,6 @@ * DUART Serial Driver. * Conflicts with AUART driver which can be set by board. */ -#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK 24000000 #define CONFIG_PL01x_PORTS { (void *)MXS_UARTDBG_BASE } #define CONFIG_CONS_INDEX 0 diff --git a/include/configs/omap3_evm.h b/include/configs/omap3_evm.h index ba67e33c384..71d49e3cd3f 100644 --- a/include/configs/omap3_evm.h +++ b/include/configs/omap3_evm.h @@ -86,43 +86,24 @@ #define MEM_LAYOUT_ENV_SETTINGS \ DEFAULT_LINUX_BOOT_ENV -#if defined(CONFIG_NAND) && defined(CONFIG_CMD_UBI) -/* NAND boot with uImage from NAND 'kernel' partition */ #define BOOTENV_DEV_NAND(devtypeu, devtypel, instance) \ "bootcmd_" #devtypel #instance "=" \ "run nandboot\0" #define BOOTENV_DEV_NAME_NAND(devtypeu, devtypel, instance) \ #devtypel #instance " " -/* NAND boot with zImage from UBIFS '/boot/zImage' */ -#define BOOTENV_DEV_UBIFS_NAND(devtypeu, devtypel, instance) \ +#define BOOTENV_DEV_LEGACY_MMC(devtypeu, devtypel, instance) \ "bootcmd_" #devtypel #instance "=" \ - "run nandbootubifs\0" -#define BOOTENV_DEV_NAME_UBIFS_NAND(devtypeu, devtypel, instance) \ - #devtypel #instance " " -#endif /* CONFIG_NAND && CONFIG_CMD_UBI */ - -/* MMC boot with uImage from MMC 0:2 '/boot/uImage' */ -#define BOOTENV_DEV_UIMAGE_MMC(devtypeu, devtypel, instance) \ - "bootcmd_" #devtypel #instance "=" \ - "setenv mmcdev " #instance"; " \ - "run mmcboot\0" -#define BOOTENV_DEV_NAME_UIMAGE_MMC(devtypeu, devtypel, instance) \ - #devtypel #instance " " - -/* MMC boot with zImage from MMC 0:2 '/boot/zImage' */ -#define BOOTENV_DEV_ZIMAGE_MMC(devtypeu, devtypel, instance) \ - "bootcmd_" #devtypel #instance "=" \ - "setenv mmcdev " #instance"; " \ - "run mmcbootz\0" -#define BOOTENV_DEV_NAME_ZIMAGE_MMC(devtypeu, devtypel, instance) \ + "setenv mmcdev " #instance "; " \ + "setenv bootpart " #instance ":${mmcpart} ; " \ + "run mmcboot\0" +#define BOOTENV_DEV_NAME_LEGACY_MMC(devtypeu, devtypel, instance) \ #devtypel #instance " " #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ - func(ZIMAGE_MMC, zimage_mmc, 0) \ - func(UIMAGE_MMC, uimage_mmc, 0) \ - func(UBIFS_NAND, ubifs_nand, 0) \ + func(LEGACY_MMC, legacy_mmc, 0) \ + func(UBIFS, ubifs, 0) \ func(NAND, nand, 0) #include <config_distro_bootcmd.h> @@ -135,9 +116,13 @@ "fdt_high=0xffffffff\0" \ "bootdir=/boot\0" \ "bootenv=uEnv.txt\0" \ + "bootfile=zImage\0" \ + "bootubivol=rootfs\0" \ + "bootubipart=rootfs\0" \ "optargs=\0" \ "mmcdev=0\0" \ "mmcpart=2\0" \ + "bootpart=${mmcdev}:${mmcpart}\0" \ "console=ttyO0,115200n8\0" \ "mmcargs=setenv bootargs console=${console} " \ "${mtdparts} " \ @@ -150,7 +135,7 @@ "root=ubi0:rootfs rw ubi.mtd=rootfs noinitrd " \ "rootfstype=ubifs rootwait\0" \ "loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenv}\0" \ - "ext4bootenv=ext4load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootenv}\0" \ + "ext4bootenv=ext4load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootenv}\0" \ "importbootenv=echo Importing environment from mmc ...; " \ "env import -t ${loadaddr} ${filesize}\0" \ "mmcbootenv=mmc dev ${mmcdev}; " \ @@ -162,39 +147,24 @@ "run uenvcmd; " \ "fi; " \ "fi\0" \ - "loaduimage=setenv bootfile uImage; " \ - "ext4load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootfile}\0" \ - "loadzimage=setenv bootfile zImage; " \ - "ext4load mmc ${mmcdev}:${mmcpart} ${loadaddr} ${bootdir}/${bootfile}\0" \ - "loaddtb=ext4load mmc ${mmcdev}:${mmcpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \ - "loadubizimage=setenv bootfile zImage; " \ - "ubifsload ${loadaddr} ${bootdir}/${bootfile}\0" \ - "loadubidtb=ubifsload ${fdtaddr} ${bootdir}/${fdtfile}\0" \ + "loadimage=ext4load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}\0" \ + "loaddtb=ext4load mmc ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}\0" \ "mmcboot=run mmcbootenv; " \ - "if run loaduimage && run loaddtb; then " \ - "echo Booting ${bootdir}/${bootfile} from mmc ${mmcdev}:${mmcpart} ...; " \ + "if run loadimage && run loaddtb; then " \ + "echo Booting ${bootdir}/${bootfile} from mmc ${bootpart} ...; " \ "run mmcargs; " \ - "bootm ${loadaddr} - ${fdtaddr}; " \ - "fi\0" \ - "mmcbootz=run mmcbootenv; " \ - "if run loadzimage && run loaddtb; then " \ - "echo Booting ${bootdir}/${bootfile} from mmc ${mmcdev}:${mmcpart} ...; " \ - "run mmcargs; " \ - "bootz ${loadaddr} - ${fdtaddr}; " \ + "if test ${bootfile} = uImage; then " \ + "bootm ${loadaddr} - ${fdtaddr}; " \ + "fi; " \ + "if test ${bootfile} = zImage; then " \ + "bootz ${loadaddr} - ${fdtaddr}; " \ + "fi; " \ "fi\0" \ "nandboot=" \ - "nand read ${loadaddr} kernel; " \ - "nand read ${fdtaddr} dtb; " \ - "echo Booting uImage from NAND MTD 'kernel' partition ...; " \ - "run nandargs; " \ - "bootm ${loadaddr} - ${fdtaddr}\0" \ - "nandbootubifs=" \ - "ubi part rootfs; " \ - "ubifsmount ubi0:rootfs; " \ - "if run loadubizimage && run loadubidtb; then " \ - "echo Booting ${bootdir}/${bootfile} from NAND ubi0:rootfs ...; " \ + "if nand read ${loadaddr} kernel && nand read ${fdtaddr} dtb; then " \ + "echo Booting uImage from NAND MTD 'kernel' partition ...; " \ "run nandargs; " \ - "bootz ${loadaddr} - ${fdtaddr}; " \ + "bootm ${loadaddr} - ${fdtaddr}; " \ "fi\0" \ BOOTENV diff --git a/include/configs/pdu001.h b/include/configs/pdu001.h new file mode 100644 index 00000000000..6fccae5e6a8 --- /dev/null +++ b/include/configs/pdu001.h @@ -0,0 +1,87 @@ +/* + * pdu001.h + * + * Copyright (C) 2018 EETS GmbH - http://www.eets.ch/ + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_PDU001_H +#define __CONFIG_PDU001_H + +#include <configs/ti_am335x_common.h> + +/* No more need for I2C legacy compatibility for this board. + * CONFIG_DM_I2C_COMPAT is defined in ti_armv7_common.h. See the comment there + * for the right moment to delete the following line. + */ +#undef CONFIG_DM_I2C_COMPAT + +/* Using 32K of volatile storage for environment */ +#define CONFIG_ENV_SIZE 0x4000 + +#define MACH_TYPE_PDU001 5075 +#define CONFIG_MACH_TYPE MACH_TYPE_PDU001 +#define CONFIG_BOARD_LATE_INIT + +/* Clock Defines */ +#define V_OSCK 24000000 /* Clock output from T2 */ +#define V_SCLK (V_OSCK) + +#if CONFIG_CONS_INDEX == 1 + #define CONSOLE_DEV "ttyO0" +#elif CONFIG_CONS_INDEX == 2 + #define CONSOLE_DEV "ttyO1" +#elif CONFIG_CONS_INDEX == 3 + #define CONSOLE_DEV "ttyO2" +#elif CONFIG_CONS_INDEX == 4 + #define CONSOLE_DEV "ttyO3" +#elif CONFIG_CONS_INDEX == 5 + #define CONSOLE_DEV "ttyO4" +#elif CONFIG_CONS_INDEX == 6 + #define CONSOLE_DEV "ttyO5" +#endif + +#define CONFIG_BOOTCOMMAND \ + "run eval_boot_device;" \ + "setenv bootargs console=${console} " \ + "vt.global_cursor_default=0 " \ + "root=/dev/mmcblk${mmc_boot}p${root_fs_partition} " \ + "rootfstype=ext4 " \ + "rootwait " \ + "rootdelay=1;" \ + "fatload mmc ${mmc_boot} ${fdtaddr} ${fdtfile};" \ + "fatload mmc ${mmc_boot} ${loadaddr} ${bootfile};" \ + "bootz ${loadaddr} - ${fdtaddr}" + +#ifndef CONFIG_SPL_BUILD +#define CONFIG_EXTRA_ENV_SETTINGS \ + DEFAULT_LINUX_BOOT_ENV \ + "fdtfile=am335x-pdu001.dtb\0" \ + "bootfile=zImage\0" \ + "console=" CONSOLE_DEV ",115200n8\0" \ + "root_fs_partition=2\0" \ + "eval_boot_device=" \ + "if test $boot_device = emmc; then " \ + "setenv mmc_boot 0;" \ + "elif test $boot_device = sdcard; then " \ + "setenv mmc_boot 1;" \ + "else " \ + "echo Bootdevice is neither MMC0 nor MMC1;" \ + "reset;" \ + "fi;" \ + "\0" +#endif + +/* NS16550 Configuration */ +#define CONFIG_SYS_NS16550_COM1 UART0_BASE +#define CONFIG_SYS_NS16550_COM2 UART1_BASE +#define CONFIG_SYS_NS16550_COM3 UART2_BASE +#define CONFIG_SYS_NS16550_COM4 UART3_BASE +#define CONFIG_SYS_NS16550_COM5 UART4_BASE +#define CONFIG_SYS_NS16550_COM6 UART5_BASE +#define CONFIG_BAUDRATE 115200 + +#endif /* ! __CONFIG_PDU001_H */ diff --git a/include/configs/poplar.h b/include/configs/poplar.h index acdce29ba9f..859da38462d 100644 --- a/include/configs/poplar.h +++ b/include/configs/poplar.h @@ -26,9 +26,6 @@ /* ATF bl33.bin load address (must match) */ #define CONFIG_SYS_TEXT_BASE 0x37000000 -/* PL010/PL011 */ -#define CONFIG_PL01X_SERIAL - /* USB configuration */ #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 diff --git a/include/configs/qemu-arm.h b/include/configs/qemu-arm.h index c8852cef349..c8ba78d8aad 100644 --- a/include/configs/qemu-arm.h +++ b/include/configs/qemu-arm.h @@ -20,9 +20,6 @@ #define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_2M) #define CONFIG_SYS_MALLOC_LEN SZ_16M -/* QEMU's PL011 serial port is detected via FDT using the device model */ -#define CONFIG_PL01X_SERIAL - /* QEMU implements a 62.5MHz architected timer */ /* FIXME: can we rely on CNTFREQ instead of hardcoding this fact here? */ #define CONFIG_SYS_ARCH_TIMER diff --git a/include/configs/rpi.h b/include/configs/rpi.h index cab8661779e..f2d3646753e 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -75,13 +75,6 @@ #define CONFIG_MISC_INIT_R #endif -/* Console UART */ -#if defined (CONFIG_BCM2837) || defined(CONFIG_TARGET_RPI_0_W) -#define CONFIG_BCM283X_MU_SERIAL -#else -#define CONFIG_PL01X_SERIAL -#endif - /* Console configuration */ #define CONFIG_SYS_CBSIZE 1024 diff --git a/include/configs/spear-common.h b/include/configs/spear-common.h index 349232e1bfd..c123e44d156 100644 --- a/include/configs/spear-common.h +++ b/include/configs/spear-common.h @@ -76,7 +76,6 @@ * Serial Configuration (PL011) * CONFIG_PL01x_PORTS is defined in specific files */ -#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK (48 * 1000 * 1000) #define CONFIG_CONS_INDEX 0 #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, \ diff --git a/include/configs/stm32f429-discovery.h b/include/configs/stm32f429-discovery.h index 1ad36986ae3..af9daad3207 100644 --- a/include/configs/stm32f429-discovery.h +++ b/include/configs/stm32f429-discovery.h @@ -43,8 +43,6 @@ #define CONFIG_STM32_FLASH -#define CONFIG_STM32_HSE_HZ 8000000 - #define CONFIG_SYS_CLK_FREQ 180000000 /* 180 MHz */ #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ diff --git a/include/configs/stm32f429-evaluation.h b/include/configs/stm32f429-evaluation.h new file mode 100644 index 00000000000..ab33d0f3d2a --- /dev/null +++ b/include/configs/stm32f429-evaluation.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) STMicroelectronics SA 2017 + * Author(s): Patrice CHOTARD, <patrice.chotard@st.com> for STMicroelectronics. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_MISC_INIT_R + +#define CONFIG_SYS_FLASH_BASE 0x08000000 + +#define CONFIG_SYS_INIT_SP_ADDR 0x10010000 +#define CONFIG_SYS_TEXT_BASE 0x08000000 + +#define CONFIG_SYS_ICACHE_OFF +#define CONFIG_SYS_DCACHE_OFF + +/* + * Configuration of the external SDRAM memory + */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_RAM_FREQ_DIV 2 +#define CONFIG_SYS_RAM_BASE 0x00000000 +#define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_RAM_BASE +#define CONFIG_SYS_LOAD_ADDR 0x00400000 +#define CONFIG_LOADADDR 0x00400000 + +#define CONFIG_SYS_MAX_FLASH_SECT 12 +#define CONFIG_SYS_MAX_FLASH_BANKS 2 + +#define CONFIG_ENV_OFFSET (256 << 10) +#define CONFIG_ENV_SECT_SIZE (128 << 10) +#define CONFIG_ENV_SIZE (8 << 10) + +#define CONFIG_STM32_FLASH + +#define CONFIG_SYS_CLK_FREQ 180000000 /* 180 MHz */ +#define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ + +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_INITRD_TAG +#define CONFIG_REVISION_TAG + +#define CONFIG_SYS_CBSIZE 1024 + +#define CONFIG_SYS_MALLOC_LEN (1 * 1024 * 1024) + +#define CONFIG_BOOTCOMMAND \ + "run boot_sd" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "boot_sd=mmc dev 0;fatload mmc 0 0x00700000 stm32429i-eval.dtb; fatload mmc 0 0x00008000 zImage; icache off; bootz 0x00008000 - 0x00700000" + +/* + * Command line configuration. + */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_AUTO_COMPLETE +#define CONFIG_CMDLINE_EDITING + +#endif /* __CONFIG_H */ diff --git a/include/configs/stm32f469-discovery.h b/include/configs/stm32f469-discovery.h index 140999994b1..c290a66fddd 100644 --- a/include/configs/stm32f469-discovery.h +++ b/include/configs/stm32f469-discovery.h @@ -39,7 +39,6 @@ #define CONFIG_STM32_FLASH -#define CONFIG_STM32_HSE_HZ 8000000 #define CONFIG_SYS_CLK_FREQ 180000000 /* 180 MHz */ #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h index d12b1d831e2..301ab0f8f21 100644 --- a/include/configs/stm32f746-disco.h +++ b/include/configs/stm32f746-disco.h @@ -37,7 +37,6 @@ #define CONFIG_MII #define CONFIG_PHY_SMSC -#define CONFIG_STM32_HSE_HZ 25000000 #define CONFIG_SYS_CLK_FREQ 200000000 /* 200 MHz */ #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ diff --git a/include/configs/stv0991.h b/include/configs/stv0991.h index beb8f1ae9a9..c21fea3fe1b 100644 --- a/include/configs/stv0991.h +++ b/include/configs/stv0991.h @@ -25,9 +25,6 @@ (PHYS_SDRAM_1_SIZE - CONFIG_ENV_SIZE) #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 16 * 1024) -/* serial port (PL011) configuration */ -#define CONFIG_PL01X_SERIAL - /* user interface */ #define CONFIG_SYS_CBSIZE 1024 diff --git a/include/configs/thunderx_88xx.h b/include/configs/thunderx_88xx.h index 209a7c34175..34940efb412 100644 --- a/include/configs/thunderx_88xx.h +++ b/include/configs/thunderx_88xx.h @@ -35,7 +35,6 @@ /* PL011 Serial Configuration */ -#define CONFIG_PL01X_SERIAL #define CONFIG_PL011_CLOCK 24000000 #define CONFIG_CONS_INDEX 1 diff --git a/include/configs/vexpress_aemv8a.h b/include/configs/vexpress_aemv8a.h index 6203e141356..07cc92ce170 100644 --- a/include/configs/vexpress_aemv8a.h +++ b/include/configs/vexpress_aemv8a.h @@ -110,8 +110,6 @@ /* PL011 Serial Configuration */ #define CONFIG_CONS_INDEX 0 -#define CONFIG_PL01X_SERIAL -#define CONFIG_PL011_SERIAL #ifdef CONFIG_TARGET_VEXPRESS64_JUNO #define CONFIG_PL011_CLOCK 7273800 #else diff --git a/include/configs/vexpress_common.h b/include/configs/vexpress_common.h index 294ca181865..94a352fef7d 100644 --- a/include/configs/vexpress_common.h +++ b/include/configs/vexpress_common.h @@ -133,7 +133,6 @@ #define CONFIG_SYS_TIMER_COUNTS_DOWN /* PL011 Serial Configuration */ -#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK 24000000 #define CONFIG_PL01x_PORTS {(void *)CONFIG_SYS_SERIAL0, \ (void *)CONFIG_SYS_SERIAL1} diff --git a/include/configs/x600.h b/include/configs/x600.h index 4aa5a2a924f..66a8e889024 100644 --- a/include/configs/x600.h +++ b/include/configs/x600.h @@ -38,7 +38,6 @@ #define CONFIG_SYS_SERIAL1 0xD0080000 #define CONFIG_PL01x_PORTS { (void *)CONFIG_SYS_SERIAL0, \ (void *)CONFIG_SYS_SERIAL1 } -#define CONFIG_PL011_SERIAL #define CONFIG_PL011_CLOCK (48 * 1000 * 1000) #define CONFIG_CONS_INDEX 0 #define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, \ diff --git a/include/dm/platform_data/serial_bcm283x_mu.h b/include/dm/platform_data/serial_bcm283x_mu.h index c47d3c0e60e..57ae6adc053 100644 --- a/include/dm/platform_data/serial_bcm283x_mu.h +++ b/include/dm/platform_data/serial_bcm283x_mu.h @@ -19,7 +19,6 @@ struct bcm283x_mu_serial_platdata { unsigned long base; unsigned int clock; bool skip_init; - bool disabled; }; #endif diff --git a/include/dm/read.h b/include/dm/read.h index f1f0dfd4a33..f14c7a7ba87 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -265,7 +265,7 @@ int dev_count_phandle_with_args(struct udevice *dev, const char *list_name, * This walks back up the tree to find the closest #address-cells property * which controls the given node. * - * @dev: devioe to check + * @dev: device to check * @return number of address cells this node uses */ int dev_read_addr_cells(struct udevice *dev); @@ -276,7 +276,7 @@ int dev_read_addr_cells(struct udevice *dev); * This walks back up the tree to find the closest #size-cells property * which controls the given node. * - * @dev: devioe to check + * @dev: device to check * @return number of size cells this node uses */ int dev_read_size_cells(struct udevice *dev); @@ -286,7 +286,7 @@ int dev_read_size_cells(struct udevice *dev); * * This function matches fdt_address_cells(). * - * @dev: devioe to check + * @dev: device to check * @return number of address cells this node uses */ int dev_read_simple_addr_cells(struct udevice *dev); @@ -296,7 +296,7 @@ int dev_read_simple_addr_cells(struct udevice *dev); * * This function matches fdt_size_cells(). * - * @dev: devioe to check + * @dev: device to check * @return number of size cells this node uses */ int dev_read_simple_size_cells(struct udevice *dev); diff --git a/include/libfdt.h b/include/libfdt.h index 7ba13e634b6..b00e9935a01 100644 --- a/include/libfdt.h +++ b/include/libfdt.h @@ -1 +1,318 @@ -#include "../lib/libfdt/libfdt.h" +#ifndef UBOOT_LIBFDT_H +#define UBOOT_LIBFDT_H +/* + * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause + */ + +#ifdef USE_HOSTCC +#include "../scripts/dtc/libfdt/libfdt.h" +#else +#include <linux/libfdt.h> +#endif + +/* U-Boot local hacks */ + +#ifndef SWIG /* Not available in Python */ +struct fdt_region { + int offset; + int size; +}; + +/* + * Flags for fdt_find_regions() + * + * Add a region for the string table (always the last region) + */ +#define FDT_REG_ADD_STRING_TAB (1 << 0) + +/* + * Add all supernodes of a matching node/property, useful for creating a + * valid subset tree + */ +#define FDT_REG_SUPERNODES (1 << 1) + +/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */ +#define FDT_REG_DIRECT_SUBNODES (1 << 2) + +/* Add all subnodes of a matching node */ +#define FDT_REG_ALL_SUBNODES (1 << 3) + +/* Add a region for the mem_rsvmap table (always the first region) */ +#define FDT_REG_ADD_MEM_RSVMAP (1 << 4) + +/* Indicates what an fdt part is (node, property, value) */ +#define FDT_IS_NODE (1 << 0) +#define FDT_IS_PROP (1 << 1) +#define FDT_IS_VALUE (1 << 2) /* not supported */ +#define FDT_IS_COMPAT (1 << 3) /* used internally */ +#define FDT_NODE_HAS_PROP (1 << 4) /* node contains prop */ + +#define FDT_ANY_GLOBAL (FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \ + FDT_IS_COMPAT) +#define FDT_IS_ANY 0x1f /* all the above */ + +/* We set a reasonable limit on the number of nested nodes */ +#define FDT_MAX_DEPTH 32 + +/* Decribes what we want to include from the current tag */ +enum want_t { + WANT_NOTHING, + WANT_NODES_ONLY, /* No properties */ + WANT_NODES_AND_PROPS, /* Everything for one level */ + WANT_ALL_NODES_AND_PROPS /* Everything for all levels */ +}; + +/* Keeps track of the state at parent nodes */ +struct fdt_subnode_stack { + int offset; /* Offset of node */ + enum want_t want; /* The 'want' value here */ + int included; /* 1 if we included this node, 0 if not */ +}; + +struct fdt_region_ptrs { + int depth; /* Current tree depth */ + int done; /* What we have completed scanning */ + enum want_t want; /* What we are currently including */ + char *end; /* Pointer to end of full node path */ + int nextoffset; /* Next node offset to check */ +}; + +/* The state of our finding algortihm */ +struct fdt_region_state { + struct fdt_subnode_stack stack[FDT_MAX_DEPTH]; /* node stack */ + struct fdt_region *region; /* Contains list of regions found */ + int count; /* Numnber of regions found */ + const void *fdt; /* FDT blob */ + int max_regions; /* Maximum regions to find */ + int can_merge; /* 1 if we can merge with previous region */ + int start; /* Start position of current region */ + struct fdt_region_ptrs ptrs; /* Pointers for what we are up to */ +}; + +/** + * fdt_find_regions() - find regions in device tree + * + * Given a list of nodes to include and properties to exclude, find + * the regions of the device tree which describe those included parts. + * + * The intent is to get a list of regions which will be invariant provided + * those parts are invariant. For example, if you request a list of regions + * for all nodes but exclude the property "data", then you will get the + * same region contents regardless of any change to "data" properties. + * + * This function can be used to produce a byte-stream to send to a hashing + * function to verify that critical parts of the FDT have not changed. + * + * Nodes which are given in 'inc' are included in the region list, as + * are the names of the immediate subnodes nodes (but not the properties + * or subnodes of those subnodes). + * + * For eaxample "/" means to include the root node, all root properties + * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter + * ensures that we capture the names of the subnodes. In a hashing situation + * it prevents the root node from changing at all Any change to non-excluded + * properties, names of subnodes or number of subnodes would be detected. + * + * When used with FITs this provides the ability to hash and sign parts of + * the FIT based on different configurations in the FIT. Then it is + * impossible to change anything about that configuration (include images + * attached to the configuration), but it may be possible to add new + * configurations, new images or new signatures within the existing + * framework. + * + * Adding new properties to a device tree may result in the string table + * being extended (if the new property names are different from those + * already added). This function can optionally include a region for + * the string table so that this can be part of the hash too. + * + * The device tree header is not included in the list. + * + * @fdt: Device tree to check + * @inc: List of node paths to included + * @inc_count: Number of node paths in list + * @exc_prop: List of properties names to exclude + * @exc_prop_count: Number of properties in exclude list + * @region: Returns list of regions + * @max_region: Maximum length of region list + * @path: Pointer to a temporary string for the function to use for + * building path names + * @path_len: Length of path, must be large enough to hold the longest + * path in the tree + * @add_string_tab: 1 to add a region for the string table + * @return number of regions in list. If this is >max_regions then the + * region array was exhausted. You should increase max_regions and try + * the call again. + */ +int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, + char * const exc_prop[], int exc_prop_count, + struct fdt_region region[], int max_regions, + char *path, int path_len, int add_string_tab); + +/** + * fdt_first_region() - find regions in device tree + * + * Given a nodes and properties to include and properties to exclude, find + * the regions of the device tree which describe those included parts. + * + * The use for this function is twofold. Firstly it provides a convenient + * way of performing a structure-aware grep of the tree. For example it is + * possible to grep for a node and get all the properties associated with + * that node. Trees can be subsetted easily, by specifying the nodes that + * are required, and then writing out the regions returned by this function. + * This is useful for small resource-constrained systems, such as boot + * loaders, which want to use an FDT but do not need to know about all of + * it. + * + * Secondly it makes it easy to hash parts of the tree and detect changes. + * The intent is to get a list of regions which will be invariant provided + * those parts are invariant. For example, if you request a list of regions + * for all nodes but exclude the property "data", then you will get the + * same region contents regardless of any change to "data" properties. + * + * This function can be used to produce a byte-stream to send to a hashing + * function to verify that critical parts of the FDT have not changed. + * Note that semantically null changes in order could still cause false + * hash misses. Such reordering might happen if the tree is regenerated + * from source, and nodes are reordered (the bytes-stream will be emitted + * in a different order and many hash functions will detect this). However + * if an existing tree is modified using libfdt functions, such as + * fdt_add_subnode() and fdt_setprop(), then this problem is avoided. + * + * The nodes/properties to include/exclude are defined by a function + * provided by the caller. This function is called for each node and + * property, and must return: + * + * 0 - to exclude this part + * 1 - to include this part + * -1 - for FDT_IS_PROP only: no information is available, so include + * if its containing node is included + * + * The last case is only used to deal with properties. Often a property is + * included if its containing node is included - this is the case where + * -1 is returned.. However if the property is specifically required to be + * included/excluded, then 0 or 1 can be returned. Note that including a + * property when the FDT_REG_SUPERNODES flag is given will force its + * containing node to be included since it is not valid to have a property + * that is not in a node. + * + * Using the information provided, the inclusion of a node can be controlled + * either by a node name or its compatible string, or any other property + * that the function can determine. + * + * As an example, including node "/" means to include the root node and all + * root properties. A flag provides a way of also including supernodes (of + * which there is none for the root node), and another flag includes + * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and + * FDT_END_NODE of all subnodes of /. + * + * The subnode feature helps in a hashing situation since it prevents the + * root node from changing at all. Any change to non-excluded properties, + * names of subnodes or number of subnodes would be detected. + * + * When used with FITs this provides the ability to hash and sign parts of + * the FIT based on different configurations in the FIT. Then it is + * impossible to change anything about that configuration (include images + * attached to the configuration), but it may be possible to add new + * configurations, new images or new signatures within the existing + * framework. + * + * Adding new properties to a device tree may result in the string table + * being extended (if the new property names are different from those + * already added). This function can optionally include a region for + * the string table so that this can be part of the hash too. This is always + * the last region. + * + * The FDT also has a mem_rsvmap table which can also be included, and is + * always the first region if so. + * + * The device tree header is not included in the region list. Since the + * contents of the FDT are changing (shrinking, often), the caller will need + * to regenerate the header anyway. + * + * @fdt: Device tree to check + * @h_include: Function to call to determine whether to include a part or + * not: + * + * @priv: Private pointer as passed to fdt_find_regions() + * @fdt: Pointer to FDT blob + * @offset: Offset of this node / property + * @type: Type of this part, FDT_IS_... + * @data: Pointer to data (node name, property name, compatible + * string, value (not yet supported) + * @size: Size of data, or 0 if none + * @return 0 to exclude, 1 to include, -1 if no information is + * available + * @priv: Private pointer passed to h_include + * @region: Returns list of regions, sorted by offset + * @max_regions: Maximum length of region list + * @path: Pointer to a temporary string for the function to use for + * building path names + * @path_len: Length of path, must be large enough to hold the longest + * path in the tree + * @flags: Various flags that control the region algortihm, see + * FDT_REG_... + * @return number of regions in list. If this is >max_regions then the + * region array was exhausted. You should increase max_regions and try + * the call again. Only the first max_regions elements are available in the + * array. + * + * On error a -ve value is return, which can be: + * + * -FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_NOSPACE (path area is too small) + */ +int fdt_first_region(const void *fdt, + int (*h_include)(void *priv, const void *fdt, int offset, + int type, const char *data, int size), + void *priv, struct fdt_region *region, + char *path, int path_len, int flags, + struct fdt_region_state *info); + +/** fdt_next_region() - find next region + * + * See fdt_first_region() for full description. This function finds the + * next region according to the provided parameters, which must be the same + * as passed to fdt_first_region(). + * + * This function can additionally return -FDT_ERR_NOTFOUND when there are no + * more regions + */ +int fdt_next_region(const void *fdt, + int (*h_include)(void *priv, const void *fdt, int offset, + int type, const char *data, int size), + void *priv, struct fdt_region *region, + char *path, int path_len, int flags, + struct fdt_region_state *info); + +/** + * fdt_add_alias_regions() - find aliases that point to existing regions + * + * Once a device tree grep is complete some of the nodes will be present + * and some will have been dropped. This function checks all the alias nodes + * to figure out which points point to nodes which are still present. These + * aliases need to be kept, along with the nodes they reference. + * + * Given a list of regions function finds the aliases that still apply and + * adds more regions to the list for these. This function is called after + * fdt_next_region() has finished returning regions and requires the same + * state. + * + * @fdt: Device tree file to reference + * @region: List of regions that will be kept + * @count: Number of regions + * @max_regions: Number of entries that can fit in @region + * @info: Region state as returned from fdt_next_region() + * @return new number of regions in @region (i.e. count + the number added) + * or -FDT_ERR_NOSPACE if there was not enough space. + */ +int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count, + int max_regions, struct fdt_region_state *info); +#endif /* SWIG */ + +extern struct fdt_header *working_fdt; /* Pointer to the working fdt */ + +/* adding a ramdisk needs 0x44 bytes in version 2008.10 */ +#define FDT_RAMDISK_OVERHEAD 0x80 + +#endif /* UBOOT_LIBFDT_H */ diff --git a/include/libfdt_env.h b/include/libfdt_env.h index 273b5d30f86..d7e9d328635 100644 --- a/include/libfdt_env.h +++ b/include/libfdt_env.h @@ -1,29 +1,5 @@ -/* - * libfdt - Flat Device Tree manipulation (build/run environment adaptation) - * Copyright (C) 2007 Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com - * Original version written by David Gibson, IBM Corporation. - * - * SPDX-License-Identifier: LGPL-2.1+ - */ - -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H - -#include "compiler.h" -#include "linux/types.h" - -extern struct fdt_header *working_fdt; /* Pointer to the working fdt */ - -typedef __be16 fdt16_t; -typedef __be32 fdt32_t; -typedef __be64 fdt64_t; - -#define fdt32_to_cpu(x) be32_to_cpu(x) -#define cpu_to_fdt32(x) cpu_to_be32(x) -#define fdt64_to_cpu(x) be64_to_cpu(x) -#define cpu_to_fdt64(x) cpu_to_be64(x) - -/* adding a ramdisk needs 0x44 bytes in version 2008.10 */ -#define FDT_RAMDISK_OVERHEAD 0x80 - -#endif /* _LIBFDT_ENV_H */ +#ifdef USE_HOSTCC +#include "../scripts/dtc/libfdt/libfdt_env.h" +#else +#include <linux/libfdt_env.h> +#endif diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h index 2a663c6bb42..90ed4ebfa69 100644 --- a/include/linux/libfdt.h +++ b/include/linux/libfdt.h @@ -1,17 +1,8 @@ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _INCLUDE_LIBFDT_H_ +#define _INCLUDE_LIBFDT_H_ -#include <linux/string.h> +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/libfdt.h" -#include <asm/byteorder.h> - -typedef __be16 fdt16_t; -typedef __be32 fdt32_t; -typedef __be64 fdt64_t; - -#define fdt32_to_cpu(x) be32_to_cpu(x) -#define cpu_to_fdt32(x) cpu_to_be32(x) -#define fdt64_to_cpu(x) be64_to_cpu(x) -#define cpu_to_fdt64(x) cpu_to_be64(x) - -#endif /* _LIBFDT_ENV_H */ +#endif /* _INCLUDE_LIBFDT_H_ */ diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile index be42e946b79..4e3e12f505d 100644 --- a/lib/libfdt/Makefile +++ b/lib/libfdt/Makefile @@ -11,6 +11,7 @@ obj-y += \ fdt_wip.o \ fdt_strerror.o \ fdt_sw.o \ + fdt_rw.o \ fdt_empty_tree.o \ fdt_addresses.o @@ -18,9 +19,7 @@ obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o # Locally modified for U-Boot. # TODO: split out the local modifiction. -obj-y += \ - fdt_ro.o \ - fdt_rw.o +obj-y += fdt_ro.o # U-Boot own file obj-y += fdt_region.o diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c index 3dc775261fb..aafded07a15 100644 --- a/lib/libfdt/fdt_rw.c +++ b/lib/libfdt/fdt_rw.c @@ -1,496 +1,2 @@ -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ -#include <libfdt_env.h> - -#ifndef USE_HOSTCC -#include <fdt.h> -#include <libfdt.h> -#else -#include "fdt_host.h" -#endif - -#include "libfdt_internal.h" - -static int _fdt_blocks_misordered(const void *fdt, - int mem_rsv_size, int struct_size) -{ - return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) - || (fdt_off_dt_struct(fdt) < - (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) - || (fdt_off_dt_strings(fdt) < - (fdt_off_dt_struct(fdt) + struct_size)) - || (fdt_totalsize(fdt) < - (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); -} - -static int _fdt_rw_check_header(void *fdt) -{ - FDT_CHECK_HEADER(fdt); - - if (fdt_version(fdt) < 17) - return -FDT_ERR_BADVERSION; - if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry), - fdt_size_dt_struct(fdt))) - return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) - fdt_set_version(fdt, 17); - - return 0; -} - -#define FDT_RW_CHECK_HEADER(fdt) \ - { \ - int __err; \ - if ((__err = _fdt_rw_check_header(fdt)) != 0) \ - return __err; \ - } - -static inline int _fdt_data_size(void *fdt) -{ - return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); -} - -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) -{ - char *p = splicepoint; - char *end = (char *)fdt + _fdt_data_size(fdt); - - if (((p + oldlen) < p) || ((p + oldlen) > end)) - return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) - return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) - return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); - return 0; -} - -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p, - int oldn, int newn) -{ - int delta = (newn - oldn) * sizeof(*p); - int err; - err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); - if (err) - return err; - fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_struct(void *fdt, void *p, - int oldlen, int newlen) -{ - int delta = newlen - oldlen; - int err; - - if ((err = _fdt_splice(fdt, p, oldlen, newlen))) - return err; - - fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); - fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); - return 0; -} - -static int _fdt_splice_string(void *fdt, int newlen) -{ - void *p = (char *)fdt - + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); - int err; - - if ((err = _fdt_splice(fdt, p, 0, newlen))) - return err; - - fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); - return 0; -} - -static int _fdt_find_add_string(void *fdt, const char *s) -{ - char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); - const char *p; - char *new; - int len = strlen(s) + 1; - int err; - - p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s); - if (p) - /* found it */ - return (p - strtab); - - new = strtab + fdt_size_dt_strings(fdt); - err = _fdt_splice_string(fdt, len); - if (err) - return err; - - memcpy(new, s, len); - return (new - strtab); -} - -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) -{ - struct fdt_reserve_entry *re; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt)); - err = _fdt_splice_mem_rsv(fdt, re, 0, 1); - if (err) - return err; - - re->address = cpu_to_fdt64(address); - re->size = cpu_to_fdt64(size); - return 0; -} - -int fdt_del_mem_rsv(void *fdt, int n) -{ - struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); - - FDT_RW_CHECK_HEADER(fdt); - - if (n >= fdt_num_mem_rsv(fdt)) - return -FDT_ERR_NOTFOUND; - - return _fdt_splice_mem_rsv(fdt, re, 1, 0); -} - -static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int oldlen; - int err; - - *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (!*prop) - return oldlen; - - if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(len)))) - return err; - - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -static int _fdt_add_property(void *fdt, int nodeoffset, const char *name, - int len, struct fdt_property **prop) -{ - int proplen; - int nextoffset; - int namestroff; - int err; - - if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0) - return nextoffset; - - namestroff = _fdt_find_add_string(fdt, name); - if (namestroff < 0) - return namestroff; - - *prop = _fdt_offset_ptr_w(fdt, nextoffset); - proplen = sizeof(**prop) + FDT_TAGALIGN(len); - - err = _fdt_splice_struct(fdt, *prop, 0, proplen); - if (err) - return err; - - (*prop)->tag = cpu_to_fdt32(FDT_PROP); - (*prop)->nameoff = cpu_to_fdt32(namestroff); - (*prop)->len = cpu_to_fdt32(len); - return 0; -} - -int fdt_set_name(void *fdt, int nodeoffset, const char *name) -{ - char *namep; - int oldlen, newlen; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); - if (!namep) - return oldlen; - - newlen = strlen(name); - - err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1), - FDT_TAGALIGN(newlen+1)); - if (err) - return err; - - memcpy(namep, name, newlen+1); - return 0; -} - -int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, - int len, void **prop_data) -{ - struct fdt_property *prop; - int err; - - FDT_RW_CHECK_HEADER(fdt); - - err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop); - if (err == -FDT_ERR_NOTFOUND) - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - - *prop_data = prop->data; - return 0; -} - -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - void *prop_data; - int err; - - err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); - if (err) - return err; - - if (len) - memcpy(prop_data, val, len); - return 0; -} - -int fdt_appendprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) -{ - struct fdt_property *prop; - int err, oldlen, newlen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); - if (prop) { - newlen = len + oldlen; - err = _fdt_splice_struct(fdt, prop->data, - FDT_TAGALIGN(oldlen), - FDT_TAGALIGN(newlen)); - if (err) - return err; - prop->len = cpu_to_fdt32(newlen); - memcpy(prop->data + oldlen, val, len); - } else { - err = _fdt_add_property(fdt, nodeoffset, name, len, &prop); - if (err) - return err; - memcpy(prop->data, val, len); - } - return 0; -} - -int fdt_delprop(void *fdt, int nodeoffset, const char *name) -{ - struct fdt_property *prop; - int len, proplen; - - FDT_RW_CHECK_HEADER(fdt); - - prop = fdt_get_property_w(fdt, nodeoffset, name, &len); - if (!prop) - return len; - - proplen = sizeof(*prop) + FDT_TAGALIGN(len); - return _fdt_splice_struct(fdt, prop, proplen, 0); -} - -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen) -{ - struct fdt_node_header *nh; - int offset, nextoffset; - int nodelen; - int err; - uint32_t tag; - fdt32_t *endtag; - - FDT_RW_CHECK_HEADER(fdt); - - offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); - if (offset >= 0) - return -FDT_ERR_EXISTS; - else if (offset != -FDT_ERR_NOTFOUND) - return offset; - - /* Try to place the new node after the parent's properties */ - fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ - do { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - } while ((tag == FDT_PROP) || (tag == FDT_NOP)); - - nh = _fdt_offset_ptr_w(fdt, offset); - nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; - - err = _fdt_splice_struct(fdt, nh, 0, nodelen); - if (err) - return err; - - nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); - memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); - memcpy(nh->name, name, namelen); - endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); - *endtag = cpu_to_fdt32(FDT_END_NODE); - - return offset; -} - -int fdt_add_subnode(void *fdt, int parentoffset, const char *name) -{ - return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); -} - -int fdt_del_node(void *fdt, int nodeoffset) -{ - int endoffset; - - FDT_RW_CHECK_HEADER(fdt); - - endoffset = _fdt_node_end_offset(fdt, nodeoffset); - if (endoffset < 0) - return endoffset; - - return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset), - endoffset - nodeoffset, 0); -} - -static void _fdt_packblocks(const char *old, char *new, - int mem_rsv_size, int struct_size) -{ - int mem_rsv_off, struct_off, strings_off; - - mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); - struct_off = mem_rsv_off + mem_rsv_size; - strings_off = struct_off + struct_size; - - memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); - fdt_set_off_mem_rsvmap(new, mem_rsv_off); - - memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); - fdt_set_off_dt_struct(new, struct_off); - fdt_set_size_dt_struct(new, struct_size); - - memmove(new + strings_off, old + fdt_off_dt_strings(old), - fdt_size_dt_strings(old)); - fdt_set_off_dt_strings(new, strings_off); - fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); -} - -int fdt_open_into(const void *fdt, void *buf, int bufsize) -{ - int err; - int mem_rsv_size, struct_size; - int newsize; - const char *fdtstart = fdt; - const char *fdtend = fdtstart + fdt_totalsize(fdt); - char *tmp; - - FDT_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - - if (fdt_version(fdt) >= 17) { - struct_size = fdt_size_dt_struct(fdt); - } else { - struct_size = 0; - while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) - ; - if (struct_size < 0) - return struct_size; - } - - if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) { - /* no further work necessary */ - err = fdt_move(fdt, buf, bufsize); - if (err) - return err; - fdt_set_version(buf, 17); - fdt_set_size_dt_struct(buf, struct_size); - fdt_set_totalsize(buf, bufsize); - return 0; - } - - /* Need to reorder */ - newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size - + struct_size + fdt_size_dt_strings(fdt); - - if (bufsize < newsize) - return -FDT_ERR_NOSPACE; - - /* First attempt to build converted tree at beginning of buffer */ - tmp = buf; - /* But if that overlaps with the old tree... */ - if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { - /* Try right after the old tree instead */ - tmp = (char *)(uintptr_t)fdtend; - if ((tmp + newsize) > ((char *)buf + bufsize)) - return -FDT_ERR_NOSPACE; - } - - _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size); - memmove(buf, tmp, newsize); - - fdt_set_magic(buf, FDT_MAGIC); - fdt_set_totalsize(buf, bufsize); - fdt_set_version(buf, 17); - fdt_set_last_comp_version(buf, 16); - fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); - - return 0; -} - -int fdt_pack(void *fdt) -{ - int mem_rsv_size; - - FDT_RW_CHECK_HEADER(fdt); - - mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) - * sizeof(struct fdt_reserve_entry); - _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); - fdt_set_totalsize(fdt, _fdt_data_size(fdt)); - - return 0; -} - -int fdt_remove_unused_strings(const void *old, void *new) -{ - const struct fdt_property *old_prop; - struct fdt_property *new_prop; - int size = fdt_totalsize(old); - int next_offset, offset; - const char *str; - int ret; - int tag = FDT_PROP; - - /* Make a copy and remove the strings */ - memcpy(new, old, size); - fdt_set_size_dt_strings(new, 0); - - /* Add every property name back into the new string table */ - for (offset = 0; tag != FDT_END; offset = next_offset) { - tag = fdt_next_tag(old, offset, &next_offset); - if (tag != FDT_PROP) - continue; - old_prop = fdt_get_property_by_offset(old, offset, NULL); - new_prop = (struct fdt_property *)(unsigned long) - fdt_get_property_by_offset(new, offset, NULL); - str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff)); - ret = _fdt_find_add_string(new, str); - if (ret < 0) - return ret; - new_prop->nameoff = cpu_to_fdt32(ret); - } - - return 0; -} +#include <linux/libfdt_env.h> +#include "../../scripts/dtc/libfdt/fdt_rw.c" diff --git a/lib/libfdt/libfdt.h b/lib/libfdt/libfdt.h deleted file mode 100644 index 6af94cb3f75..00000000000 --- a/lib/libfdt/libfdt.h +++ /dev/null @@ -1,2170 +0,0 @@ -#ifndef _LIBFDT_H -#define _LIBFDT_H -/* - * libfdt - Flat Device Tree manipulation - * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause - */ - -#include <libfdt_env.h> -#include <fdt.h> - -#define FDT_FIRST_SUPPORTED_VERSION 0x10 -#define FDT_LAST_SUPPORTED_VERSION 0x11 - -/* Error codes: informative error codes */ -#define FDT_ERR_NOTFOUND 1 - /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ -#define FDT_ERR_EXISTS 2 - /* FDT_ERR_EXISTS: Attempted to create a node or property which - * already exists */ -#define FDT_ERR_NOSPACE 3 - /* FDT_ERR_NOSPACE: Operation needed to expand the device - * tree, but its buffer did not have sufficient space to - * contain the expanded tree. Use fdt_open_into() to move the - * device tree to a buffer with more space. */ - -/* Error codes: codes for bad parameters */ -#define FDT_ERR_BADOFFSET 4 - /* FDT_ERR_BADOFFSET: Function was passed a structure block - * offset which is out-of-bounds, or which points to an - * unsuitable part of the structure for the operation. */ -#define FDT_ERR_BADPATH 5 - /* FDT_ERR_BADPATH: Function was passed a badly formatted path - * (e.g. missing a leading / for a function which requires an - * absolute path) */ -#define FDT_ERR_BADPHANDLE 6 - /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. - * This can be caused either by an invalid phandle property - * length, or the phandle value was either 0 or -1, which are - * not permitted. */ -#define FDT_ERR_BADSTATE 7 - /* FDT_ERR_BADSTATE: Function was passed an incomplete device - * tree created by the sequential-write functions, which is - * not sufficiently complete for the requested operation. */ - -/* Error codes: codes for bad device tree blobs */ -#define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: Structure block of the given device tree - * ends without an FDT_END tag. */ -#define FDT_ERR_BADMAGIC 9 - /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a - * device tree at all - it is missing the flattened device - * tree magic number. */ -#define FDT_ERR_BADVERSION 10 - /* FDT_ERR_BADVERSION: Given device tree has a version which - * can't be handled by the requested operation. For - * read-write functions, this may mean that fdt_open_into() is - * required to convert the tree to the expected version. */ -#define FDT_ERR_BADSTRUCTURE 11 - /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt - * structure block or other serious error (e.g. misnested - * nodes, or subnodes preceding properties). */ -#define FDT_ERR_BADLAYOUT 12 - /* FDT_ERR_BADLAYOUT: For read-write functions, the given - * device tree has it's sub-blocks in an order that the - * function can't handle (memory reserve map, then structure, - * then strings). Use fdt_open_into() to reorganize the tree - * into a form suitable for the read-write operations. */ - -/* "Can't happen" error indicating a bug in libfdt */ -#define FDT_ERR_INTERNAL 13 - /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. - * Should never be returned, if it is, it indicates a bug in - * libfdt itself. */ - -/* Errors in device tree content */ -#define FDT_ERR_BADNCELLS 14 - /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells - * or similar property with a bad format or value */ - -#define FDT_ERR_BADVALUE 15 - /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected - * value. For example: a property expected to contain a string list - * is not NUL-terminated within the length of its value. */ - -#define FDT_ERR_BADOVERLAY 16 - /* FDT_ERR_BADOVERLAY: The device tree overlay, while - * correctly structured, cannot be applied due to some - * unexpected or missing value, property or node. */ - -#define FDT_ERR_NOPHANDLES 17 - /* FDT_ERR_NOPHANDLES: The device tree doesn't have any - * phandle available anymore without causing an overflow */ - -#define FDT_ERR_MAX 17 - -/**********************************************************************/ -/* Low-level functions (you probably don't need these) */ -/**********************************************************************/ - -#ifndef SWIG /* This function is not useful in Python */ -const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); -#endif -static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) -{ - return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); -} - -uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); - -/**********************************************************************/ -/* Traversal functions */ -/**********************************************************************/ - -int fdt_next_node(const void *fdt, int offset, int *depth); - -/** - * fdt_first_subnode() - get offset of first direct subnode - * - * @fdt: FDT blob - * @offset: Offset of node to check - * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none - */ -int fdt_first_subnode(const void *fdt, int offset); - -/** - * fdt_next_subnode() - get offset of next direct subnode - * - * After first calling fdt_first_subnode(), call this function repeatedly to - * get direct subnodes of a parent node. - * - * @fdt: FDT blob - * @offset: Offset of previous subnode - * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more - * subnodes - */ -int fdt_next_subnode(const void *fdt, int offset); - -/** - * fdt_for_each_subnode - iterate over all subnodes of a parent - * - * @node: child node (int, lvalue) - * @fdt: FDT blob (const void *) - * @parent: parent node (int) - * - * This is actually a wrapper around a for loop and would be used like so: - * - * fdt_for_each_subnode(node, fdt, parent) { - * Use node - * ... - * } - * - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { - * Error handling - * } - * - * Note that this is implemented as a macro and @node is used as - * iterator in the loop. The parent variable be constant or even a - * literal. - * - */ -#define fdt_for_each_subnode(node, fdt, parent) \ - for (node = fdt_first_subnode(fdt, parent); \ - node >= 0; \ - node = fdt_next_subnode(fdt, node)) - -/**********************************************************************/ -/* General functions */ -/**********************************************************************/ -#define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) -#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) -#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) -#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) -#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) -#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) -#define fdt_version(fdt) (fdt_get_header(fdt, version)) -#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) -#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) -#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) -#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) - -#define __fdt_set_hdr(name) \ - static inline void fdt_set_##name(void *fdt, uint32_t val) \ - { \ - struct fdt_header *fdth = (struct fdt_header *)fdt; \ - fdth->name = cpu_to_fdt32(val); \ - } -__fdt_set_hdr(magic); -__fdt_set_hdr(totalsize); -__fdt_set_hdr(off_dt_struct); -__fdt_set_hdr(off_dt_strings); -__fdt_set_hdr(off_mem_rsvmap); -__fdt_set_hdr(version); -__fdt_set_hdr(last_comp_version); -__fdt_set_hdr(boot_cpuid_phys); -__fdt_set_hdr(size_dt_strings); -__fdt_set_hdr(size_dt_struct); -#undef __fdt_set_hdr - -/** - * fdt_check_header - sanity check a device tree or possible device tree - * @fdt: pointer to data which might be a flattened device tree - * - * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree with sane information in its - * header. - * - * returns: - * 0, if the buffer appears to contain a valid device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings, as above - */ -int fdt_check_header(const void *fdt); - -/** - * fdt_move - move a device tree around in memory - * @fdt: pointer to the device tree to move - * @buf: pointer to memory where the device is to be moved - * @bufsize: size of the memory space at buf - * - * fdt_move() relocates, if possible, the device tree blob located at - * fdt to the buffer at buf of size bufsize. The buffer may overlap - * with the existing device tree blob at fdt. Therefore, - * fdt_move(fdt, fdt, fdt_totalsize(fdt)) - * should always succeed. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_move(const void *fdt, void *buf, int bufsize); - -/**********************************************************************/ -/* Read-only functions */ -/**********************************************************************/ - -/** - * fdt_string - retrieve a string from the strings block of a device tree - * @fdt: pointer to the device tree blob - * @stroffset: offset of the string within the strings block (native endian) - * - * fdt_string() retrieves a pointer to a single string from the - * strings block of the device tree blob at fdt. - * - * returns: - * a pointer to the string, on success - * NULL, if stroffset is out of bounds - */ -const char *fdt_string(const void *fdt, int stroffset); - -/** - * fdt_get_max_phandle - retrieves the highest phandle in a tree - * @fdt: pointer to the device tree blob - * - * fdt_get_max_phandle retrieves the highest phandle in the given - * device tree. This will ignore badly formatted phandles, or phandles - * with a value of 0 or -1. - * - * returns: - * the highest phandle on success - * 0, if no phandle was found in the device tree - * -1, if an error occurred - */ -uint32_t fdt_get_max_phandle(const void *fdt); - -/** - * fdt_num_mem_rsv - retrieve the number of memory reserve map entries - * @fdt: pointer to the device tree blob - * - * Returns the number of entries in the device tree blob's memory - * reservation map. This does not include the terminating 0,0 entry - * or any other (0,0) entries reserved for expansion. - * - * returns: - * the number of entries - */ -int fdt_num_mem_rsv(const void *fdt); - -/** - * fdt_get_mem_rsv - retrieve one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: pointers to 64-bit variables - * - * On success, *address and *size will contain the address and size of - * the n-th reserve map entry from the device tree blob, in - * native-endian format. - * - * returns: - * 0, on success - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); - -/** - * fdt_subnode_offset_namelen - find a subnode based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_subnode_offset(), but only examine the first - * namelen characters of name for matching the subnode name. This is - * useful for finding subnodes based on a portion of a larger string, - * such as a full path. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, - const char *name, int namelen); -#endif -/** - * fdt_subnode_offset - find a subnode of a given node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_subnode_offset() finds a subnode of the node at structure block - * offset parentoffset with the given name. name may include a unit - * address, in which case fdt_subnode_offset() will find the subnode - * with that unit address, or the unit address may be omitted, in - * which case fdt_subnode_offset() will find an arbitrary subnode - * whose name excluding unit address matches the given name. - * - * returns: - * structure block offset of the requested subnode (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); - -/** - * fdt_path_offset_namelen - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate - * @namelen: number of characters of path to consider - * - * Identical to fdt_path_offset(), but only consider the first namelen - * characters of path as the path name. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); -#endif - -/** - * fdt_path_offset - find a tree node by its full path - * @fdt: pointer to the device tree blob - * @path: full path of the node to locate - * - * fdt_path_offset() finds a node of a given path in the device tree. - * Each path component may omit the unit address portion, but the - * results of this are undefined if any such path component is - * ambiguous (that is if there are multiple nodes at the relevant - * level matching the given component, differentiated only by unit - * address). - * - * returns: - * structure block offset of the node with the requested path (>=0), on - * success - * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid - * -FDT_ERR_NOTFOUND, if the requested node does not exist - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_path_offset(const void *fdt, const char *path); - -/** - * fdt_get_name - retrieve the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the starting node - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_name() retrieves the name (including unit address) of the - * device tree node at structure block offset nodeoffset. If lenp is - * non-NULL, the length of this name is also returned, in the integer - * pointed to by lenp. - * - * returns: - * pointer to the node's name, on success - * If lenp is non-NULL, *lenp contains the length of that name - * (>=0) - * NULL, on error - * if lenp is non-NULL *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); - -/** - * fdt_first_property_offset - find the offset of a node's first property - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * - * fdt_first_property_offset() finds the first property of the node at - * the given structure block offset. - * - * returns: - * structure block offset of the property (>=0), on success - * -FDT_ERR_NOTFOUND, if the requested node has no properties - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_first_property_offset(const void *fdt, int nodeoffset); - -/** - * fdt_next_property_offset - step through a node's properties - * @fdt: pointer to the device tree blob - * @offset: structure block offset of a property - * - * fdt_next_property_offset() finds the property immediately after the - * one at the given structure block offset. This will be a property - * of the same node as the given property. - * - * returns: - * structure block offset of the next property (>=0), on success - * -FDT_ERR_NOTFOUND, if the given property is the last in its node - * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_next_property_offset(const void *fdt, int offset); - -/** - * fdt_for_each_property_offset - iterate over all properties of a node - * - * @property_offset: property offset (int, lvalue) - * @fdt: FDT blob (const void *) - * @node: node offset (int) - * - * This is actually a wrapper around a for loop and would be used like so: - * - * fdt_for_each_property_offset(property, fdt, node) { - * Use property - * ... - * } - * - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { - * Error handling - * } - * - * Note that this is implemented as a macro and property is used as - * iterator in the loop. The node variable can be constant or even a - * literal. - */ -#define fdt_for_each_property_offset(property, fdt, node) \ - for (property = fdt_first_property_offset(fdt, node); \ - property >= 0; \ - property = fdt_next_property_offset(fdt, property)) - -/** - * fdt_get_property_by_offset - retrieve the property at a given offset - * @fdt: pointer to the device tree blob - * @offset: offset of the property to retrieve - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property_by_offset() retrieves a pointer to the - * fdt_property structure within the device tree blob at the given - * offset. If lenp is non-NULL, the length of the property value is - * also returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property_by_offset(const void *fdt, - int offset, - int *lenp); - -/** - * fdt_get_property_namelen - find a property based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_get_property(), but only examine the first namelen - * characters of name for matching the property name. - */ -#ifndef SWIG /* Not available in Python */ -const struct fdt_property *fdt_get_property_namelen(const void *fdt, - int nodeoffset, - const char *name, - int namelen, int *lenp); -#endif - -/** - * fdt_get_property - find a given property in a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_get_property() retrieves a pointer to the fdt_property - * structure within the device tree blob corresponding to the property - * named 'name' of the node at offset nodeoffset. If lenp is - * non-NULL, the length of the property value is also returned, in the - * integer pointed to by lenp. - * - * returns: - * pointer to the structure representing the property - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, - const char *name, - int *lenp) -{ - return (struct fdt_property *)(uintptr_t) - fdt_get_property(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_getprop_by_offset - retrieve the value of a property at a given offset - * @fdt: pointer to the device tree blob - * @ffset: offset of the property to read - * @namep: pointer to a string variable (will be overwritten) or NULL - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop_by_offset() retrieves a pointer to the value of the - * property at structure block offset 'offset' (this will be a pointer - * to within the device blob itself, not a copy of the value). If - * lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. If namep is non-NULL, - * the property's namne will also be returned in the char * pointed to - * by namep (this will be a pointer to within the device tree's string - * block, not a new copy of the name). - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * if namep is non-NULL *namep contiains a pointer to the property - * name. - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#ifndef SWIG /* This function is not useful in Python */ -const void *fdt_getprop_by_offset(const void *fdt, int offset, - const char **namep, int *lenp); -#endif - -/** - * fdt_getprop_namelen - get property value based on substring - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @namelen: number of characters of name to consider - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * Identical to fdt_getprop(), but only examine the first namelen - * characters of name for matching the property name. - */ -#ifndef SWIG /* Not available in Python */ -const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, - const char *name, int namelen, int *lenp); -static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, - const char *name, int namelen, - int *lenp) -{ - return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, - namelen, lenp); -} -#endif - -/** - * fdt_getprop - retrieve the value of a given property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to find - * @name: name of the property to find - * @lenp: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_getprop() retrieves a pointer to the value of the property - * named 'name' of the node at offset nodeoffset (this will be a - * pointer to within the device blob itself, not a copy of the value). - * If lenp is non-NULL, the length of the property value is also - * returned, in the integer pointed to by lenp. - * - * returns: - * pointer to the property's value - * if lenp is non-NULL, *lenp contains the length of the property - * value (>=0) - * NULL, on error - * if lenp is non-NULL, *lenp contains an error code (<0): - * -FDT_ERR_NOTFOUND, node does not have named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE - * tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -const void *fdt_getprop(const void *fdt, int nodeoffset, - const char *name, int *lenp); -static inline void *fdt_getprop_w(void *fdt, int nodeoffset, - const char *name, int *lenp) -{ - return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); -} - -/** - * fdt_get_phandle - retrieve the phandle of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of the node - * - * fdt_get_phandle() retrieves the phandle of the device tree node at - * structure block offset nodeoffset. - * - * returns: - * the phandle of the node at nodeoffset, on success (!= 0, != -1) - * 0, if the node has no phandle, or another error occurs - */ -uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); - -/** - * fdt_get_alias_namelen - get alias based on substring - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * @namelen: number of characters of name to consider - * - * Identical to fdt_get_alias(), but only examine the first namelen - * characters of name for matching the alias name. - */ -#ifndef SWIG /* Not available in Python */ -const char *fdt_get_alias_namelen(const void *fdt, - const char *name, int namelen); -#endif - -/** - * fdt_get_alias - retrieve the path referenced by a given alias - * @fdt: pointer to the device tree blob - * @name: name of the alias th look up - * - * fdt_get_alias() retrieves the value of a given alias. That is, the - * value of the property named 'name' in the node /aliases. - * - * returns: - * a pointer to the expansion of the alias named 'name', if it exists - * NULL, if the given alias or the /aliases node does not exist - */ -const char *fdt_get_alias(const void *fdt, const char *name); - -/** - * fdt_get_path - determine the full path of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose path to find - * @buf: character buffer to contain the returned path (will be overwritten) - * @buflen: size of the character buffer at buf - * - * fdt_get_path() computes the full path of the node at offset - * nodeoffset, and records that path in the buffer at buf. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * 0, on success - * buf contains the absolute path of the node at - * nodeoffset, as a NUL-terminated string. - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) - * characters and will not fit in the given buffer. - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); - -/** - * fdt_supernode_atdepth_offset - find a specific ancestor of a node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * @supernodedepth: depth of the ancestor to find - * @nodedepth: pointer to an integer variable (will be overwritten) or NULL - * - * fdt_supernode_atdepth_offset() finds an ancestor of the given node - * at a specific depth from the root (where the root itself has depth - * 0, its immediate subnodes depth 1 and so forth). So - * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); - * will always return 0, the offset of the root node. If the node at - * nodeoffset has depth D, then: - * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); - * will return nodeoffset itself. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * structure block offset of the node at node offset's ancestor - * of depth supernodedepth (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of - * nodeoffset - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, - int supernodedepth, int *nodedepth); - -/** - * fdt_node_depth - find the depth of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_node_depth() finds the depth of a given node. The root node - * has depth 0, its immediate subnodes depth 1 and so forth. - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset. - * - * returns: - * depth of the node at nodeoffset (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_depth(const void *fdt, int nodeoffset); - -/** - * fdt_parent_offset - find the parent of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose parent to find - * - * fdt_parent_offset() locates the parent node of a given node (that - * is, it finds the offset of the node which contains the node at - * nodeoffset as a subnode). - * - * NOTE: This function is expensive, as it must scan the device tree - * structure from the start to nodeoffset, *twice*. - * - * returns: - * structure block offset of the parent of the node at nodeoffset - * (>=0), on success - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_parent_offset(const void *fdt, int nodeoffset); - -/** - * fdt_node_offset_by_prop_value - find nodes with a given property value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @propname: property name to check - * @propval: property value to search for - * @proplen: length of the value in propval - * - * fdt_node_offset_by_prop_value() returns the offset of the first - * node after startoffset, which has a property named propname whose - * value is of length proplen and has value equal to propval; or if - * startoffset is -1, the very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, - * propval, proplen); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, - * propval, proplen); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, - const char *propname, - const void *propval, int proplen); - -/** - * fdt_node_offset_by_phandle - find the node with a given phandle - * @fdt: pointer to the device tree blob - * @phandle: phandle value - * - * fdt_node_offset_by_phandle() returns the offset of the node - * which has the given phandle value. If there is more than one node - * in the tree with the given phandle (an invalid tree), results are - * undefined. - * - * returns: - * structure block offset of the located node (>= 0), on success - * -FDT_ERR_NOTFOUND, no node with that phandle exists - * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); - -/** - * fdt_node_check_compatible: check a node's compatible property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @compatible: string to match against - * - * - * fdt_node_check_compatible() returns 0 if the given node contains a - * 'compatible' property with the given string as one of its elements, - * it returns non-zero otherwise, or on error. - * - * returns: - * 0, if the node has a 'compatible' property listing the given string - * 1, if the node has a 'compatible' property, but it does not list - * the given string - * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property - * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_check_compatible(const void *fdt, int nodeoffset, - const char *compatible); - -/** - * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value - * @fdt: pointer to the device tree blob - * @startoffset: only find nodes after this offset - * @compatible: 'compatible' string to match against - * - * fdt_node_offset_by_compatible() returns the offset of the first - * node after startoffset, which has a 'compatible' property which - * lists the given compatible string; or if startoffset is -1, the - * very first such node in the tree. - * - * To iterate through all nodes matching the criterion, the following - * idiom can be used: - * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); - * while (offset != -FDT_ERR_NOTFOUND) { - * // other code here - * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); - * } - * - * Note the -1 in the first call to the function, if 0 is used here - * instead, the function will never locate the root node, even if it - * matches the criterion. - * - * returns: - * structure block offset of the located node (>= 0, >startoffset), - * on success - * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the - * tree after startoffset - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, standard meanings - */ -int fdt_node_offset_by_compatible(const void *fdt, int startoffset, - const char *compatible); - -/** - * fdt_stringlist_contains - check a string list property for a string - * @strlist: Property containing a list of strings to check - * @listlen: Length of property - * @str: String to search for - * - * This is a utility function provided for convenience. The list contains - * one or more strings, each terminated by \0, as is found in a device tree - * "compatible" property. - * - * @return: 1 if the string is found in the list, 0 not found, or invalid list - */ -int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); - -/** - * fdt_stringlist_count - count the number of strings in a string list - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @property: name of the property containing the string list - * @return: - * the number of strings in the given property - * -FDT_ERR_BADVALUE if the property value is not NUL-terminated - * -FDT_ERR_NOTFOUND if the property does not exist - */ -int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); - -/** - * fdt_stringlist_search - find a string in a string list and return its index - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @property: name of the property containing the string list - * @string: string to look up in the string list - * - * Note that it is possible for this function to succeed on property values - * that are not NUL-terminated. That's because the function will stop after - * finding the first occurrence of @string. This can for example happen with - * small-valued cell properties, such as #address-cells, when searching for - * the empty string. - * - * @return: - * the index of the string in the list of strings - * -FDT_ERR_BADVALUE if the property value is not NUL-terminated - * -FDT_ERR_NOTFOUND if the property does not exist or does not contain - * the given string - */ -int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, - const char *string); - -/** - * fdt_stringlist_get() - obtain the string at a given index in a string list - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of a tree node - * @property: name of the property containing the string list - * @index: index of the string to return - * @lenp: return location for the string length or an error code on failure - * - * Note that this will successfully extract strings from properties with - * non-NUL-terminated values. For example on small-valued cell properties - * this function will return the empty string. - * - * If non-NULL, the length of the string (on success) or a negative error-code - * (on failure) will be stored in the integer pointer to by lenp. - * - * @return: - * A pointer to the string at the given index in the string list or NULL on - * failure. On success the length of the string will be stored in the memory - * location pointed to by the lenp parameter, if non-NULL. On failure one of - * the following negative error codes will be returned in the lenp parameter - * (if non-NULL): - * -FDT_ERR_BADVALUE if the property value is not NUL-terminated - * -FDT_ERR_NOTFOUND if the property does not exist - */ -const char *fdt_stringlist_get(const void *fdt, int nodeoffset, - const char *property, int index, - int *lenp); - -/**********************************************************************/ -/* Read-only functions (addressing related) */ -/**********************************************************************/ - -/** - * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells - * - * This is the maximum value for #address-cells, #size-cells and - * similar properties that will be processed by libfdt. IEE1275 - * requires that OF implementations handle values up to 4. - * Implementations may support larger values, but in practice higher - * values aren't used. - */ -#define FDT_MAX_NCELLS 4 - -/** - * fdt_address_cells - retrieve address size for a bus represented in the tree - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to find the address size for - * - * When the node has a valid #address-cells property, returns its value. - * - * returns: - * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property - * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid - * #address-cells property - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_address_cells(const void *fdt, int nodeoffset); - -/** - * fdt_size_cells - retrieve address range size for a bus represented in the - * tree - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to find the address range size for - * - * When the node has a valid #size-cells property, returns its value. - * - * returns: - * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property - * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid - * #size-cells property - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_size_cells(const void *fdt, int nodeoffset); - - -/**********************************************************************/ -/* Write-in-place functions */ -/**********************************************************************/ - -/** - * fdt_setprop_inplace_namelen_partial - change a property's value, - * but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @namelen: number of characters of name to consider - * @idx: index of the property to change in the array - * @val: pointer to data to replace the property value with - * @len: length of the property value - * - * Identical to fdt_setprop_inplace(), but modifies the given property - * starting from the given index, and using only the first characters - * of the name. It is useful when you want to manipulate only one value of - * an array and you have a string that doesn't end with \0. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, - const char *name, int namelen, - uint32_t idx, const void *val, - int len); -#endif - -/** - * fdt_setprop_inplace - change a property's value, but not its size - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to replace the property value with - * @len: length of the property value - * - * fdt_setprop_inplace() replaces the value of a given property with - * the data in val, of length len. This function cannot change the - * size of a property, and so will only work if len is equal to the - * current length of the property. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if len is not equal to the property's current length - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#ifndef SWIG /* Not available in Python */ -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, - const void *val, int len); -#endif - -/** - * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value to replace the property with - * - * fdt_setprop_inplace_u32() replaces the value of a given property - * with the 32-bit integer value in val, converting val to big-endian - * if necessary. This function cannot change the size of a property, - * and so will only work if the property already exists and has length - * 4. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value to replace the property with - * - * fdt_setprop_inplace_u64() replaces the value of a given property - * with the 64-bit integer value in val, converting val to big-endian - * if necessary. This function cannot change the size of a property, - * and so will only work if the property already exists and has length - * 8. - * - * This function will alter only the bytes in the blob which contain - * the given property value, and will not alter or move any other part - * of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, - const char *name, uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_inplace_cell - change the value of a single-cell property - * - * This is an alternative name for fdt_setprop_inplace_u32() - */ -static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_nop_property - replace a property with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_nop_property() will replace a given property's representation - * in the blob with FDT_NOP tags, effectively removing it from the - * tree. - * - * This function will alter only the bytes in the blob which contain - * the property, and will not alter or move any other part of the - * tree. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_property(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_nop_node - replace a node (subtree) with nop tags - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_nop_node() will replace a given node's representation in the - * blob, including all its subnodes, if any, with FDT_NOP tags, - * effectively removing it from the tree. - * - * This function will alter only the bytes in the blob which contain - * the node and its properties and subnodes, and will not alter or - * move any other part of the tree. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_nop_node(void *fdt, int nodeoffset); - -/**********************************************************************/ -/* Sequential write functions */ -/**********************************************************************/ - -int fdt_create(void *buf, int bufsize); -int fdt_resize(void *fdt, void *buf, int bufsize); -int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); -int fdt_finish_reservemap(void *fdt); -int fdt_begin_node(void *fdt, const char *name); -int fdt_property(void *fdt, const char *name, const void *val, int len); -static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_property(fdt, name, &tmp, sizeof(tmp)); -} -static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_property(fdt, name, &tmp, sizeof(tmp)); -} -static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) -{ - return fdt_property_u32(fdt, name, val); -} - -/** - * fdt_property_placeholder - add a new property and return a ptr to its value - * - * @fdt: pointer to the device tree blob - * @name: name of property to add - * @len: length of property value in bytes - * @valp: returns a pointer to where where the value should be placed - * - * returns: - * 0, on success - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_NOSPACE, standard meanings - */ -int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); - -#define fdt_property_string(fdt, name, str) \ - fdt_property(fdt, name, str, strlen(str)+1) -int fdt_end_node(void *fdt); -int fdt_finish(void *fdt); - -/**********************************************************************/ -/* Read-write functions */ -/**********************************************************************/ - -int fdt_create_empty_tree(void *buf, int bufsize); -int fdt_open_into(const void *fdt, void *buf, int bufsize); -int fdt_pack(void *fdt); - -/** - * fdt_add_mem_rsv - add one memory reserve map entry - * @fdt: pointer to the device tree blob - * @address, @size: 64-bit values (native endian) - * - * Adds a reserve map entry to the given blob reserving a region at - * address address of length size. - * - * This function will insert data into the reserve map and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new reservation entry - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); - -/** - * fdt_del_mem_rsv - remove a memory reserve map entry - * @fdt: pointer to the device tree blob - * @n: entry to remove - * - * fdt_del_mem_rsv() removes the n-th memory reserve map entry from - * the blob. - * - * This function will delete data from the reservation table and will - * therefore change the indexes of some entries in the table. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there - * are less than n+1 reserve map entries) - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_mem_rsv(void *fdt, int n); - -/** - * fdt_set_name - change the name of a given node - * @fdt: pointer to the device tree blob - * @nodeoffset: structure block offset of a node - * @name: name to give the node - * - * fdt_set_name() replaces the name (including unit address, if any) - * of the given node with the given string. NOTE: this function can't - * efficiently check if the new name is unique amongst the given - * node's siblings; results are undefined if this function is invoked - * with a name equal to one of the given node's siblings. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob - * to contain the new name - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings - */ -int fdt_set_name(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_setprop - create or change a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: pointer to data to set the property value to - * @len: length of the property value - * - * fdt_setprop() sets the value of the named property in the given - * node to the given value and length, creating the property if it - * does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_setprop _placeholder - allocate space for a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @len: length of the property value - * @prop_data: return pointer to property data - * - * fdt_setprop_placeholer() allocates the named property in the given node. - * If the property exists it is resized. In either case a pointer to the - * property data is returned. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, - int len, void **prop_data); - -/** - * fdt_setprop_u32 - set a property to a 32-bit integer - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value for the property (native endian) - * - * fdt_setprop_u32() sets the value of the named property in the given - * node to the given 32-bit integer value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_u64 - set a property to a 64-bit integer - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value for the property (native endian) - * - * fdt_setprop_u64() sets the value of the named property in the given - * node to the given 64-bit integer value (converting to big-endian if - * necessary), or creates a new property with that value if it does - * not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, - uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_setprop_cell - set a property to a single cell value - * - * This is an alternative name for fdt_setprop_u32() - */ -static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, - uint32_t val) -{ - return fdt_setprop_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_setprop_string - set a property to a string value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value for the property - * - * fdt_setprop_string() sets the value of the named property in the - * given node to the given string value (using the length of the - * string to determine the new length of the property), or creates a - * new property with that value if it does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_setprop_string(fdt, nodeoffset, name, str) \ - fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - - -/** - * fdt_setprop_empty - set a property to an empty value - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * - * fdt_setprop_empty() sets the value of the named property in the - * given node to an empty (zero length) value, or creates a new empty - * property if it does not already exist. - * - * This function may insert or delete data from the blob, and will - * therefore change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_setprop_empty(fdt, nodeoffset, name) \ - fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) - -/** - * fdt_appendprop - append to or create a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to append to - * @val: pointer to data to append to the property value - * @len: length of the data to append to the property value - * - * fdt_appendprop() appends the value to the named property in the - * given node, creating the property if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_appendprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len); - -/** - * fdt_appendprop_u32 - append a 32-bit integer value to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 32-bit integer value to append to the property (native endian) - * - * fdt_appendprop_u32() appends the given 32-bit integer value - * (converting to big-endian if necessary) to the value of the named - * property in the given node, or creates a new property with that - * value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - fdt32_t tmp = cpu_to_fdt32(val); - return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_appendprop_u64 - append a 64-bit integer value to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @val: 64-bit integer value to append to the property (native endian) - * - * fdt_appendprop_u64() appends the given 64-bit integer value - * (converting to big-endian if necessary) to the value of the named - * property in the given node, or creates a new property with that - * value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, - const char *name, uint64_t val) -{ - fdt64_t tmp = cpu_to_fdt64(val); - return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); -} - -/** - * fdt_appendprop_cell - append a single cell value to a property - * - * This is an alternative name for fdt_appendprop_u32() - */ -static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, - const char *name, uint32_t val) -{ - return fdt_appendprop_u32(fdt, nodeoffset, name, val); -} - -/** - * fdt_appendprop_string - append a string to a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to change - * @name: name of the property to change - * @str: string value to append to the property - * - * fdt_appendprop_string() appends the given string to the value of - * the named property in the given node, or creates a new property - * with that value if it does not already exist. - * - * This function may insert data into the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to - * contain the new property value - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_TRUNCATED, standard meanings - */ -#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ - fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) - -/** - * fdt_delprop - delete a property - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node whose property to nop - * @name: name of the property to nop - * - * fdt_del_property() will delete the given property. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_NOTFOUND, node does not have the named property - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_delprop(void *fdt, int nodeoffset, const char *name); - -/** - * fdt_add_subnode_namelen - creates a new node based on substring - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * @namelen: number of characters of name to consider - * - * Identical to fdt_add_subnode(), but use only the first namelen - * characters of name as the name of the new node. This is useful for - * creating subnodes based on a portion of a larger string, such as a - * full path. - */ -#ifndef SWIG /* Not available in Python */ -int fdt_add_subnode_namelen(void *fdt, int parentoffset, - const char *name, int namelen); -#endif - -/** - * fdt_add_subnode - creates a new node - * @fdt: pointer to the device tree blob - * @parentoffset: structure block offset of a node - * @name: name of the subnode to locate - * - * fdt_add_subnode() creates a new node as a subnode of the node at - * structure block offset parentoffset, with the given name (which - * should include the unit address, if any). - * - * This function will insert data into the blob, and will therefore - * change the offsets of some existing nodes. - - * returns: - * structure block offset of the created nodeequested subnode (>=0), on - * success - * -FDT_ERR_NOTFOUND, if the requested subnode does not exist - * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE - * tag - * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of - * the given name - * -FDT_ERR_NOSPACE, if there is insufficient free space in the - * blob to contain the new node - * -FDT_ERR_NOSPACE - * -FDT_ERR_BADLAYOUT - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings. - */ -int fdt_add_subnode(void *fdt, int parentoffset, const char *name); - -/** - * fdt_del_node - delete a node (subtree) - * @fdt: pointer to the device tree blob - * @nodeoffset: offset of the node to nop - * - * fdt_del_node() will remove the given node, including all its - * subnodes if any, from the blob. - * - * This function will delete data from the blob, and will therefore - * change the offsets of some existing nodes. - * - * returns: - * 0, on success - * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_del_node(void *fdt, int nodeoffset); - -/** - * fdt_overlay_apply - Applies a DT overlay on a base DT - * @fdt: pointer to the base device tree blob - * @fdto: pointer to the device tree overlay blob - * - * fdt_overlay_apply() will apply the given device tree overlay on the - * given base device tree. - * - * Expect the base device tree to be modified, even if the function - * returns an error. - * - * returns: - * 0, on success - * -FDT_ERR_NOSPACE, there's not enough space in the base device tree - * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or - * properties in the base DT - * -FDT_ERR_BADPHANDLE, - * -FDT_ERR_BADOVERLAY, - * -FDT_ERR_NOPHANDLES, - * -FDT_ERR_INTERNAL, - * -FDT_ERR_BADLAYOUT, - * -FDT_ERR_BADMAGIC, - * -FDT_ERR_BADOFFSET, - * -FDT_ERR_BADPATH, - * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTRUCTURE, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_TRUNCATED, standard meanings - */ -int fdt_overlay_apply(void *fdt, void *fdto); - -/**********************************************************************/ -/* Debugging / informational functions */ -/**********************************************************************/ - -#ifndef SWIG /* Not available in Python */ -const char *fdt_strerror(int errval); - -/** - * fdt_remove_unused_strings() - Remove any unused strings from an FDT - * - * This creates a new device tree in @new with unused strings removed. The - * called can then use fdt_pack() to minimise the space consumed. - * - * @old: Old device tree blog - * @new: Place to put new device tree blob, which must be as large as - * @old - * @return - * 0, on success - * -FDT_ERR_BADOFFSET, corrupt device tree - * -FDT_ERR_NOSPACE, out of space, which should not happen unless there - * is something very wrong with the device tree input - */ -int fdt_remove_unused_strings(const void *old, void *new); - -struct fdt_region { - int offset; - int size; -}; - -/* - * Flags for fdt_find_regions() - * - * Add a region for the string table (always the last region) - */ -#define FDT_REG_ADD_STRING_TAB (1 << 0) - -/* - * Add all supernodes of a matching node/property, useful for creating a - * valid subset tree - */ -#define FDT_REG_SUPERNODES (1 << 1) - -/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */ -#define FDT_REG_DIRECT_SUBNODES (1 << 2) - -/* Add all subnodes of a matching node */ -#define FDT_REG_ALL_SUBNODES (1 << 3) - -/* Add a region for the mem_rsvmap table (always the first region) */ -#define FDT_REG_ADD_MEM_RSVMAP (1 << 4) - -/* Indicates what an fdt part is (node, property, value) */ -#define FDT_IS_NODE (1 << 0) -#define FDT_IS_PROP (1 << 1) -#define FDT_IS_VALUE (1 << 2) /* not supported */ -#define FDT_IS_COMPAT (1 << 3) /* used internally */ -#define FDT_NODE_HAS_PROP (1 << 4) /* node contains prop */ - -#define FDT_ANY_GLOBAL (FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \ - FDT_IS_COMPAT) -#define FDT_IS_ANY 0x1f /* all the above */ - -/* We set a reasonable limit on the number of nested nodes */ -#define FDT_MAX_DEPTH 32 - -/* Decribes what we want to include from the current tag */ -enum want_t { - WANT_NOTHING, - WANT_NODES_ONLY, /* No properties */ - WANT_NODES_AND_PROPS, /* Everything for one level */ - WANT_ALL_NODES_AND_PROPS /* Everything for all levels */ -}; - -/* Keeps track of the state at parent nodes */ -struct fdt_subnode_stack { - int offset; /* Offset of node */ - enum want_t want; /* The 'want' value here */ - int included; /* 1 if we included this node, 0 if not */ -}; - -struct fdt_region_ptrs { - int depth; /* Current tree depth */ - int done; /* What we have completed scanning */ - enum want_t want; /* What we are currently including */ - char *end; /* Pointer to end of full node path */ - int nextoffset; /* Next node offset to check */ -}; - -/* The state of our finding algortihm */ -struct fdt_region_state { - struct fdt_subnode_stack stack[FDT_MAX_DEPTH]; /* node stack */ - struct fdt_region *region; /* Contains list of regions found */ - int count; /* Numnber of regions found */ - const void *fdt; /* FDT blob */ - int max_regions; /* Maximum regions to find */ - int can_merge; /* 1 if we can merge with previous region */ - int start; /* Start position of current region */ - struct fdt_region_ptrs ptrs; /* Pointers for what we are up to */ -}; - -/** - * fdt_find_regions() - find regions in device tree - * - * Given a list of nodes to include and properties to exclude, find - * the regions of the device tree which describe those included parts. - * - * The intent is to get a list of regions which will be invariant provided - * those parts are invariant. For example, if you request a list of regions - * for all nodes but exclude the property "data", then you will get the - * same region contents regardless of any change to "data" properties. - * - * This function can be used to produce a byte-stream to send to a hashing - * function to verify that critical parts of the FDT have not changed. - * - * Nodes which are given in 'inc' are included in the region list, as - * are the names of the immediate subnodes nodes (but not the properties - * or subnodes of those subnodes). - * - * For eaxample "/" means to include the root node, all root properties - * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter - * ensures that we capture the names of the subnodes. In a hashing situation - * it prevents the root node from changing at all Any change to non-excluded - * properties, names of subnodes or number of subnodes would be detected. - * - * When used with FITs this provides the ability to hash and sign parts of - * the FIT based on different configurations in the FIT. Then it is - * impossible to change anything about that configuration (include images - * attached to the configuration), but it may be possible to add new - * configurations, new images or new signatures within the existing - * framework. - * - * Adding new properties to a device tree may result in the string table - * being extended (if the new property names are different from those - * already added). This function can optionally include a region for - * the string table so that this can be part of the hash too. - * - * The device tree header is not included in the list. - * - * @fdt: Device tree to check - * @inc: List of node paths to included - * @inc_count: Number of node paths in list - * @exc_prop: List of properties names to exclude - * @exc_prop_count: Number of properties in exclude list - * @region: Returns list of regions - * @max_region: Maximum length of region list - * @path: Pointer to a temporary string for the function to use for - * building path names - * @path_len: Length of path, must be large enough to hold the longest - * path in the tree - * @add_string_tab: 1 to add a region for the string table - * @return number of regions in list. If this is >max_regions then the - * region array was exhausted. You should increase max_regions and try - * the call again. - */ -int fdt_find_regions(const void *fdt, char * const inc[], int inc_count, - char * const exc_prop[], int exc_prop_count, - struct fdt_region region[], int max_regions, - char *path, int path_len, int add_string_tab); - -/** - * fdt_first_region() - find regions in device tree - * - * Given a nodes and properties to include and properties to exclude, find - * the regions of the device tree which describe those included parts. - * - * The use for this function is twofold. Firstly it provides a convenient - * way of performing a structure-aware grep of the tree. For example it is - * possible to grep for a node and get all the properties associated with - * that node. Trees can be subsetted easily, by specifying the nodes that - * are required, and then writing out the regions returned by this function. - * This is useful for small resource-constrained systems, such as boot - * loaders, which want to use an FDT but do not need to know about all of - * it. - * - * Secondly it makes it easy to hash parts of the tree and detect changes. - * The intent is to get a list of regions which will be invariant provided - * those parts are invariant. For example, if you request a list of regions - * for all nodes but exclude the property "data", then you will get the - * same region contents regardless of any change to "data" properties. - * - * This function can be used to produce a byte-stream to send to a hashing - * function to verify that critical parts of the FDT have not changed. - * Note that semantically null changes in order could still cause false - * hash misses. Such reordering might happen if the tree is regenerated - * from source, and nodes are reordered (the bytes-stream will be emitted - * in a different order and mnay hash functions will detect this). However - * if an existing tree is modified using libfdt functions, such as - * fdt_add_subnode() and fdt_setprop(), then this problem is avoided. - * - * The nodes/properties to include/exclude are defined by a function - * provided by the caller. This function is called for each node and - * property, and must return: - * - * 0 - to exclude this part - * 1 - to include this part - * -1 - for FDT_IS_PROP only: no information is available, so include - * if its containing node is included - * - * The last case is only used to deal with properties. Often a property is - * included if its containing node is included - this is the case where - * -1 is returned.. However if the property is specifically required to be - * included/excluded, then 0 or 1 can be returned. Note that including a - * property when the FDT_REG_SUPERNODES flag is given will force its - * containing node to be included since it is not valid to have a property - * that is not in a node. - * - * Using the information provided, the inclusion of a node can be controlled - * either by a node name or its compatible string, or any other property - * that the function can determine. - * - * As an example, including node "/" means to include the root node and all - * root properties. A flag provides a way of also including supernodes (of - * which there is none for the root node), and another flag includes - * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and - * FDT_END_NODE of all subnodes of /. - * - * The subnode feature helps in a hashing situation since it prevents the - * root node from changing at all. Any change to non-excluded properties, - * names of subnodes or number of subnodes would be detected. - * - * When used with FITs this provides the ability to hash and sign parts of - * the FIT based on different configurations in the FIT. Then it is - * impossible to change anything about that configuration (include images - * attached to the configuration), but it may be possible to add new - * configurations, new images or new signatures within the existing - * framework. - * - * Adding new properties to a device tree may result in the string table - * being extended (if the new property names are different from those - * already added). This function can optionally include a region for - * the string table so that this can be part of the hash too. This is always - * the last region. - * - * The FDT also has a mem_rsvmap table which can also be included, and is - * always the first region if so. - * - * The device tree header is not included in the region list. Since the - * contents of the FDT are changing (shrinking, often), the caller will need - * to regenerate the header anyway. - * - * @fdt: Device tree to check - * @h_include: Function to call to determine whether to include a part or - * not: - * - * @priv: Private pointer as passed to fdt_find_regions() - * @fdt: Pointer to FDT blob - * @offset: Offset of this node / property - * @type: Type of this part, FDT_IS_... - * @data: Pointer to data (node name, property name, compatible - * string, value (not yet supported) - * @size: Size of data, or 0 if none - * @return 0 to exclude, 1 to include, -1 if no information is - * available - * @priv: Private pointer passed to h_include - * @region: Returns list of regions, sorted by offset - * @max_regions: Maximum length of region list - * @path: Pointer to a temporary string for the function to use for - * building path names - * @path_len: Length of path, must be large enough to hold the longest - * path in the tree - * @flags: Various flags that control the region algortihm, see - * FDT_REG_... - * @return number of regions in list. If this is >max_regions then the - * region array was exhausted. You should increase max_regions and try - * the call again. Only the first max_regions elements are available in the - * array. - * - * On error a -ve value is return, which can be: - * - * -FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags - * -FDT_ERR_BADLAYOUT - * -FDT_ERR_NOSPACE (path area is too small) - */ -int fdt_first_region(const void *fdt, - int (*h_include)(void *priv, const void *fdt, int offset, - int type, const char *data, int size), - void *priv, struct fdt_region *region, - char *path, int path_len, int flags, - struct fdt_region_state *info); - -/** fdt_next_region() - find next region - * - * See fdt_first_region() for full description. This function finds the - * next region according to the provided parameters, which must be the same - * as passed to fdt_first_region(). - * - * This function can additionally return -FDT_ERR_NOTFOUND when there are no - * more regions - */ -int fdt_next_region(const void *fdt, - int (*h_include)(void *priv, const void *fdt, int offset, - int type, const char *data, int size), - void *priv, struct fdt_region *region, - char *path, int path_len, int flags, - struct fdt_region_state *info); - -/** - * fdt_add_alias_regions() - find aliases that point to existing regions - * - * Once a device tree grep is complete some of the nodes will be present - * and some will have been dropped. This function checks all the alias nodes - * to figure out which points point to nodes which are still present. These - * aliases need to be kept, along with the nodes they reference. - * - * Given a list of regions function finds the aliases that still apply and - * adds more regions to the list for these. This function is called after - * fdt_next_region() has finished returning regions and requires the same - * state. - * - * @fdt: Device tree file to reference - * @region: List of regions that will be kept - * @count: Number of regions - * @max_regions: Number of entries that can fit in @region - * @info: Region state as returned from fdt_next_region() - * @return new number of regions in @region (i.e. count + the number added) - * or -FDT_ERR_NOSPACE if there was not enough space. - */ -int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count, - int max_regions, struct fdt_region_state *info); -#endif /* SWIG */ - -#endif /* _LIBFDT_H */ diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index bc7a148cfe3..efcb251e442 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -121,7 +121,6 @@ CONFIG_BCH_CONST_M CONFIG_BCH_CONST_PARAMS CONFIG_BCH_CONST_T CONFIG_BCM2835_GPIO -CONFIG_BCM283X_MU_SERIAL CONFIG_BIOSEMU CONFIG_BITBANGMII_MULTI CONFIG_BL1_OFFSET @@ -1276,7 +1275,6 @@ CONFIG_MACB2_PHY CONFIG_MACB3_PHY CONFIG_MACB_SEARCH_PHY CONFIG_MACH_OMAPL138_LCDK -CONFIG_MACH_SPECIFIC CONFIG_MACH_TYPE CONFIG_MACH_TYPE_COMPAT_REV CONFIG_MACRESET_TIMEOUT @@ -1618,11 +1616,8 @@ CONFIG_PIXIS_BRDCFG1_SSI_TDM_MASK CONFIG_PIXIS_BRDCFG1_SSI_TDM_SSI CONFIG_PIXIS_BRDCFG1_TDM CONFIG_PIXIS_SGMII_CMD -CONFIG_PL010_SERIAL CONFIG_PL011_CLOCK -CONFIG_PL011_SERIAL CONFIG_PL011_SERIAL_RLCR -CONFIG_PL01X_SERIAL CONFIG_PL01x_PORTS CONFIG_PLATFORM_ENV_SETTINGS CONFIG_PLATINUM_BOARD diff --git a/scripts/dtc/pylibfdt/setup.py b/scripts/dtc/pylibfdt/setup.py index daf1089425d..4f7cf042bfe 100755 --- a/scripts/dtc/pylibfdt/setup.py +++ b/scripts/dtc/pylibfdt/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 """ setup.py file for SWIG libfdt diff --git a/scripts/mailmapper b/scripts/mailmapper index 922ada6f5fb..78b23d152d9 100755 --- a/scripts/mailmapper +++ b/scripts/mailmapper @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # # Copyright (C) 2014, Masahiro Yamada <yamada.m@jp.panasonic.com> # diff --git a/test/py/test.py b/test/py/test.py index 74e560a4d33..4695079ef71 100755 --- a/test/py/test.py +++ b/test/py/test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # Copyright (c) 2015 Stephen Warren # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. diff --git a/tools/Makefile b/tools/Makefile index b7d7d418ee0..d3387fad696 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -63,11 +63,11 @@ FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o # The following files are synced with upstream DTC. # Use synced versions from scripts/dtc/libfdt/. -LIBFDT_SRCS_SYNCED := fdt.c fdt_wip.c fdt_sw.c fdt_strerror.c fdt_empty_tree.c \ - fdt_addresses.c fdt_overlay.c +LIBFDT_SRCS_SYNCED := fdt.c fdt_wip.c fdt_sw.c fdt_rw.c \ + fdt_strerror.c fdt_empty_tree.c fdt_addresses.c fdt_overlay.c # The following files are locally modified for U-Boot (unfotunately). # Use U-Boot own versions from lib/libfdt/. -LIBFDT_SRCS_UNSYNCED := fdt_ro.c fdt_rw.c fdt_region.c +LIBFDT_SRCS_UNSYNCED := fdt_ro.c fdt_region.c LIBFDT_OBJS := $(addprefix libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_SYNCED))) \ $(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_UNSYNCED))) @@ -242,7 +242,7 @@ endif # !LOGO_BMP # Define __KERNEL_STRICT_NAMES to prevent typedef overlaps # Define _GNU_SOURCE to obtain the getline prototype from stdio.h # -HOST_EXTRACFLAGS += -include $(srctree)/include/libfdt_env.h \ +HOST_EXTRACFLAGS += -include $(srctree)/include/compiler.h \ $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \ -I$(srctree)/lib/libfdt \ -I$(srctree)/tools \ diff --git a/tools/buildman/buildman.py b/tools/buildman/buildman.py index 11a4f162c5f..473117ccff7 100755 --- a/tools/buildman/buildman.py +++ b/tools/buildman/buildman.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # # Copyright (c) 2012 The Chromium OS Authors. # diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/dtoc.py index ce7bc054e5e..6eacfc90a0a 100755 --- a/tools/dtoc/dtoc.py +++ b/tools/dtoc/dtoc.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python2 # # Copyright (C) 2016 Google, Inc # Written by Simon Glass <sjg@chromium.org> diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 18c2324d2fc..ca5507d4d73 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -505,8 +505,6 @@ int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts) int fw_env_flush(struct env_opts *opts) { - int ret; - if (!opts) opts = &default_opts; diff --git a/tools/fdt_host.h b/tools/fdt_host.h index 134d9657139..8d4aa066bb0 100644 --- a/tools/fdt_host.h +++ b/tools/fdt_host.h @@ -11,6 +11,23 @@ #include "../include/libfdt.h" #include "../include/fdt_support.h" +/** + * fdt_remove_unused_strings() - Remove any unused strings from an FDT + * + * This creates a new device tree in @new with unused strings removed. The + * called can then use fdt_pack() to minimise the space consumed. + * + * @old: Old device tree blog + * @new: Place to put new device tree blob, which must be as large as + * @old + * @return + * 0, on success + * -FDT_ERR_BADOFFSET, corrupt device tree + * -FDT_ERR_NOSPACE, out of space, which should not happen unless there + * is something very wrong with the device tree input + */ +int fdt_remove_unused_strings(const void *old, void *new); + int fit_check_sign(const void *working_fdt, const void *key); #endif /* __FDT_HOST_H__ */ diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c index 5897b6d5f78..8d33205ea2a 100644 --- a/tools/fdtgrep.c +++ b/tools/fdtgrep.c @@ -10,13 +10,16 @@ #include <assert.h> #include <ctype.h> +#include <errno.h> #include <getopt.h> +#include <fcntl.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "../include/libfdt.h" +#include "fdt_host.h" #include "libfdt_internal.h" /* Define DEBUG to get some debugging output on stderr */ diff --git a/tools/gen_ethaddr_crc.c b/tools/gen_ethaddr_crc.c index fe9896dca94..8cf86f4835d 100644 --- a/tools/gen_ethaddr_crc.c +++ b/tools/gen_ethaddr_crc.c @@ -6,6 +6,7 @@ */ #include <ctype.h> +#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 195b1533ab6..729991ee33f 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -12,6 +12,7 @@ #include <assert.h> #include <fcntl.h> #include <getopt.h> +#include <stdbool.h> #include <stdlib.h> #include <stdio.h> #include <string.h> diff --git a/tools/imagetool.h b/tools/imagetool.h index a8d505423b8..e67de9b5ad3 100644 --- a/tools/imagetool.h +++ b/tools/imagetool.h @@ -12,6 +12,7 @@ #include "os_support.h" #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/tools/libfdt/fdt_rw.c b/tools/libfdt/fdt_rw.c new file mode 100644 index 00000000000..e475084faec --- /dev/null +++ b/tools/libfdt/fdt_rw.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause */ +#include "fdt_host.h" +#include "../../scripts/dtc/libfdt/fdt_rw.c" + +int fdt_remove_unused_strings(const void *old, void *new) +{ + const struct fdt_property *old_prop; + struct fdt_property *new_prop; + int size = fdt_totalsize(old); + int next_offset, offset; + const char *str; + int ret; + int tag = FDT_PROP; + + /* Make a copy and remove the strings */ + memcpy(new, old, size); + fdt_set_size_dt_strings(new, 0); + + /* Add every property name back into the new string table */ + for (offset = 0; tag != FDT_END; offset = next_offset) { + tag = fdt_next_tag(old, offset, &next_offset); + if (tag != FDT_PROP) + continue; + old_prop = fdt_get_property_by_offset(old, offset, NULL); + new_prop = (struct fdt_property *)(unsigned long) + fdt_get_property_by_offset(new, offset, NULL); + str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff)); + ret = _fdt_find_add_string(new, str); + if (ret < 0) + return ret; + new_prop->nameoff = cpu_to_fdt32(ret); + } + + return 0; +} diff --git a/tools/microcode-tool.py b/tools/microcode-tool.py index 790c27e4598..069d961d80d 100755 --- a/tools/microcode-tool.py +++ b/tools/microcode-tool.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # # Copyright (c) 2014 Google, Inc # diff --git a/tools/mips-relocs.c b/tools/mips-relocs.c index 8be69d320fb..27d47308e00 100644 --- a/tools/mips-relocs.c +++ b/tools/mips-relocs.c @@ -11,6 +11,7 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> diff --git a/tools/patman/patman.py b/tools/patman/patman.py index 4b3bc787453..7647440be5e 100755 --- a/tools/patman/patman.py +++ b/tools/patman/patman.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # # Copyright (c) 2011 The Chromium OS Authors. # diff --git a/tools/rkmux.py b/tools/rkmux.py index 39173359cae..11c192a0737 100755 --- a/tools/rkmux.py +++ b/tools/rkmux.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python2 # Script to create enums from datasheet register tables # |
