From 2c2dead122e5e7561806e99608cbc29c0b02ae29 Mon Sep 17 00:00:00 2001 From: liiir1985 Date: Sun, 23 Jun 2024 20:20:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0u-boot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- u-boot/Kconfig | 6 + u-boot/Makefile | 19 + u-boot/arch/arm/cpu/armv7/arch_timer.c | 2 +- u-boot/arch/arm/dts/rk3308.dtsi | 8 +- u-boot/arch/arm/dts/rk3528-u-boot.dtsi | 5 + u-boot/arch/arm/dts/rk3568-u-boot.dtsi | 2 +- u-boot/arch/arm/dts/rk3588-u-boot.dtsi | 18 + u-boot/arch/arm/dts/rk3588.dtsi | 1 + u-boot/arch/arm/dts/rk3588s.dtsi | 1 + u-boot/arch/arm/dts/rv1106-evb.dts | 4 + u-boot/arch/arm/dts/rv1106-evb2.dts | 9 +- u-boot/arch/arm/dts/rv1106.dtsi | 5 +- .../include/asm/arch-rockchip/cru_rk3528.h | 4 +- .../arm/include/asm/arch-rockchip/rk_atags.h | 26 + .../asm/arch-rockchip/rockchip_smccc.h | 1 + u-boot/arch/arm/lib/interrupts_64.c | 17 + u-boot/arch/arm/mach-rockchip/Kconfig | 31 +- u-boot/arch/arm/mach-rockchip/Makefile | 2 + u-boot/arch/arm/mach-rockchip/board.c | 263 +- u-boot/arch/arm/mach-rockchip/fit_nodes.sh | 4 + u-boot/arch/arm/mach-rockchip/memblk.c | 2 +- u-boot/arch/arm/mach-rockchip/pstore.c | 7 +- u-boot/arch/arm/mach-rockchip/rk3308/rk3308.c | 16 + u-boot/arch/arm/mach-rockchip/rk3562/rk3562.c | 24 +- u-boot/arch/arm/mach-rockchip/rk3588/rk3588.c | 210 +- u-boot/arch/arm/mach-rockchip/rk_atags.c | 46 +- u-boot/arch/arm/mach-rockchip/rk_mini_dump.c | 535 + u-boot/arch/arm/mach-rockchip/rv1106/rv1106.c | 25 +- u-boot/arch/arm/mach-rockchip/spl.c | 61 +- .../arch/arm/mach-rockchip/spl_pcie_ep_boot.c | 109 +- u-boot/arch/arm/mach-rockchip/usbplug.c | 125 +- u-boot/arch/arm/mach-rockchip/vendor.c | 40 +- u-boot/arch/arm/mach-rockchip/vendor_misc.c | 3 +- u-boot/board/rockchip/evb_rk3528/evb_rk3528.c | 56 +- u-boot/board/rockchip/evb_rk3588/evb_rk3588.c | 56 +- u-boot/cmd/Kconfig | 9 + u-boot/cmd/Makefile | 1 + u-boot/cmd/atags.c | 8 + u-boot/cmd/demo.c | 5 +- u-boot/cmd/gpio.c | 7 +- u-boot/cmd/pinmux.c | 147 + u-boot/cmd/pmic.c | 11 +- u-boot/cmd/regulator.c | 4 +- u-boot/cmd/rockusb.c | 88 +- u-boot/common/Kconfig | 14 + u-boot/common/Makefile | 1 + u-boot/common/board_info.c | 8 - u-boot/common/console.c | 14 +- u-boot/common/edid.c | 4 +- u-boot/common/fdt_support.c | 13 + u-boot/common/id_attestation.c | 93 + u-boot/common/image-android.c | 31 +- u-boot/common/image-sig.c | 2 +- u-boot/common/spl/Kconfig | 4 +- u-boot/common/spl/Makefile | 8 +- u-boot/common/spl/spl.c | 5 + u-boot/common/spl/spl_ab.c | 36 + u-boot/common/spl/spl_fit_tb_rv1106.S | 12882 ++++++++++++++++ ...spl_fit_tb_arm32.S => spl_fit_tb_rv1126.S} | 0 u-boot/common/stdio.c | 9 +- u-boot/common/write_keybox.c | 15 + u-boot/configs/gki.config | 1 + u-boot/configs/rk-amp.config | 1 - u-boot/configs/rk322x_defconfig | 2 + u-boot/configs/rk3308-ia.config | 14 + u-boot/configs/rk3308_defconfig | 2 + u-boot/configs/rk3328_defconfig | 8 +- u-boot/configs/rk3528-usbplug.config | 25 + u-boot/configs/rk3562-usbplug.config | 25 + u-boot/configs/rk3562_defconfig | 1 + u-boot/configs/rk3568-pcie-ep_defconfig | 226 + u-boot/configs/rk3568-usbplug.config | 14 + u-boot/configs/rk3568_defconfig | 4 +- u-boot/configs/rk3583.config | 2 + u-boot/configs/rk3588-ab-car.config | 18 + u-boot/configs/rk3588-qnx_defconfig | 2 +- u-boot/configs/rk3588-usbplug.config | 26 + u-boot/configs/rk3588_defconfig | 16 +- .../rv1106-spi-nand-tb-nofastae_defconfig | 121 + u-boot/configs/rv1106-spi-nand-tb_defconfig | 122 + u-boot/configs/rv1106-usbplug.config | 48 + u-boot/configs/rv1106_defconfig | 9 +- u-boot/configs/rv1126-emmc-tb-nofastae.config | 35 + u-boot/configs/rv1126-spl-slc-nand_defconfig | 184 + u-boot/disk/part_env.c | 4 +- u-boot/disk/part_rkparm.c | 4 +- u-boot/disk/part_rkram.c | 4 +- .../pinctrl/pinctrl-bindings.txt | 65 +- u-boot/drivers/ata/ahci.c | 16 + u-boot/drivers/clk/rockchip/clk_pll.c | 29 +- u-boot/drivers/clk/rockchip/clk_rk3036.c | 41 +- u-boot/drivers/clk/rockchip/clk_rk3308.c | 8 +- u-boot/drivers/clk/rockchip/clk_rk3528.c | 58 +- u-boot/drivers/clk/rockchip/clk_rk3562.c | 8 +- u-boot/drivers/clk/rockchip/clk_rk3568.c | 7 +- u-boot/drivers/clk/rockchip/clk_rk3588.c | 9 +- u-boot/drivers/clk/rockchip/clk_rv1106.c | 3 + u-boot/drivers/core/device.c | 4 +- u-boot/drivers/core/uclass.c | 65 +- u-boot/drivers/cpu/amp.its | 2 + u-boot/drivers/cpu/rockchip_amp.c | 12 +- u-boot/drivers/crypto/rockchip/crypto_v2.c | 4 + u-boot/drivers/dma/dma-uclass.c | 7 +- u-boot/drivers/gpio/Kconfig | 9 + u-boot/drivers/gpio/Makefile | 1 + u-boot/drivers/gpio/gpio-uclass.c | 14 +- u-boot/drivers/gpio/nca9539_gpio.c | 301 + u-boot/drivers/irq/irq-gpio-switch.c | 119 +- u-boot/drivers/irq/irq-gpio-v2.c | 2 +- u-boot/drivers/misc/Kconfig | 6 + u-boot/drivers/misc/Makefile | 1 + u-boot/drivers/misc/rockchip_decompress.c | 8 + u-boot/drivers/misc/rockchip_pm_config.c | 193 + u-boot/drivers/mmc/dw_mmc.c | 9 + u-boot/drivers/mmc/mmc-uclass.c | 3 +- u-boot/drivers/mmc/mmc.c | 8 +- u-boot/drivers/mmc/rockchip_dw_mmc.c | 126 +- u-boot/drivers/mtd/mtd_blk.c | 34 +- u-boot/drivers/mtd/nand/bbt.c | 250 +- .../drivers/mtd/nand/raw/rockchip_nand_spl.c | 9 +- .../mtd/nand/raw/rockchip_nand_spl_v9.c | 9 +- u-boot/drivers/mtd/nand/spi/core.c | 1 + u-boot/drivers/mtd/nand/spi/skyhigh.c | 8 +- u-boot/drivers/mtd/nand/spi/unim.c | 134 +- u-boot/drivers/mtd/nand/spi/winbond.c | 9 + u-boot/drivers/mtd/nand/spi/xincun.c | 9 + u-boot/drivers/mtd/nand/spi/xtx.c | 27 + u-boot/drivers/mtd/spi/spi-nor-core.c | 1 + u-boot/drivers/mtd/spi/spi-nor-ids.c | 3 +- u-boot/drivers/pci/pci-uclass.c | 15 +- .../drivers/phy/phy-rockchip-naneng-combphy.c | 77 +- u-boot/drivers/phy/phy-rockchip-usbdp.c | 670 +- u-boot/drivers/pinctrl/Kconfig | 25 + u-boot/drivers/pinctrl/pinctrl-generic.c | 125 +- u-boot/drivers/pinctrl/pinctrl-uclass.c | 169 +- .../pinctrl/rockchip/pinctrl-rockchip-core.c | 35 + .../drivers/pinctrl/rockchip/pinctrl-rv1126.c | 2 +- u-boot/drivers/power/charge_animation.c | 16 +- u-boot/drivers/power/pmic/rk8xx.c | 143 +- u-boot/drivers/power/pmic/rk8xx_spi.c | 57 +- u-boot/drivers/power/regulator/Kconfig | 11 +- u-boot/drivers/power/regulator/Makefile | 1 - u-boot/drivers/power/regulator/rk806.c | 1017 -- u-boot/drivers/power/regulator/rk8xx.c | 506 +- u-boot/drivers/rkflash/flash.c | 8 +- u-boot/drivers/rkflash/sfc_nand.c | 62 +- u-boot/drivers/rkflash/sfc_nor.c | 11 +- u-boot/drivers/serial/serial-uclass.c | 2 +- u-boot/drivers/spi/rockchip_sfc.c | 271 +- u-boot/drivers/usb/common/common.c | 7 + u-boot/drivers/usb/dwc3/core.c | 6 + u-boot/drivers/usb/dwc3/core.h | 3 + u-boot/drivers/usb/dwc3/ep0.c | 1 + u-boot/drivers/usb/dwc3/gadget.c | 53 +- u-boot/drivers/usb/gadget/composite.c | 4 + u-boot/drivers/usb/gadget/ether.c | 6 +- u-boot/drivers/usb/gadget/f_mass_storage.c | 20 +- u-boot/drivers/usb/gadget/f_rockusb.c | 201 +- u-boot/drivers/usb/gadget/storage_common.c | 4 + u-boot/drivers/video/drm/Kconfig | 3 + u-boot/drivers/video/drm/Makefile | 5 +- u-boot/drivers/video/drm/analogix_dp.c | 17 + .../drivers/video/drm/display-serdes/Kconfig | 29 + .../drivers/video/drm/display-serdes/Makefile | 15 + .../drivers/video/drm/display-serdes/core.h | 369 + .../drivers/video/drm/display-serdes/gpio.h | 253 + .../video/drm/display-serdes/maxim/Kconfig | 47 + .../video/drm/display-serdes/maxim/Makefile | 14 + .../drm/display-serdes/maxim/maxim-max96745.c | 813 + .../drm/display-serdes/maxim/maxim-max96745.h | 146 + .../drm/display-serdes/maxim/maxim-max96752.c | 594 + .../drm/display-serdes/maxim/maxim-max96752.h | 46 + .../drm/display-serdes/maxim/maxim-max96755.c | 709 + .../drm/display-serdes/maxim/maxim-max96755.h | 197 + .../drm/display-serdes/maxim/maxim-max96772.c | 737 + .../drm/display-serdes/maxim/maxim-max96772.h | 37 + .../drm/display-serdes/maxim/maxim-max96789.c | 726 + .../drm/display-serdes/maxim/maxim-max96789.h | 197 + .../video/drm/display-serdes/novo/Kconfig | 23 + .../video/drm/display-serdes/novo/Makefile | 10 + .../drm/display-serdes/novo/novo-nca9539.c | 18 + .../video/drm/display-serdes/rockchip/Kconfig | 28 + .../drm/display-serdes/rockchip/Makefile | 11 + .../display-serdes/rockchip/rockchip-rkx111.c | 39 + .../display-serdes/rockchip/rockchip-rkx121.c | 39 + .../video/drm/display-serdes/rohm/Kconfig | 28 + .../video/drm/display-serdes/rohm/Makefile | 11 + .../drm/display-serdes/rohm/rohm-bu18rl82.c | 458 + .../drm/display-serdes/rohm/rohm-bu18rl82.h | 395 + .../drm/display-serdes/rohm/rohm-bu18tl82.c | 441 + .../drm/display-serdes/rohm/rohm-bu18tl82.h | 452 + .../drm/display-serdes/serdes-bridge-split.c | 181 + .../video/drm/display-serdes/serdes-bridge.c | 196 + .../video/drm/display-serdes/serdes-core.c | 523 + .../video/drm/display-serdes/serdes-gpio.c | 109 + .../video/drm/display-serdes/serdes-i2c.c | 238 + .../drm/display-serdes/serdes-panel-split.c | 179 + .../video/drm/display-serdes/serdes-panel.c | 179 + .../video/drm/display-serdes/serdes-pinctrl.c | 217 + u-boot/drivers/video/drm/drm_of.c | 161 + u-boot/drivers/video/drm/drm_of.h | 33 + u-boot/drivers/video/drm/dw_hdmi.c | 26 +- u-boot/drivers/video/drm/dw_hdmi_qp.c | 131 +- u-boot/drivers/video/drm/dw_mipi_dsi2.c | 64 +- u-boot/drivers/video/drm/inno_mipi_phy.c | 7 +- u-boot/drivers/video/drm/libnsbmp.c | 1369 ++ u-boot/drivers/video/drm/libnsbmp.h | 252 + .../drm/phy-rockchip-samsung-hdptx-hdmi.c | 11 +- u-boot/drivers/video/drm/rockchip_display.c | 302 +- u-boot/drivers/video/drm/rockchip_display.h | 7 + .../drivers/video/drm/rockchip_dw_hdmi_qp.c | 6 +- u-boot/drivers/video/drm/rockchip_lvds.c | 105 +- u-boot/drivers/video/drm/rockchip_rgb.c | 3 + u-boot/drivers/video/drm/rockchip_vop.c | 15 +- u-boot/drivers/video/drm/rockchip_vop2.c | 225 +- u-boot/drivers/video/drm/samsung_mipi_dcphy.c | 3 + u-boot/env/envf.c | 13 + u-boot/include/abuf.h | 159 + u-boot/include/attestation_key.h | 1 + u-boot/include/configs/rk3528_common.h | 3 + u-boot/include/configs/rk3562_common.h | 2 + u-boot/include/configs/rk3568_common.h | 3 + u-boot/include/configs/rk3588_common.h | 6 + u-boot/include/configs/rockchip-common.h | 4 + u-boot/include/configs/rv1106_common.h | 8 +- u-boot/include/dm/pinctrl.h | 138 +- u-boot/include/dm/test.h | 2 + u-boot/include/dm/uclass.h | 88 +- u-boot/include/drm_modes.h | 47 + u-boot/include/dt-bindings/clock/rk3308-cru.h | 4 +- u-boot/include/edid.h | 2 + u-boot/include/elf.h | 372 +- u-boot/include/fdt_support.h | 13 + u-boot/include/id_attestation.h | 43 + u-boot/include/linux/mtd/spinand.h | 1 + u-boot/include/linux/string.h | 13 + u-boot/include/linux/usb/ch9.h | 4 - .../linux/usb/phy-rockchip-naneng-combphy.h | 18 + u-boot/include/linux/usb/phy-rockchip-usbdp.h | 66 +- .../optee_include/OpteeClientInterface.h | 15 + .../include/optee_include/OpteeClientLoadTa.h | 33 + u-boot/include/power/rk8xx_pmic.h | 85 + u-boot/include/rk_mini_dump.h | 39 + u-boot/include/rockusb.h | 39 +- u-boot/include/usbplug.h | 12 + u-boot/lib/Makefile | 1 + u-boot/lib/abuf.c | 109 + u-boot/lib/display_options.c | 2 +- u-boot/lib/efi_loader/efi_gop.c | 3 +- u-boot/lib/optee_clientApi/Makefile | 1 + .../optee_clientApi/OpteeClientInterface.c | 428 + .../lib/optee_clientApi/OpteeClientLoadTa.c | 162 + u-boot/lib/optee_clientApi/OpteeClientRPC.c | 166 +- u-boot/lib/optee_clientApi/tabinary_to_img.py | 86 + .../1db57234-dacd-462d-9bb1-ae79de44e2a5.ta | 3 + .../1db57234-dacd-462d-9bb1ae79de44e2a5.ta | 3 + u-boot/lib/rsa/rsa-verify.c | 51 +- u-boot/lib/string.c | 13 + u-boot/make.sh | 20 +- u-boot/net/eth-uclass.c | 4 +- u-boot/scripts/fit.sh | 21 +- u-boot/test/dm/core.c | 24 +- u-boot/test/dm/test-fdt.c | 69 +- u-boot/test/dm/test-main.c | 8 +- 264 files changed, 32398 insertions(+), 2698 deletions(-) create mode 100644 u-boot/arch/arm/mach-rockchip/rk_mini_dump.c create mode 100644 u-boot/cmd/pinmux.c create mode 100644 u-boot/common/id_attestation.c create mode 100644 u-boot/common/spl/spl_fit_tb_rv1106.S rename u-boot/common/spl/{spl_fit_tb_arm32.S => spl_fit_tb_rv1126.S} (100%) mode change 100755 => 100644 u-boot/common/write_keybox.c create mode 100644 u-boot/configs/gki.config create mode 100644 u-boot/configs/rk3308-ia.config create mode 100644 u-boot/configs/rk3528-usbplug.config create mode 100644 u-boot/configs/rk3562-usbplug.config create mode 100644 u-boot/configs/rk3568-pcie-ep_defconfig create mode 100644 u-boot/configs/rk3583.config create mode 100644 u-boot/configs/rk3588-ab-car.config create mode 100644 u-boot/configs/rk3588-usbplug.config create mode 100644 u-boot/configs/rv1106-spi-nand-tb-nofastae_defconfig create mode 100644 u-boot/configs/rv1106-spi-nand-tb_defconfig create mode 100755 u-boot/configs/rv1106-usbplug.config create mode 100644 u-boot/configs/rv1126-emmc-tb-nofastae.config create mode 100644 u-boot/configs/rv1126-spl-slc-nand_defconfig create mode 100644 u-boot/drivers/gpio/nca9539_gpio.c create mode 100644 u-boot/drivers/misc/rockchip_pm_config.c delete mode 100644 u-boot/drivers/power/regulator/rk806.c create mode 100644 u-boot/drivers/video/drm/display-serdes/Kconfig create mode 100644 u-boot/drivers/video/drm/display-serdes/Makefile create mode 100644 u-boot/drivers/video/drm/display-serdes/core.h create mode 100644 u-boot/drivers/video/drm/display-serdes/gpio.h create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/Kconfig create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/Makefile create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.c create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.h create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.c create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.h create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.c create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.h create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.c create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.h create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.c create mode 100644 u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.h create mode 100644 u-boot/drivers/video/drm/display-serdes/novo/Kconfig create mode 100644 u-boot/drivers/video/drm/display-serdes/novo/Makefile create mode 100644 u-boot/drivers/video/drm/display-serdes/novo/novo-nca9539.c create mode 100644 u-boot/drivers/video/drm/display-serdes/rockchip/Kconfig create mode 100644 u-boot/drivers/video/drm/display-serdes/rockchip/Makefile create mode 100644 u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx111.c create mode 100644 u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx121.c create mode 100644 u-boot/drivers/video/drm/display-serdes/rohm/Kconfig create mode 100644 u-boot/drivers/video/drm/display-serdes/rohm/Makefile create mode 100644 u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.c create mode 100644 u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.h create mode 100644 u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.c create mode 100644 u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.h create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-bridge-split.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-bridge.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-core.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-gpio.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-i2c.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-panel-split.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-panel.c create mode 100644 u-boot/drivers/video/drm/display-serdes/serdes-pinctrl.c create mode 100644 u-boot/drivers/video/drm/drm_of.c create mode 100644 u-boot/drivers/video/drm/drm_of.h create mode 100644 u-boot/drivers/video/drm/libnsbmp.c create mode 100644 u-boot/drivers/video/drm/libnsbmp.h create mode 100644 u-boot/include/abuf.h create mode 100644 u-boot/include/id_attestation.h create mode 100644 u-boot/include/linux/usb/phy-rockchip-naneng-combphy.h create mode 100644 u-boot/include/optee_include/OpteeClientLoadTa.h create mode 100644 u-boot/include/rk_mini_dump.h create mode 100644 u-boot/include/usbplug.h create mode 100644 u-boot/lib/abuf.c create mode 100644 u-boot/lib/optee_clientApi/OpteeClientLoadTa.c create mode 100644 u-boot/lib/optee_clientApi/tabinary_to_img.py create mode 100644 u-boot/lib/optee_clientApi/userta/1db57234-dacd-462d-9bb1-ae79de44e2a5.ta create mode 100644 u-boot/lib/optee_clientApi/userta/1db57234-dacd-462d-9bb1ae79de44e2a5.ta diff --git a/u-boot/Kconfig b/u-boot/Kconfig index 548950970a..7c0af1e5ca 100644 --- a/u-boot/Kconfig +++ b/u-boot/Kconfig @@ -168,6 +168,12 @@ endmenu # General setup menu "Boot images" +config IMAGE_GZIP + bool "U-Boot Image with gzip compression" + default n + help + This enables gzip compression on U-Boot Image. + config ANDROID_BOOT_IMAGE bool "Enable support for Android Boot Images" default y if FASTBOOT diff --git a/u-boot/Makefile b/u-boot/Makefile index 590fd4c1f2..1012b065ad 100644 --- a/u-boot/Makefile +++ b/u-boot/Makefile @@ -85,6 +85,13 @@ else Q = @ endif +ifeq ("$(origin FWVER)", "command line") + PLAT_FW_VERSION := $(FWVER) +endif +ifeq ("$(origin SPL_FWVER)", "command line") + PLAT_SPL_FW_VERSION := $(SPL_FWVER) +endif + # If the user is running make -s (silent mode), suppress echoing of # commands @@ -1369,6 +1376,12 @@ ifeq ($(CONFIG_SUPPORT_USBPLUG),) define filechk_version.h (echo \#define PLAIN_VERSION \"$(UBOOTRELEASE)\"; \ echo \#define U_BOOT_VERSION \"U-Boot \" PLAIN_VERSION; \ + if [ -n "$(PLAT_SPL_FW_VERSION)" ]; then \ + echo \#define BUILD_SPL_TAG \"$(PLAT_SPL_FW_VERSION)\"; \ + fi; \ + if [ -n "$(PLAT_FW_VERSION)" ]; then \ + echo \#define BUILD_TAG \"$(PLAT_FW_VERSION)\"; \ + fi; \ echo \#define CC_VERSION_STRING \"$$(LC_ALL=C $(CC) --version | head -n 1)\"; \ echo \#define LD_VERSION_STRING \"$$(LC_ALL=C $(LD) --version | head -n 1)\"; ) endef @@ -1376,6 +1389,12 @@ else define filechk_version.h (echo \#define PLAIN_VERSION \"$(UBOOTRELEASE)\"; \ echo \#define U_BOOT_VERSION \"USB-PLUG \" PLAIN_VERSION; \ + if [ -n "$(PLAT_SPL_FW_VERSION)" ]; then \ + echo \#define BUILD_SPL_TAG \"$(PLAT_SPL_FW_VERSION)\"; \ + fi; \ + if [ -n "$(PLAT_FW_VERSION)" ]; then \ + echo \#define BUILD_TAG \"$(PLAT_FW_VERSION)\"; \ + fi; \ echo \#define CC_VERSION_STRING \"$$(LC_ALL=C $(CC) --version | head -n 1)\"; \ echo \#define LD_VERSION_STRING \"$$(LC_ALL=C $(LD) --version | head -n 1)\"; ) endef diff --git a/u-boot/arch/arm/cpu/armv7/arch_timer.c b/u-boot/arch/arm/cpu/armv7/arch_timer.c index 545c518506..c4400a061c 100644 --- a/u-boot/arch/arm/cpu/armv7/arch_timer.c +++ b/u-boot/arch/arm/cpu/armv7/arch_timer.c @@ -41,5 +41,5 @@ ulong timer_get_boot_us(void) ulong get_tbclk(void) { - return gd->arch.timer_rate_hz; + return gd->arch.timer_rate_hz ? : CONFIG_SYS_HZ_CLOCK; } diff --git a/u-boot/arch/arm/dts/rk3308.dtsi b/u-boot/arch/arm/dts/rk3308.dtsi index acdb47f55d..e646bddb13 100644 --- a/u-boot/arch/arm/dts/rk3308.dtsi +++ b/u-boot/arch/arm/dts/rk3308.dtsi @@ -300,7 +300,7 @@ #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm0_pin>; - clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; status = "disabled"; }; @@ -311,7 +311,7 @@ #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm1_pin>; - clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; status = "disabled"; }; @@ -322,7 +322,7 @@ #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm2_pin>; - clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; status = "disabled"; }; @@ -333,7 +333,7 @@ #pwm-cells = <3>; pinctrl-names = "active"; pinctrl-0 = <&pwm3_pin>; - clocks = <&cru SCLK_PWM>, <&cru PCLK_PWM>; + clocks = <&cru SCLK_PWM0>, <&cru PCLK_PWM>; clock-names = "pwm", "pclk"; status = "disabled"; }; diff --git a/u-boot/arch/arm/dts/rk3528-u-boot.dtsi b/u-boot/arch/arm/dts/rk3528-u-boot.dtsi index 7d093617e7..405af02872 100644 --- a/u-boot/arch/arm/dts/rk3528-u-boot.dtsi +++ b/u-boot/arch/arm/dts/rk3528-u-boot.dtsi @@ -37,6 +37,11 @@ status = "okay"; }; +&combphy_pu { + u-boot,dm-pre-reloc; + status = "okay"; +}; + &cru { /delete-property/ assigned-clocks; /delete-property/ assigned-clock-rates; diff --git a/u-boot/arch/arm/dts/rk3568-u-boot.dtsi b/u-boot/arch/arm/dts/rk3568-u-boot.dtsi index a0678e35db..77abf24a3e 100644 --- a/u-boot/arch/arm/dts/rk3568-u-boot.dtsi +++ b/u-boot/arch/arm/dts/rk3568-u-boot.dtsi @@ -387,7 +387,7 @@ }; &pinctrl { - u-boot,dm-pre-reloc; + u-boot,dm-spl; status = "okay"; }; diff --git a/u-boot/arch/arm/dts/rk3588-u-boot.dtsi b/u-boot/arch/arm/dts/rk3588-u-boot.dtsi index d0b82f64b7..8dbc5d688e 100644 --- a/u-boot/arch/arm/dts/rk3588-u-boot.dtsi +++ b/u-boot/arch/arm/dts/rk3588-u-boot.dtsi @@ -193,6 +193,24 @@ status = "okay"; }; +&usb_grf{ + u-boot,dm-pre-reloc; +}; + +&usbdpphy0_grf{ + u-boot,dm-pre-reloc; +}; + +&usbdp_phy0{ + u-boot,dm-pre-reloc; + status = "okay"; +}; + +&usbdp_phy0_u3{ + u-boot,dm-pre-reloc; + status = "okay"; +}; + /* Support SPL-PINCTRL: * 1. ioc * 2. pinctrl(sdmmc) diff --git a/u-boot/arch/arm/dts/rk3588.dtsi b/u-boot/arch/arm/dts/rk3588.dtsi index fbffe36daf..c75f661bee 100644 --- a/u-boot/arch/arm/dts/rk3588.dtsi +++ b/u-boot/arch/arm/dts/rk3588.dtsi @@ -467,6 +467,7 @@ usbdp_phy1: phy@fed90000 { compatible = "rockchip,rk3588-usbdp-phy"; reg = <0x0 0xfed90000 0x0 0x10000>; + rockchip,u2phy-grf = <&usb2phy1_grf>; rockchip,usb-grf = <&usb_grf>; rockchip,usbdpphy-grf = <&usbdpphy1_grf>; rockchip,vo-grf = <&vo0_grf>; diff --git a/u-boot/arch/arm/dts/rk3588s.dtsi b/u-boot/arch/arm/dts/rk3588s.dtsi index ebe8761ac1..d97ed1b4d5 100644 --- a/u-boot/arch/arm/dts/rk3588s.dtsi +++ b/u-boot/arch/arm/dts/rk3588s.dtsi @@ -2260,6 +2260,7 @@ usbdp_phy0: phy@fed80000 { compatible = "rockchip,rk3588-usbdp-phy"; reg = <0x0 0xfed80000 0x0 0x10000>; + rockchip,u2phy-grf = <&usb2phy0_grf>; rockchip,usb-grf = <&usb_grf>; rockchip,usbdpphy-grf = <&usbdpphy0_grf>; rockchip,vo-grf = <&vo0_grf>; diff --git a/u-boot/arch/arm/dts/rv1106-evb.dts b/u-boot/arch/arm/dts/rv1106-evb.dts index 344558f8f9..06a03d3329 100644 --- a/u-boot/arch/arm/dts/rv1106-evb.dts +++ b/u-boot/arch/arm/dts/rv1106-evb.dts @@ -30,3 +30,7 @@ }; }; +&hw_decompress { + u-boot,dm-spl; + status = "okay"; +}; diff --git a/u-boot/arch/arm/dts/rv1106-evb2.dts b/u-boot/arch/arm/dts/rv1106-evb2.dts index 71ad07be7c..7b9d9dc68b 100644 --- a/u-boot/arch/arm/dts/rv1106-evb2.dts +++ b/u-boot/arch/arm/dts/rv1106-evb2.dts @@ -22,7 +22,7 @@ compatible = "adc-keys"; io-channels = <&saradc 0>; io-channel-names = "buttons"; - keyup-threshold-microvolt = <1800000>; + keyup-threshold-microvolt = <893000>; u-boot,dm-spl; status = "okay"; @@ -30,6 +30,13 @@ u-boot,dm-spl; linux,code = ; label = "volume up"; + press-threshold-microvolt = <339589>; + }; + + volumedown-key { + u-boot,dm-spl; + linux,code = ; + label = "volume down"; press-threshold-microvolt = <17578>; }; }; diff --git a/u-boot/arch/arm/dts/rv1106.dtsi b/u-boot/arch/arm/dts/rv1106.dtsi index dba1d8c865..7a88bb13eb 100644 --- a/u-boot/arch/arm/dts/rv1106.dtsi +++ b/u-boot/arch/arm/dts/rv1106.dtsi @@ -861,8 +861,11 @@ wdt: watchdog@ff5a0000 { compatible = "rockchip,rv1106-wdt", "snps,dw-wdt"; reg = <0xff5a0000 0x100>; - clocks = <&cru PCLK_WDT_NS>; + clocks = <&cru TCLK_WDT_NS>, <&cru PCLK_WDT_NS>; + clock-names = "tclk", "pclk"; interrupts = ; + resets = <&cru SRST_P_WDT_NS>; + reset-names = "reset"; status = "disabled"; }; diff --git a/u-boot/arch/arm/include/asm/arch-rockchip/cru_rk3528.h b/u-boot/arch/arm/include/asm/arch-rockchip/cru_rk3528.h index 3576b03c21..6be2648d5b 100644 --- a/u-boot/arch/arm/include/asm/arch-rockchip/cru_rk3528.h +++ b/u-boot/arch/arm/include/asm/arch-rockchip/cru_rk3528.h @@ -124,10 +124,10 @@ struct pll_rate_table { #define RK3528_PCIE_CLKSEL_CON(x) ((x) * 0x4 + 0x300 + RK3528_PCIE_CRU_BASE) #define RK3528_DDRPHY_MODE_CON (0x280 + RK3528_DDRPHY_CRU_BASE) -#define RK3528_DIV_ACLK_M_CORE_MASK 0x1f #define RK3528_DIV_ACLK_M_CORE_SHIFT 11 -#define RK3528_DIV_PCLK_DBG_MASK 0x1f +#define RK3528_DIV_ACLK_M_CORE_MASK (0x1f << RK3528_DIV_ACLK_M_CORE_SHIFT) #define RK3528_DIV_PCLK_DBG_SHIFT 1 +#define RK3528_DIV_PCLK_DBG_MASK (0x1f << RK3528_DIV_PCLK_DBG_SHIFT) enum { /* CRU_CLKSEL_CON00 */ diff --git a/u-boot/arch/arm/include/asm/arch-rockchip/rk_atags.h b/u-boot/arch/arm/include/asm/arch-rockchip/rk_atags.h index 5b9a17d515..efc0189f41 100644 --- a/u-boot/arch/arm/include/asm/arch-rockchip/rk_atags.h +++ b/u-boot/arch/arm/include/asm/arch-rockchip/rk_atags.h @@ -21,6 +21,7 @@ #define ATAG_SOC_INFO 0x54410057 #define ATAG_BOOT1_PARAM 0x54410058 #define ATAG_PSTORE 0x54410059 +#define ATAG_FWVER 0x5441005a #define ATAG_MAX 0x544100ff /* Tag size and offset */ @@ -75,6 +76,17 @@ /* tag_ddr_mem.flags */ #define DDR_MEM_FLG_EXT_TOP 1 +/* tag_fwver.ver[fwid][] */ +#define FWVER_LEN 36 + +enum fwid { + FW_DDR, + FW_SPL, + FW_ATF, + FW_TEE, + FW_MAX, +}; + struct tag_serial { u32 version; u32 enable; @@ -183,6 +195,12 @@ struct tag_pstore { u32 hash; } __packed; +struct tag_fwver { + u32 version; + char ver[8][FWVER_LEN]; + u32 hash; +} __packed; + struct tag_core { u32 flags; u32 pagesize; @@ -209,6 +227,7 @@ struct tag { struct tag_soc_info soc; struct tag_boot1p boot1p; struct tag_pstore pstore; + struct tag_fwver fwver; } u; } __aligned(4); @@ -266,6 +285,13 @@ int atags_overflow(struct tag *t); */ int atags_bad_magic(u32 magic); +/* + * atags_set_shared_fwver - set fwver tag. + * + * return: 0 on success, otherwise failed. + */ +int atags_set_shared_fwver(u32 fwid, char *ver); + #ifdef CONFIG_SPL_BUILD /* * get_bootdev_by_brom_bootsource diff --git a/u-boot/arch/arm/include/asm/arch-rockchip/rockchip_smccc.h b/u-boot/arch/arm/include/asm/arch-rockchip/rockchip_smccc.h index 39bafbc0a3..afe6c5e9df 100644 --- a/u-boot/arch/arm/include/asm/arch-rockchip/rockchip_smccc.h +++ b/u-boot/arch/arm/include/asm/arch-rockchip/rockchip_smccc.h @@ -95,6 +95,7 @@ typedef enum { SHARE_PAGE_TYPE_DDR_ADDRMAP, SHARE_PAGE_TYPE_LAST_LOG, SHARE_PAGE_TYPE_HDCP, + SHARE_PAGE_TYPE_SLEEP, SHARE_PAGE_TYPE_MAX, } share_page_type_t; diff --git a/u-boot/arch/arm/lib/interrupts_64.c b/u-boot/arch/arm/lib/interrupts_64.c index 17271d061f..e51d38a8a4 100644 --- a/u-boot/arch/arm/lib/interrupts_64.c +++ b/u-boot/arch/arm/lib/interrupts_64.c @@ -10,6 +10,9 @@ #include #include #include +#ifdef CONFIG_ROCKCHIP_MINIDUMP +#include +#endif DECLARE_GLOBAL_DATA_PTR; @@ -181,6 +184,13 @@ void do_bad_error(struct pt_regs *pt_regs, unsigned int esr) void do_sync(struct pt_regs *pt_regs, unsigned int esr) { efi_restore_gd(); +#ifdef CONFIG_ROCKCHIP_MINIDUMP + if (md_no_fault_handler(pt_regs, esr)) { + /* Return to next instruction */ + pt_regs->elr += 4; + return; + } +#endif printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr); show_regs(pt_regs); panic("Resetting CPU ...\n"); @@ -219,6 +229,13 @@ void do_fiq(struct pt_regs *pt_regs, unsigned int esr) void __weak do_error(struct pt_regs *pt_regs, unsigned int esr) { efi_restore_gd(); +#ifdef CONFIG_ROCKCHIP_MINIDUMP + if (md_no_fault_handler(pt_regs, esr)) { + /* Return to next instruction */ + pt_regs->elr += 4; + return; + } +#endif printf("\"Error\" handler, esr 0x%08x\n", esr); show_regs(pt_regs); panic("Resetting CPU ...\n"); diff --git a/u-boot/arch/arm/mach-rockchip/Kconfig b/u-boot/arch/arm/mach-rockchip/Kconfig index 383503ddeb..f76eb1868e 100644 --- a/u-boot/arch/arm/mach-rockchip/Kconfig +++ b/u-boot/arch/arm/mach-rockchip/Kconfig @@ -487,7 +487,7 @@ config TPL_LDSCRIPT default "arch/arm/mach-rockchip/u-boot-tpl-v8.lds" config TPL_TEXT_BASE - default 0xfdcc1000 + default 0xff001000 config TPL_MAX_SIZE default 61440 @@ -846,7 +846,7 @@ config ROCKCHIP_HWID_DTB config ROCKCHIP_VENDOR_PARTITION bool "Rockchip vendor storage partition support" - depends on RKIMG_BOOTLOADER + depends on (RKIMG_BOOTLOADER || SUPPORT_USBPLUG) help This enable support to read/write vendor configuration data from/to this partition. @@ -1101,6 +1101,33 @@ config PERSISTENT_RAM_SIZE This select linux pstore buffer size for U-Boot, the value must be set if PERSISTENT_RAM_ADDR != 0. +config ROCKCHIP_MINIDUMP + bool "Minidump Save Linux Debug Data To Ram Elf" + default n + help + This enable saving linux debug data to a reserved memory as a elf file. + +config ROCKCHIP_MINIDUMP_SMEM_BASE + hex "The base of share memory between Uboot and Linux" + default 0x1f0000 + depends on ROCKCHIP_MINIDUMP + help + This select the base address of share memory, which is behind PSTORE. + +config ROCKCHIP_MINIDUMP_MAX_ELF_SIZE + hex "The max size of minidump elf" + default 0x2000000 + depends on ROCKCHIP_MINIDUMP + help + This is used to judge the elf program size and section size. + +config ROCKCHIP_MINIDUMP_MAX_ENTRIES + hex "The max entries of minidump region" + default 0x200 + depends on ROCKCHIP_MINIDUMP + help + This sets the max entries of minidump region. + source "arch/arm/mach-rockchip/px30/Kconfig" source "arch/arm/mach-rockchip/rk3036/Kconfig" source "arch/arm/mach-rockchip/rk3066/Kconfig" diff --git a/u-boot/arch/arm/mach-rockchip/Makefile b/u-boot/arch/arm/mach-rockchip/Makefile index 75de030b8f..095f99d907 100644 --- a/u-boot/arch/arm/mach-rockchip/Makefile +++ b/u-boot/arch/arm/mach-rockchip/Makefile @@ -92,3 +92,5 @@ obj-$(CONFIG_TPL_BUILD) += $(obj-tpl-y) obj-$(CONFIG_ROCKCHIP_PRELOADER_ATAGS) += rk_atags.o obj-$(CONFIG_SET_DFU_ALT_INFO) += dfu_alt_info.o obj-$(CONFIG_PSTORE) += pstore.o +obj-$(CONFIG_ROCKCHIP_MINIDUMP) += rk_mini_dump.o + diff --git a/u-boot/arch/arm/mach-rockchip/board.c b/u-boot/arch/arm/mach-rockchip/board.c index 00a705c208..6121bb8ce5 100644 --- a/u-boot/arch/arm/mach-rockchip/board.c +++ b/u-boot/arch/arm/mach-rockchip/board.c @@ -5,6 +5,8 @@ */ #include +#include +#include #include #include #include @@ -26,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -53,8 +56,9 @@ #ifdef CONFIG_ROCKCHIP_EINK_DISPLAY #include #endif - -DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_ROCKCHIP_MINIDUMP +#include +#endif #ifdef CONFIG_ARM64 static ulong orig_images_ep; @@ -98,7 +102,6 @@ __weak int rk_board_init(void) */ #define VENDOR_SN_MAX 513 #define CPUID_LEN 0x10 -#define CPUID_OFF 0x07 #define MAX_ETHERNET 0x2 @@ -175,10 +178,13 @@ static int rockchip_set_serialno(void) for (i = 0; i < j; i++) { if ((serialno_str[i] >= 'a' && serialno_str[i] <= 'z') || (serialno_str[i] >= 'A' && serialno_str[i] <= 'Z') || - (serialno_str[i] >= '0' && serialno_str[i] <= '9')) + (serialno_str[i] >= '0' && serialno_str[i] <= '9')) { continue; - else + } else { + if (i > 0) + serialno_str[i] = 0x0; break; + } } /* valid character count > 0 */ @@ -208,7 +214,7 @@ static int rockchip_set_serialno(void) } /* read the cpu_id range from the efuses */ - ret = misc_read(dev, CPUID_OFF, &cpuid, sizeof(cpuid)); + ret = misc_read(dev, CFG_CPUID_OFFSET, &cpuid, sizeof(cpuid)); if (ret) { printf("%s: read cpuid from efuse/otp failed, ret=%d\n", __func__, ret); @@ -461,6 +467,11 @@ int board_late_init(void) #ifdef CONFIG_DM_CHARGE_DISPLAY charge_display(); #endif + +#ifdef CONFIG_ROCKCHIP_MINIDUMP + rk_minidump_init(); +#endif + #ifdef CONFIG_DRM_ROCKCHIP if (rockchip_get_boot_mode() != BOOT_MODE_QUIESCENT) rockchip_show_logo(); @@ -544,7 +555,6 @@ int board_init(void) if (ab_decrease_tries()) printf("Decrease ab tries count fail!\n"); #endif - return rk_board_init(); } @@ -894,7 +904,7 @@ int bootm_board_start(void) * we switch to uart debug function in order to print it after loading * images. */ -#if defined(CONFIG_CONSOLE_RECORD) +#if 0 if (!strcmp("mmc", env_get("devtype")) && !strcmp("1", env_get("devnum"))) { printf("IOMUX: sdmmc => uart debug"); @@ -1115,47 +1125,142 @@ void board_quiesce_devices(void *images) #endif } -char *board_fdt_chosen_bootargs(void *fdt) +/* + * Use hardware rng to seed Linux random + * + * 'Android_14 + GKI' requires this information. + */ +int board_rng_seed(struct abuf *buf) { - /* bootargs_ext is used when dtbo is applied. */ - const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; - const char *bootargs; - int nodeoffset; - int i, dump; - char *msg = "kernel"; - - /* debug */ - hotkey_run(HK_INITCALL); - dump = is_hotkey(HK_CMDLINE); - if (dump) - printf("## bootargs(u-boot): %s\n\n", env_get("bootargs")); - - /* find or create "/chosen" node. */ - nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); - if (nodeoffset < 0) - return NULL; - - for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { - bootargs = fdt_getprop(fdt, nodeoffset, arr_bootargs[i], NULL); - if (!bootargs) - continue; - if (dump) - printf("## bootargs(%s-%s): %s\n\n", - msg, arr_bootargs[i], bootargs); - /* - * Append kernel bootargs - * If use AB system, delete default "root=" which route - * to rootfs. Then the ab bootctl will choose the - * high priority system to boot and add its UUID - * to cmdline. The format is "roo=PARTUUID=xxxx...". - */ -#ifdef CONFIG_ANDROID_AB - env_update_filter("bootargs", bootargs, "root="); -#else - env_update("bootargs", bootargs); +#ifdef CONFIG_DM_RNG + struct udevice *dev; #endif + size_t len = 32; + u8 *data; + int i; + + data = malloc(len); + if (!data) { + printf("Out of memory\n"); + return -ENOMEM; } +#ifdef CONFIG_DM_RNG + if (uclass_get_device(UCLASS_RNG, 0, &dev) || dm_rng_read(dev, data, len)) +#endif + { + printf("board seed: Pseudo\n"); + for (i = 0; i < len; i++) + data[i] = (u8)rand(); + } + + abuf_init_set(buf, data, len); + + return 0; +} + +/* + * Pass fwver when any available. + */ +static void bootargs_add_fwver(bool verbose) +{ +#ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS + struct tag *t; + char *list1 = NULL; + char *list2 = NULL; + char *fwver = NULL; + char *p = PLAIN_VERSION; + int i, end; + + t = atags_get_tag(ATAG_FWVER); + if (t) { + list1 = calloc(1, sizeof(struct tag_fwver)); + if (!list1) + return; + for (i = 0; i < FW_MAX; i++) { + if (t->u.fwver.ver[i][0] != '\0') { + strcat(list1, t->u.fwver.ver[i]); + strcat(list1, ","); + } + } + } + + list2 = calloc(1, FWVER_LEN); + if (!list2) + goto out; + strcat(list2, "uboot-"); + /* optional */ +#ifdef BUILD_TAG + strcat(list2, BUILD_TAG); + strcat(list2, "-"); +#endif + /* optional */ + if (strcmp(PLAIN_VERSION, "2017.09")) { + strncat(list2, p + strlen("2017.09-g"), 10); + strcat(list2, "-"); + } + strcat(list2, U_BOOT_DMI_DATE); + + /* merge ! */ + if (list1 || list2) { + fwver = calloc(1, sizeof(struct tag_fwver)); + if (!fwver) + goto out; + + strcat(fwver, "androidboot.fwver="); + if (list1) + strcat(fwver, list1); + if (list2) { + strcat(fwver, list2); + } else { + end = strlen(fwver) - 1; + fwver[end] = '\0'; /* omit last ',' */ + } + if (verbose) + printf("## fwver: %s\n\n", fwver); + env_update("bootargs", fwver); + env_set("fwver", fwver + strlen("androidboot.")); + } +out: + if (list1) + free(list1); + if (list2) + free(list2); + if (fwver) + free(fwver); +#endif +} + +static void bootargs_add_android(bool verbose) +{ +#ifdef CONFIG_ANDROID_AB + ab_update_root_partition(); +#endif + + /* Android header v4+ need this handle */ +#ifdef CONFIG_ANDROID_BOOT_IMAGE + struct andr_img_hdr *hdr; + char *fwver; + + hdr = (void *)env_get_ulong("android_addr_r", 16, 0); + if (hdr && !android_image_check_header(hdr) && hdr->header_version >= 4) { + if (env_update_extract_subset("bootargs", "andr_bootargs", "androidboot.")) + printf("extract androidboot.xxx error\n"); + if (verbose) + printf("## bootargs(android): %s\n\n", env_get("andr_bootargs")); + + /* for kernel cmdline can be read */ + fwver = env_get("fwver"); + if (fwver) { + env_update("bootargs", fwver); + env_set("fwver", NULL); + } + } +#endif +} + +static void bootargs_add_partition(bool verbose) +{ #if defined(CONFIG_ENVF) || defined(CONFIG_ENV_PARTITION) char *part_type[] = { "mtdparts", "blkdevparts" }; char *part_list; @@ -1177,14 +1282,14 @@ char *board_fdt_chosen_bootargs(void *fdt) part_list = env; } env_update("bootargs", part_list); - if (dump) + if (verbose) printf("## parts: %s\n\n", part_list); } env = env_get("sys_bootargs"); if (env) { env_update("bootargs", env); - if (dump) + if (verbose) printf("## sys_bootargs: %s\n\n", env); } #endif @@ -1199,10 +1304,58 @@ char *board_fdt_chosen_bootargs(void *fdt) } } #endif +} +static void bootargs_add_dtb_dtbo(void *fdt, bool verbose) +{ + /* bootargs_ext is used when dtbo is applied. */ + const char *arr_bootargs[] = { "bootargs", "bootargs_ext" }; + const char *bootargs; + char *msg = "kernel"; + int i, noffset; + + /* find or create "/chosen" node. */ + noffset = fdt_find_or_add_subnode(fdt, 0, "chosen"); + if (noffset < 0) + return; + + for (i = 0; i < ARRAY_SIZE(arr_bootargs); i++) { + bootargs = fdt_getprop(fdt, noffset, arr_bootargs[i], NULL); + if (!bootargs) + continue; + if (verbose) + printf("## bootargs(%s-%s): %s\n\n", + msg, arr_bootargs[i], bootargs); + /* + * Append kernel bootargs + * If use AB system, delete default "root=" which route + * to rootfs. Then the ab bootctl will choose the + * high priority system to boot and add its UUID + * to cmdline. The format is "roo=PARTUUID=xxxx...". + */ #ifdef CONFIG_ANDROID_AB - ab_update_root_partition(); + env_update_filter("bootargs", bootargs, "root="); +#else + env_update("bootargs", bootargs); #endif + } +} + +char *board_fdt_chosen_bootargs(void *fdt) +{ + int verbose = is_hotkey(HK_CMDLINE); + const char *bootargs; + + /* debug */ + hotkey_run(HK_INITCALL); + if (verbose) + printf("## bootargs(u-boot): %s\n\n", env_get("bootargs")); + + bootargs_add_dtb_dtbo(fdt, verbose); + bootargs_add_partition(verbose); + bootargs_add_fwver(verbose); + bootargs_add_android(verbose); + /* * Initrd fixup: remove unused "initrd=0x...,0x...", * this for compatible with legacy parameter.txt @@ -1225,20 +1378,8 @@ char *board_fdt_chosen_bootargs(void *fdt) if (gd->flags & GD_FLG_DISABLE_CONSOLE) env_delete("bootargs", "earlycon=", 0); - /* Android header v4+ need this handle */ -#ifdef CONFIG_ANDROID_BOOT_IMAGE - struct andr_img_hdr *hdr; - - hdr = (void *)env_get_ulong("android_addr_r", 16, 0); - if (hdr && !android_image_check_header(hdr) && hdr->header_version >= 4) { - if (env_update_extract_subset("bootargs", "andr_bootargs", "androidboot.")) - printf("extract androidboot.xxx error\n"); - if (dump) - printf("## bootargs(android): %s\n\n", env_get("andr_bootargs")); - } -#endif bootargs = env_get("bootargs"); - if (dump) + if (verbose) printf("## bootargs(merged): %s\n\n", bootargs); return (char *)bootargs; diff --git a/u-boot/arch/arm/mach-rockchip/fit_nodes.sh b/u-boot/arch/arm/mach-rockchip/fit_nodes.sh index 4d39ea0554..9639a06e1c 100755 --- a/u-boot/arch/arm/mach-rockchip/fit_nodes.sh +++ b/u-boot/arch/arm/mach-rockchip/fit_nodes.sh @@ -347,6 +347,10 @@ if grep -q '^CONFIG_FIT_ENABLE_RSA4096_SUPPORT=y' .config ; then else ALGO_NAME=" algo = \"sha256,rsa2048\";" fi +if [ -z "${LOADABLE_ATF}" ]; then + LOADABLE_UBOOT="\"uboot\"" +fi + echo " }; configurations { diff --git a/u-boot/arch/arm/mach-rockchip/memblk.c b/u-boot/arch/arm/mach-rockchip/memblk.c index efbde42625..ac7c2a8957 100644 --- a/u-boot/arch/arm/mach-rockchip/memblk.c +++ b/u-boot/arch/arm/mach-rockchip/memblk.c @@ -41,7 +41,7 @@ const static struct memblk_attr plat_mem_attr[MEM_MAX] = { MEM_DEFINE(ANDROID, F_HOFC | F_OFC | F_KMEM_CAN_OVERLAP), MEM_DEFINE(FDT, F_OFC), MEM_DEFINE(FDT_DTBO, F_OFC), - MEM_DEFINE_1(SHM, F_NONE, "ramoops"), + MEM_DEFINE_2(SHM, F_NONE, "ramoops", "minidump"), MEM_DEFINE_2(RAMDISK, F_OFC, "boot", "recovery"), MEM_DEFINE(UNCOMP_KERNEL,F_IGNORE_INVISIBLE), MEM_DEFINE(FIT_USER, F_OFC | F_KMEM_CAN_OVERLAP), diff --git a/u-boot/arch/arm/mach-rockchip/pstore.c b/u-boot/arch/arm/mach-rockchip/pstore.c index 18e452c938..4f0df73dac 100644 --- a/u-boot/arch/arm/mach-rockchip/pstore.c +++ b/u-boot/arch/arm/mach-rockchip/pstore.c @@ -138,15 +138,18 @@ void putc_to_ram(const char c) if (!rb || pstore_size == 0) return; + if (rb->start >= pstore_size) + rb->start = 0; + dst = rb->data + rb->start; *dst = c; if (rb->size < pstore_size) rb->size++; + else + rb->size = pstore_size; rb->start++; - if (rb->start >= pstore_size) - rb->start = 0; } void puts_to_ram(const char *str) diff --git a/u-boot/arch/arm/mach-rockchip/rk3308/rk3308.c b/u-boot/arch/arm/mach-rockchip/rk3308/rk3308.c index bc271015d3..95556c6e54 100644 --- a/u-boot/arch/arm/mach-rockchip/rk3308/rk3308.c +++ b/u-boot/arch/arm/mach-rockchip/rk3308/rk3308.c @@ -187,6 +187,10 @@ int rk_board_init(void) #define QOS_PRIORITY_P1_P0(p1, p0) ((((p1) & 0x3) << 8) |\ (((p0) & 0x3) << 0)) +#define CRU_CLKGATE_CON10 0x0328 +#define CRU_CLKGATE_CON11 0x032c +#define CRU_CLKGATE_CON12 0x0330 + enum { IOVSEL4_SHIFT = 4, IOVSEL4_MASK = BIT(4), @@ -202,6 +206,18 @@ int arch_cpu_init(void) /* Set CRYPTO SDMMC EMMC NAND SFC USB master bus to be secure access */ rk_clrreg(&sgrf->con_secure0, 0x2b83); +#else /* uboot */ + + /* + * Gate I2Sx_MCLK default + * + * It's safe to gate mclk default to avoid high freq glitch + * which may make devices work unexpected. And then enabled by + * kernel stage or any state where user use it. + */ + writel(0x80008000, CRU_BASE + CRU_CLKGATE_CON10); + writel(0x88888888, CRU_BASE + CRU_CLKGATE_CON11); + writel(0x88888888, CRU_BASE + CRU_CLKGATE_CON12); #endif #else /* defined(CONFIG_TPL_BUILD) */ static struct rk3308_cru * const cru = (void *)CRU_BASE; diff --git a/u-boot/arch/arm/mach-rockchip/rk3562/rk3562.c b/u-boot/arch/arm/mach-rockchip/rk3562/rk3562.c index b678451dd4..0dae0fc003 100644 --- a/u-boot/arch/arm/mach-rockchip/rk3562/rk3562.c +++ b/u-boot/arch/arm/mach-rockchip/rk3562/rk3562.c @@ -96,6 +96,8 @@ DECLARE_GLOBAL_DATA_PTR; #define VICAP_PRIORITY_REG 0xfee70108 #define VOP_PRIORITY_REG 0xfee80008 +#define PCIE_SHAPING_REG 0xfeea0088 + #define QOS_PRIORITY_LEVEL(h, l) ((((h) & 7) << 8) | ((l) & 7)) #ifdef CONFIG_ARM64 @@ -506,16 +508,17 @@ int fit_standalone_release(char *id, uintptr_t entry_point) /* open bus m0 sclk / bus m0 hclk / bus m0 dclk */ writel(0x00070000, TOP_CRU_BASE + TOP_CRU_CM0_GATEMASK); - /* mcu_cache_peripheral_addr */ - writel(0xa0000000, SYS_GRF_BASE + SYS_GRF_SOC_CON5); + /* + * mcu_cache_peripheral_addr + * The uncache area ranges from 0x7c00000 to 0xffb400000 + * and contains rpmsg shared memory + */ + writel(0x07c00000, SYS_GRF_BASE + SYS_GRF_SOC_CON5); writel(0xffb40000, SYS_GRF_BASE + SYS_GRF_SOC_CON6); sip_smc_mcu_config(ROCKCHIP_SIP_CONFIG_BUSMCU_0_ID, ROCKCHIP_SIP_CONFIG_MCU_CODE_START_ADDR, 0xffff0000 | (entry_point >> 16)); - /* 0x07c00000 is mapped to 0xa0000000 and used as shared memory for rpmsg */ - sip_smc_mcu_config(ROCKCHIP_SIP_CONFIG_BUSMCU_0_ID, - ROCKCHIP_SIP_CONFIG_MCU_EXPERI_START_ADDR, 0xffff07c0); /* release dcache / icache / bus m0 jtag / bus m0 */ writel(0x03280000, TOP_CRU_BASE + TOP_CRU_SOFTRST_CON23); @@ -532,7 +535,7 @@ static void qos_priority_init(void) u32 delay; u32 i; - /* power up vo,vi,gpu */ + /* power up vo,vi */ rk_clrreg(PMU_BASE_ADDR + PMU2_PWR_GATE_SFTCON0, PD_VO_DWN_SFTENA | PD_VI_DWN_SFTENA); delay = 1000; @@ -605,6 +608,8 @@ static void qos_priority_init(void) writel(QOS_PRIORITY_LEVEL(2, 2), DCF_PRIORITY_REG); writel(QOS_PRIORITY_LEVEL(2, 2), DMA2DDR_PRIORITY_REG); writel(QOS_PRIORITY_LEVEL(2, 2), PCIE_PRIORITY_REG); + + writel(0x5, PCIE_SHAPING_REG); } int arch_cpu_init(void) @@ -631,6 +636,13 @@ int arch_cpu_init(void) /* Assert reset the pipe phy to save power and de-assert when in use */ writel(0x00030001, PIPEPHY_GRF_BASE + PIPEPHY_PIPE_CON5); +#if defined(CONFIG_SUPPORT_USBPLUG) + /* Set emmc iomux */ + writel(0xffff1111, GPIO1_IOC_BASE + GPIO1A_IOMUX_SEL_L); + writel(0xffff1111, GPIO1_IOC_BASE + GPIO1A_IOMUX_SEL_H); + writel(0xffff1111, GPIO1_IOC_BASE + GPIO1B_IOMUX_SEL_L); +#endif + #if defined(CONFIG_ROCKCHIP_SFC) /* Set the fspi to access ddr memory */ val = readl(FIREWALL_DDR_BASE + FW_DDR_MST5_REG); diff --git a/u-boot/arch/arm/mach-rockchip/rk3588/rk3588.c b/u-boot/arch/arm/mach-rockchip/rk3588/rk3588.c index 678d558fc9..78ae302f23 100644 --- a/u-boot/arch/arm/mach-rockchip/rk3588/rk3588.c +++ b/u-boot/arch/arm/mach-rockchip/rk3588/rk3588.c @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -58,10 +59,14 @@ DECLARE_GLOBAL_DATA_PTR; #define BUS_IOC_BASE 0xfd5f8000 #define BUS_IOC_GPIO2A_IOMUX_SEL_L 0x40 +#define BUS_IOC_GPIO2A_IOMUX_SEL_H 0x44 #define BUS_IOC_GPIO2B_IOMUX_SEL_L 0x48 +#define BUS_IOC_GPIO2B_IOMUX_SEL_H 0x4c #define BUS_IOC_GPIO2D_IOMUX_SEL_L 0x58 #define BUS_IOC_GPIO2D_IOMUX_SEL_H 0x5c #define BUS_IOC_GPIO3A_IOMUX_SEL_L 0x60 +#define BUS_IOC_GPIO3A_IOMUX_SEL_H 0x64 +#define BUS_IOC_GPIO3C_IOMUX_SEL_H 0x74 #define VCCIO3_5_IOC_BASE 0xfd5fa000 #define IOC_VCCIO3_5_GPIO2A_DS_H 0x44 @@ -110,7 +115,13 @@ static struct mm_region rk3588_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN - }, { + }, { + .virt = 0x100000000UL, + .phys = 0x100000000UL, + .size = 0x700000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { .virt = 0x900000000, .phys = 0x900000000, .size = 0x150000000, @@ -844,6 +855,57 @@ void spl_board_storages_fixup(struct spl_image_loader *loader) } #endif +void board_set_iomux(enum if_type if_type, int devnum, int routing) +{ + switch (if_type) { + case IF_TYPE_MMC: + /* + * set the emmc io drive strength: + * data and cmd: 50ohm + * clock: 25ohm + */ + writel(0x00770052, EMMC_IOC_BASE + EMMC_IOC_GPIO2A_DS_L); + writel(0x77772222, EMMC_IOC_BASE + EMMC_IOC_GPIO2D_DS_L); + writel(0x77772222, EMMC_IOC_BASE + EMMC_IOC_GPIO2D_DS_H); + + /* set emmc iomux */ + writel(0xffff1111, BUS_IOC_BASE + BUS_IOC_GPIO2A_IOMUX_SEL_L); + writel(0xffff1111, BUS_IOC_BASE + BUS_IOC_GPIO2D_IOMUX_SEL_L); + writel(0xffff1111, BUS_IOC_BASE + BUS_IOC_GPIO2D_IOMUX_SEL_H); + break; + + case IF_TYPE_MTD: + if (routing == 0) { + writel(0x000f0002, BUS_IOC_BASE + BUS_IOC_GPIO2A_IOMUX_SEL_L); + writel(0xffff2222, BUS_IOC_BASE + BUS_IOC_GPIO2D_IOMUX_SEL_L); + writel(0x00f00020, BUS_IOC_BASE + BUS_IOC_GPIO2D_IOMUX_SEL_H); + /* Set the fspi m0 io ds level to 55ohm */ + writel(0x00070002, EMMC_IOC_BASE + EMMC_IOC_GPIO2A_DS_L); + writel(0x77772222, EMMC_IOC_BASE + EMMC_IOC_GPIO2D_DS_L); + writel(0x07000200, EMMC_IOC_BASE + EMMC_IOC_GPIO2D_DS_H); + } else if (routing == 1) { + writel(0xff003300, BUS_IOC_BASE + BUS_IOC_GPIO2A_IOMUX_SEL_H); + writel(0xf0ff3033, BUS_IOC_BASE + BUS_IOC_GPIO2B_IOMUX_SEL_L); + writel(0x000f0003, BUS_IOC_BASE + BUS_IOC_GPIO2B_IOMUX_SEL_H); + /* Set the fspi m1 io ds level to 55ohm */ + writel(0x33002200, VCCIO3_5_IOC_BASE + IOC_VCCIO3_5_GPIO2A_DS_H); + writel(0x30332022, VCCIO3_5_IOC_BASE + IOC_VCCIO3_5_GPIO2B_DS_L); + writel(0x00030002, VCCIO3_5_IOC_BASE + IOC_VCCIO3_5_GPIO2B_DS_H); + } else if (routing == 2) { + writel(0xffff5555, BUS_IOC_BASE + BUS_IOC_GPIO3A_IOMUX_SEL_L); + writel(0x00f00050, BUS_IOC_BASE + BUS_IOC_GPIO3A_IOMUX_SEL_H); + writel(0x00ff0022, BUS_IOC_BASE + BUS_IOC_GPIO3C_IOMUX_SEL_H); + /* Set the fspi m2 io ds level to 55ohm */ + writel(0x77772222, VCCIO3_5_IOC_BASE + IOC_VCCIO3_5_GPIO3A_DS_L); + writel(0x00700020, VCCIO3_5_IOC_BASE + IOC_VCCIO3_5_GPIO3A_DS_H); + writel(0x00070002, VCCIO3_5_IOC_BASE + IOC_VCCIO3_5_GPIO3C_DS_H); + } + break; + default: + break; + } +} + #ifndef CONFIG_TPL_BUILD int arch_cpu_init(void) { @@ -939,6 +1001,41 @@ int arch_cpu_init(void) writel(0x00030003, PMU1CRU_BASE + PMU1CRU_SOFTRST_CON04); spl_board_sd_iomux_save(); +#elif defined(CONFIG_SUPPORT_USBPLUG) + int secure_reg; + + /* Set the SDMMC eMMC crypto_ns FSPI access secure area */ + secure_reg = readl(FIREWALL_DDR_BASE + FW_DDR_MST5_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_DDR_BASE + FW_DDR_MST5_REG); + secure_reg = readl(FIREWALL_DDR_BASE + FW_DDR_MST13_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_DDR_BASE + FW_DDR_MST13_REG); + secure_reg = readl(FIREWALL_DDR_BASE + FW_DDR_MST21_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_DDR_BASE + FW_DDR_MST21_REG); + secure_reg = readl(FIREWALL_DDR_BASE + FW_DDR_MST26_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_DDR_BASE + FW_DDR_MST26_REG); + secure_reg = readl(FIREWALL_DDR_BASE + FW_DDR_MST27_REG); + secure_reg &= 0xffff0000; + writel(secure_reg, FIREWALL_DDR_BASE + FW_DDR_MST27_REG); + + secure_reg = readl(FIREWALL_SYSMEM_BASE + FW_SYSM_MST5_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_SYSMEM_BASE + FW_SYSM_MST5_REG); + secure_reg = readl(FIREWALL_SYSMEM_BASE + FW_SYSM_MST13_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_SYSMEM_BASE + FW_SYSM_MST13_REG); + secure_reg = readl(FIREWALL_SYSMEM_BASE + FW_SYSM_MST21_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_SYSMEM_BASE + FW_SYSM_MST21_REG); + secure_reg = readl(FIREWALL_SYSMEM_BASE + FW_SYSM_MST26_REG); + secure_reg &= 0xffff; + writel(secure_reg, FIREWALL_SYSMEM_BASE + FW_SYSM_MST26_REG); + secure_reg = readl(FIREWALL_SYSMEM_BASE + FW_SYSM_MST27_REG); + secure_reg &= 0xffff0000; + writel(secure_reg, FIREWALL_SYSMEM_BASE + FW_SYSM_MST27_REG); #else /* U-Boot */ /* uboot: config iomux */ #ifdef CONFIG_ROCKCHIP_EMMC_IOMUX @@ -966,12 +1063,24 @@ int arch_cpu_init(void) #define BAD_CPU(mask, n) ((mask) & (1 << (n))) #define BAD_RKVENC(mask, n) ((mask) & (1 << (n))) +#define BAD_RKVDEC(mask, n) ((mask) & (1 << (n))) static void fdt_rm_path(void *blob, const char *path) { fdt_del_node(blob, fdt_path_offset(blob, path)); } +static void fdt_rename_path(void *blob, const char *path, const char *name) +{ + int noffset; + + noffset = fdt_path_offset(blob, path); + if (noffset < 0) + return; + + fdt_set_name(blob, noffset, name); +} + static void fdt_rm_cooling_map(const void *blob, u8 cpu_mask) { int map1, map2; @@ -1104,7 +1213,7 @@ static void fdt_rm_cpu(const void *blob, u8 cpu_mask) } } -static void fdt_rm_cpus(const void *blob, u8 cpu_mask) +static void rk3582_fdt_rm_cpus(const void *blob, u8 cpu_mask) { /* * policy: @@ -1127,7 +1236,7 @@ static void fdt_rm_cpus(const void *blob, u8 cpu_mask) fdt_rm_cpu(blob, cpu_mask); } -static void fdt_rm_gpu(void *blob) +static void rk3582_fdt_rm_gpu(void *blob) { /* * policy: @@ -1139,7 +1248,7 @@ static void fdt_rm_gpu(void *blob) debug("rm: gpu\n"); } -static void fdt_rm_rkvdec01(void *blob) +static void rk3582_fdt_rm_rkvdec01(void *blob) { /* * policy: @@ -1153,13 +1262,15 @@ static void fdt_rm_rkvdec01(void *blob) debug("rm: rkvdec0, rkvdec1\n"); } -static void fdt_rm_rkvenc01(void *blob, u8 mask) +static void rk3582_fdt_rm_rkvenc01(void *blob, u8 mask) { /* * policy: * * 1. remove bad. * 2. if both of rkvenc0 and rkvenc1 are normal, remove rkvenc1 by default. + * 3. disable '*-ccu' node + * 4. rename '*-core@' node */ if (!BAD_RKVENC(mask, 0) && !BAD_RKVENC(mask, 1)) { /* rkvenc1 */ @@ -1179,6 +1290,50 @@ static void fdt_rm_rkvenc01(void *blob, u8 mask) debug("rm: rkvenv1\n"); } } + + do_fixup_by_path((void *)blob, "/rkvenc-ccu", + "status", "disabled", sizeof("disabled"), 0); + + /* rename node name if the node exist, actually only one exist */ + fdt_rename_path(blob, "/rkvenc-core@fdbd0000", "rkvenc@fdbd0000"); + fdt_rename_path(blob, "/rkvenc-core@fdbe0000", "rkvenc@fdbe0000"); +} + +static void rk3583_fdt_rm_rkvdec01(void *blob, u8 mask) +{ + /* + * policy: + * + * 1. remove bad. + * 2. if both of rkvdec0 and rkvdec1 are normal, remove rkvdec1 by default. + * 3. disable '*-ccu' node + * 4. rename '*-core@' node + */ + if (!BAD_RKVDEC(mask, 0) && !BAD_RKVDEC(mask, 1)) { + /* rkvdec1 */ + fdt_rm_path(blob, "/rkvdec-core@fdc48000"); + fdt_rm_path(blob, "/iommu@fdc48700"); + debug("rm: rkvdec1\n"); + } else { + if (BAD_RKVDEC(mask, 0)) { + fdt_rm_path(blob, "/rkvdec-core@fdc38000"); + fdt_rm_path(blob, "/iommu@fdc38700"); + debug("rm: rkvdec0\n"); + + } + if (BAD_RKVDEC(mask, 1)) { + fdt_rm_path(blob, "/rkvdec-core@fdc48000"); + fdt_rm_path(blob, "/iommu@fdc48700"); + debug("rm: rkvdec1\n"); + } + } + + do_fixup_by_path((void *)blob, "/rkvdec-ccu@fdc30000", + "status", "disabled", sizeof("disabled"), 0); + + /* rename node name if the node exist, actually only one exist */ + fdt_rename_path(blob, "/rkvdec-core@fdc38000", "rkvdec@fdc38000"); + fdt_rename_path(blob, "/rkvdec-core@fdc48000", "rkvdec@fdc48000"); } #define CHIP_ID_OFF 2 @@ -1190,6 +1345,7 @@ static int fdt_fixup_modules(void *blob) u8 ip_state[3]; u8 chip_id[2]; u8 rkvenc_mask; + u8 rkvdec_mask; u8 cpu_mask; int ret; @@ -1208,8 +1364,9 @@ static int fdt_fixup_modules(void *blob) debug("# chip: rk%02x%02x\n", chip_id[0], chip_id[1]); - /* only rk3582 goes further */ - if (!(chip_id[0] == 0x35 && chip_id[1] == 0x82)) + /* only rk3582/rk3583 goes further */ + if (!(chip_id[0] == 0x35 && chip_id[1] == 0x82) && + !(chip_id[0] == 0x35 && chip_id[1] == 0x83)) return 0; ret = misc_read(dev, IP_STATE_OFF, &ip_state, sizeof(ip_state)); @@ -1222,33 +1379,42 @@ static int fdt_fixup_modules(void *blob) cpu_mask = ip_state[0]; /* ip_state[2]: bit0,2 */ rkvenc_mask = (ip_state[2] & 0x1) | ((ip_state[2] & 0x4) >> 1); + /* ip_state[1]: bit6,7 */ + rkvdec_mask = (ip_state[1] & 0xc0) >> 6; #if 0 /* ip_state[1]: bit1~4 */ gpu_mask = (ip_state[1] & 0x1e) >> 1; - /* ip_state[1]: bit6,7 */ - rkvdec_mask = (ip_state[1] & 0xc0) >> 6; #endif - - debug("hwmask: 0x%02x, 0x%02x, 0x%02x\n", ip_state[0], ip_state[1], ip_state[2]); - debug("swmask: 0x%02x, 0x%02x\n", cpu_mask, rkvenc_mask); + debug("hw-mask: 0x%02x, 0x%02x, 0x%02x\n", ip_state[0], ip_state[1], ip_state[2]); + debug("sw-mask: 0x%02x, 0x%02x, 0x%02x\n", cpu_mask, rkvenc_mask, rkvdec_mask); /* - * RK3582 Policy: gpu/rkvdec are removed by default, the same for other - * IP under some condition. - * - * So don't use pattern like "if (rkvenc_mask) then fdt_rm_rkvenc01()", - * just go through all of them as this chip is rk3582. - * * FIXUP WARNING! * * The node delete changes the fdt structure, a node offset you already * got before maybe not right by now. Make sure always reading the node * offset exactly before you are going to use. */ - fdt_rm_gpu(blob); - fdt_rm_rkvdec01(blob); - fdt_rm_rkvenc01(blob, rkvenc_mask); - fdt_rm_cpus(blob, cpu_mask); + if (chip_id[0] == 0x35 && chip_id[1] == 0x82) { + /* + * RK3582 Policy: gpu/rkvdec are removed by default, the same for other + * IP under some condition. + * + * So don't use pattern like "if (rkvenc_mask) then rk3582_fdt_rm_rkvenc01()", + * just go through all of them as this chip is rk3582. + */ + rk3582_fdt_rm_gpu(blob); + rk3582_fdt_rm_rkvdec01(blob); + rk3582_fdt_rm_rkvenc01(blob, rkvenc_mask); + rk3582_fdt_rm_cpus(blob, cpu_mask); + } else if (chip_id[0] == 0x35 && chip_id[1] == 0x83) { + /* + * RK3583 Policy: some rules are the same as rk3582. + */ + rk3583_fdt_rm_rkvdec01(blob, rkvdec_mask); + rk3582_fdt_rm_rkvenc01(blob, rkvenc_mask); + rk3582_fdt_rm_cpus(blob, cpu_mask); + } return 0; } diff --git a/u-boot/arch/arm/mach-rockchip/rk_atags.c b/u-boot/arch/arm/mach-rockchip/rk_atags.c index 26f8507011..37f8a974c7 100644 --- a/u-boot/arch/arm/mach-rockchip/rk_atags.c +++ b/u-boot/arch/arm/mach-rockchip/rk_atags.c @@ -179,8 +179,9 @@ int atags_is_available(void) int atags_set_tag(u32 magic, void *tagdata) { - u32 length, size = 0, hash; struct tag *t = (struct tag *)ATAGS_PHYS_BASE; + u32 length, size = 0, hash; + int append = 1; /* 0: override */ #if !defined(CONFIG_TPL_BUILD) && !defined(CONFIG_FPGA_ROCKCHIP) if (!atags_is_available()) @@ -216,8 +217,10 @@ int atags_set_tag(u32 magic, void *tagdata) return -EINVAL; /* This is an old tag, override it */ - if (t->hdr.magic == magic) + if (t->hdr.magic == magic) { + append = 0; break; + } if (t->hdr.magic == ATAG_NONE) break; @@ -256,6 +259,9 @@ int atags_set_tag(u32 magic, void *tagdata) case ATAG_PSTORE: size = tag_size(tag_pstore); break; + case ATAG_FWVER: + size = tag_size(tag_fwver); + break; }; if (!size) @@ -264,7 +270,7 @@ int atags_set_tag(u32 magic, void *tagdata) if (atags_size_overflow(t, size)) return -ENOMEM; - /* It's okay to setup a new tag */ + /* It's okay to setup a new tag or override tag */ t->hdr.magic = magic; t->hdr.size = size; length = (t->hdr.size << 2) - sizeof(struct tag_header) - HASH_LEN; @@ -272,17 +278,41 @@ int atags_set_tag(u32 magic, void *tagdata) hash = js_hash(t, (size << 2) - HASH_LEN); memcpy((char *)&t->u + length, &hash, HASH_LEN); - /* Next tag */ - t = tag_next(t); + if (append) { + /* Next tag */ + t = tag_next(t); - /* Setup done */ - t->hdr.magic = ATAG_NONE; - t->hdr.size = 0; + /* Setup done */ + t->hdr.magic = ATAG_NONE; + t->hdr.size = 0; + } return 0; } #ifndef CONFIG_TPL_BUILD +int atags_set_shared_fwver(u32 fwid, char *ver) +{ + struct tag_fwver fw = {}, *pfw; + struct tag *t; + + if (!ver || (strlen(ver) >= FWVER_LEN) || fwid >= FW_MAX) + return -EINVAL; + + t = atags_get_tag(ATAG_FWVER); + if (!t) { + pfw = &fw; + pfw->version = 0; + } else { + pfw = &t->u.fwver; + } + + strcpy(pfw->ver[fwid], ver); + atags_set_tag(ATAG_FWVER, pfw); + + return 0; +} + struct tag *atags_get_tag(u32 magic) { u32 *hash, calc_hash, size; diff --git a/u-boot/arch/arm/mach-rockchip/rk_mini_dump.c b/u-boot/arch/arm/mach-rockchip/rk_mini_dump.c new file mode 100644 index 0000000000..ef52b76057 --- /dev/null +++ b/u-boot/arch/arm/mach-rockchip/rk_mini_dump.c @@ -0,0 +1,535 @@ +/* + * (C) Copyright 2023 Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +/* don't modify it, it is behind pstore memory space */ +#ifdef CONFIG_ROCKCHIP_MINIDUMP_SMEM_BASE +#define SMEM_BASE CONFIG_ROCKCHIP_MINIDUMP_SMEM_BASE +#else +#define SMEM_BASE 0x1f0000 +#endif + +#ifdef CONFIG_ROCKCHIP_MINIDUMP_MAX_ELF_SIZE +#define MAX_ELF_SIZE CONFIG_ROCKCHIP_MINIDUMP_MAX_ELF_SIZE +#else +#define MAX_ELF_SIZE 0x2000000 +#endif + +#ifdef CONFIG_ROCKCHIP_MINIDUMP_MAX_ENTRIES +#define MAX_NUM_ENTRIES (CONFIG_ROCKCHIP_MINIDUMP_MAX_ENTRIES + 1) +#else +#define MAX_NUM_ENTRIES 129 +#endif + +/* Bootloader has 16 byte support, 4 bytes reserved for itself */ +#define MAX_REGION_NAME_LENGTH 16 +#define MAX_STRTBL_SIZE (MAX_NUM_ENTRIES * MAX_REGION_NAME_LENGTH) + +/** + * md_table : Local Minidump toc holder + * @num_regions : Number of regions requested + * @md_ss_toc : HLOS toc pointer + * @md_gbl_toc : Global toc pointer + * @md_regions : HLOS regions base pointer + * @entry : array of HLOS regions requested + */ +struct md_table { + u32 revision; + u32 num_regions; + struct md_ss_toc *md_ss_toc; + struct md_global_toc *md_gbl_toc; + struct md_ss_region *md_regions; + struct md_region entry[MAX_NUM_ENTRIES]; +}; + +#define MAX_NUM_OF_SS 2 + +/** + * md_ss_toc: Sub system SMEM Table of content + * @md_ss_toc_init : SS toc init status + * @md_ss_enable_status : if set to 1, Bootloader would dump this SS regions + * @encryption_status: Encryption status for this subsystem + * @encryption_required : Decides to encrypt the SS regions or not + * @ss_region_count : Number of regions added in this SS toc + * @md_ss_smem_regions_baseptr : regions base pointer of the Subsystem + * @elf_header : base pointer of the minidump elf header + * @minidump_table : base pointer of the minidump_table + */ +struct md_ss_toc { + u32 md_ss_toc_init; + u32 md_ss_enable_status; + u32 encryption_status; + u32 encryption_required; + u32 ss_region_count; + u64 md_ss_smem_regions_baseptr; + u64 elf_header; + u64 elf_size; + u64 minidump_table; +}; + +/** + * md_global_toc: Global Table of Content + * @md_toc_init : Global Minidump init status + * @md_revision : Minidump revision + * @md_enable_status : Minidump enable status + * @md_ss_toc : Array of subsystems toc + */ +struct md_global_toc { + u32 md_toc_init; + u32 md_revision; + u32 md_enable_status; + struct md_ss_toc md_ss_toc[MAX_NUM_OF_SS]; +}; + +/* Bootloader has 16 byte support, 4 bytes reserved for itself */ +#define MAX_REGION_NAME_LENGTH 16 + +#define MD_REGION_VALID ('V' << 24 | 'A' << 16 | 'L' << 8 | 'I' << 0) +#define MD_REGION_INVALID ('I' << 24 | 'N' << 16 | 'V' << 8 | 'A' << 0) +#define MD_REGION_INIT ('I' << 24 | 'N' << 16 | 'I' << 8 | 'T' << 0) +#define MD_REGION_NOINIT 0 + +#define MD_SS_ENCR_REQ (0 << 24 | 'Y' << 16 | 'E' << 8 | 'S' << 0) +#define MD_SS_ENCR_NOTREQ (0 << 24 | 0 << 16 | 'N' << 8 | 'R' << 0) +#define MD_SS_ENCR_NONE ('N' << 24 | 'O' << 16 | 'N' << 8 | 'E' << 0) +#define MD_SS_ENCR_DONE ('D' << 24 | 'O' << 16 | 'N' << 8 | 'E' << 0) +#define MD_SS_ENCR_START ('S' << 24 | 'T' << 16 | 'R' << 8 | 'T' << 0) +#define MD_SS_ENABLED ('E' << 24 | 'N' << 16 | 'B' << 8 | 'L' << 0) +#define MD_SS_DISABLED ('D' << 24 | 'S' << 16 | 'B' << 8 | 'L' << 0) + +#define EM_AARCH64 183 /* ARM 64 bit */ + +/** + * md_ss_region - Minidump region + * @name : Name of the region to be dumped + * @seq_num: : Use to differentiate regions with same name. + * @md_valid : This entry to be dumped (if set to 1) + * @region_base_address : Physical address of region to be dumped + * @region_size : Size of the region + */ +struct md_ss_region { + char name[MAX_REGION_NAME_LENGTH]; + u32 seq_num; + u32 md_valid; + u64 region_base_address; + u64 region_size; +}; + +#define NO_FAULT_TAG 0x55aa55aa +static u32 no_fault; +static struct md_table *minidump_table; + +u32 md_no_fault_handler(struct pt_regs *pt_regs, unsigned int esr) +{ + if (no_fault == NO_FAULT_TAG) { + no_fault = 0; + return 1; + } + return 0; +} + +#if defined(CONFIG_ROCKCHIP_RK3588) +static u32 md_is_ddr_addr(void *addr) +{ + /* peripheral address space */ + if (addr >= (void *)0xf0000000 && addr <= (void *)0x100000000) + return 0; + /* pcie address space */ + if (addr > (void *)0x800000000) + return 0; + return 1; +} +#else +static u32 md_is_ddr_addr(void *addr) +{ + return 1; +} +#endif + +static u32 md_is_uboot_addr(void *addr) +{ + volatile u32 *p_no_fault = &no_fault; + + if(!md_is_ddr_addr(addr)) + return 0; + + *p_no_fault = NO_FAULT_TAG; + readb(addr); + return *p_no_fault; +} + +struct md_region *md_get_region(char *name) +{ + struct md_region *mdr; + int i, regno; + + if (!md_is_uboot_addr((void *)minidump_table)) + return NULL; + + regno = minidump_table->num_regions; + for (i = 0; i < regno; i++) { + mdr = &minidump_table->entry[i]; + if (!strcmp(mdr->name, name)) + return mdr; + } + return NULL; +} + +#ifdef CONFIG_ARM64 +static Elf64_Xword rk_dump_elf64_image_phdr(void *ram_image, + Elf64_Addr ehaddr, Elf64_Xword ehsize) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)ehaddr; + Elf64_Phdr *phdr = NULL, *phdr_next = NULL; + Elf64_Shdr *shdr = NULL, *shdr_next = NULL; + unsigned int i = 0, error = 0, phdr_off = 0, strtbl_off = 0; + unsigned int size = 0, elf_size = ehsize; + + if (!md_is_uboot_addr((void *)ehdr)) + return 0; + + if (!md_is_uboot_addr((void *)ram_image) || + !md_is_uboot_addr((void *)ram_image + MAX_ELF_SIZE - 4)) + return 0; + + memcpy(ehdr->e_ident, ELFMAG, SELFMAG); + ehdr->e_ident[EI_CLASS] = ELFCLASS64; + ehdr->e_ident[EI_DATA] = ELFDATA2LSB; + ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; + + if (ehdr->e_type != ET_CORE) { + error++; + ehdr->e_type = ET_CORE; + } + if (ehdr->e_machine != EM_AARCH64) { + error++; + ehdr->e_machine = EM_AARCH64; + } + if (ehdr->e_version != EV_CURRENT) { + error++; + ehdr->e_version = EV_CURRENT; + } + if (ehdr->e_ehsize != sizeof(*ehdr)) { + error++; + ehdr->e_ehsize = sizeof(*ehdr); + } + if (ehdr->e_phentsize != sizeof(*phdr)) { + error++; + ehdr->e_phentsize = sizeof(*phdr); + } + if (ehdr->e_shentsize != sizeof(*shdr)) { + error++; + ehdr->e_shentsize = sizeof(*shdr); + } + if (ehdr->e_shoff != sizeof(*ehdr)) { + error++; + ehdr->e_shoff = sizeof(*ehdr); + } + + phdr_off = sizeof(*ehdr) + (sizeof(*shdr) * MAX_NUM_ENTRIES); + + if (ehdr->e_phoff != phdr_off) { + error++; + ehdr->e_phoff = phdr_off; + } + + printf("Minidump header error:0x%x\n", error); + /* If there are much error, maybe ehdr address is wrong */ + if (error > 6) + return 0; + + ehdr->e_shstrndx = 1; + phdr = (Elf64_Phdr *)(ehaddr + ehdr->e_phoff); + shdr = (Elf64_Shdr *)(ehaddr + ehdr->e_shoff); + + shdr->sh_name = 0; + shdr->sh_type = 0; + shdr->sh_flags = 0; + shdr->sh_addr = 0; + shdr->sh_offset = 0; + shdr->sh_size = 0; + shdr->sh_link = 0; + shdr->sh_info = 0; + shdr->sh_addralign = 0; + shdr->sh_entsize = 0; + + shdr++; + if (shdr->sh_name >= MAX_STRTBL_SIZE) + shdr->sh_name = 0; + shdr->sh_type = SHT_STRTAB; + shdr->sh_flags = 0; + shdr->sh_addr = 0; + shdr->sh_offset = phdr_off + (sizeof(*phdr) * MAX_NUM_ENTRIES); + shdr->sh_size = MAX_STRTBL_SIZE; + shdr->sh_link = 0; + shdr->sh_info = 0; + shdr->sh_addralign = 0; + shdr->sh_entsize = 0; + + shdr++; + /* 3rd section is for minidump_table VA, used by parsers */ + if (shdr->sh_name >= MAX_STRTBL_SIZE) + shdr->sh_name = 0; + shdr->sh_type = SHT_PROGBITS; + shdr->sh_flags = 0; + shdr->sh_offset = 0; + shdr->sh_size = 0; + shdr->sh_link = 0; + shdr->sh_info = 0; + shdr->sh_addralign = 0; + shdr->sh_entsize = 0; + + shdr++; + shdr->sh_flags = 0; + shdr->sh_link = 0; + shdr->sh_info = 0; + shdr->sh_addralign = 0; + shdr->sh_entsize = 0; + + strtbl_off = phdr_off + (sizeof(*phdr) * MAX_NUM_ENTRIES); + strtbl_off += MAX_STRTBL_SIZE; + + if (phdr->p_offset != strtbl_off) + phdr->p_offset = strtbl_off; + if (shdr->sh_offset != strtbl_off) + shdr->sh_offset = strtbl_off; + + phdr->p_filesz &= GENMASK(23, 0); /* 16MB */ + phdr->p_memsz &= GENMASK(23, 0); /* 16MB */ + shdr->sh_size &= GENMASK(23, 0); /* 16MB */ + + if (phdr->p_filesz == phdr->p_memsz) { + size = phdr->p_filesz; + shdr->sh_size = size; + } else if (phdr->p_filesz == shdr->sh_size) { + size = phdr->p_filesz; + phdr->p_memsz = size; + } else if (phdr->p_memsz == shdr->sh_size) { + size = phdr->p_memsz; + phdr->p_filesz = size; + } else { + printf("Minidump error first phdr p_filesz:0x%llx p_memsz:0x%llx sh_size:0x%llx\n", + phdr->p_filesz, phdr->p_memsz, shdr->sh_size); + return 0; + } + + phdr++; + shdr++; + phdr_next = phdr + 1; + shdr_next = shdr + 1; + + memset(ram_image, 0x0, 0x18000); + + phdr->p_offset &= MAX_ELF_SIZE - 1; + shdr->sh_offset &= MAX_ELF_SIZE - 1; + elf_size &= MAX_ELF_SIZE - 1; + if (phdr->p_offset == shdr->sh_offset) { + elf_size = phdr->p_offset; + } else if (phdr->p_offset == elf_size) { + shdr->sh_offset = phdr->p_offset; + } else if (elf_size == shdr->sh_offset) { + phdr->p_offset = shdr->sh_offset; + } else { + printf("Minidump error phdr[1] p_offset:0x%llx sh_offset:0x%llx elf_size:0x%x\n", + phdr->p_offset, shdr->sh_offset, elf_size); + return 0; + } + + /* save phdr space */ + for (i = 1; i < MAX_NUM_ENTRIES; i++) { + void *src = NULL; + void *dst = NULL; + + if (phdr->p_vaddr == 0 || shdr->sh_addr == 0) + break; + + phdr->p_offset &= MAX_ELF_SIZE - 1; + shdr->sh_offset &= MAX_ELF_SIZE - 1; + + if (phdr->p_offset != elf_size) + phdr->p_offset = elf_size; + + if (shdr->sh_offset != elf_size) + shdr->sh_offset = elf_size; + + phdr->p_paddr &= GENMASK(34, 0); /* 32GB */ + phdr->p_align &= GENMASK(34, 0); /* 32GB */ + shdr->sh_info &= GENMASK(34, 0); /* 32GB */ + + if (phdr->p_paddr != phdr->p_align && phdr->p_align == shdr->sh_entsize) + phdr->p_paddr = phdr->p_align; + + phdr->p_type &= 0xf; + phdr->p_flags &= 0xf; + phdr->p_filesz &= GENMASK(23, 0); /* 16MB */ + phdr->p_memsz &= GENMASK(23, 0); /* 16MB */ + phdr->p_align = 0; + + if (phdr->p_vaddr != shdr->sh_addr) { + if (shdr->sh_addr == shdr->sh_addralign) + phdr->p_vaddr = shdr->sh_addr; + else if (phdr->p_vaddr == shdr->sh_addralign) + shdr->sh_addr = phdr->p_vaddr; + else + printf("Minidump error phdr[%d] p_vaddr:0x%llx sh_addr:0x%llx sh_addralign:0x%llx\n", + i, phdr->p_vaddr, shdr->sh_addr, shdr->sh_addralign); + } + + if (shdr->sh_name >= MAX_STRTBL_SIZE) + shdr->sh_name = 0; + shdr->sh_type = SHT_PROGBITS; + shdr->sh_flags = SHF_WRITE; + shdr->sh_size &= GENMASK(23, 0); /* 16MB */ + shdr->sh_link = 0; + shdr->sh_info = 0; + shdr->sh_addralign = 0; + shdr->sh_entsize = 0; + + if (phdr->p_filesz == phdr->p_memsz) { + size = phdr->p_filesz; + shdr->sh_size = size; + } else if (phdr->p_filesz == shdr->sh_size) { + size = phdr->p_filesz; + phdr->p_memsz = size; + } else if (phdr->p_memsz == shdr->sh_size) { + size = phdr->p_memsz; + phdr->p_filesz = size; + } else { + if ((phdr_next->p_offset == shdr_next->sh_offset) && + (phdr_next->p_offset != 0)) { + size = phdr_next->p_offset - phdr->p_offset; + phdr->p_filesz = size; + phdr->p_memsz = size; + shdr->sh_size = size; + } else { + printf("Minidump error phdr[%d] p_filesz:0x%llx p_memsz:0x%llx sh_size:0x%llx", + i, phdr->p_filesz, phdr->p_memsz, shdr->sh_size); + printf("p_offset:0x%llx sh_offset:0x%llx\n", phdr_next->p_offset, + shdr_next->sh_offset); + return 0; + } + } + + elf_size += size; + src = (void *)(Elf64_Addr)phdr->p_paddr; + dst = ram_image + phdr->p_offset; + + if (size > MAX_ELF_SIZE / 2) + goto donot_cpy; + + if (!md_is_uboot_addr(src) || !md_is_uboot_addr(src + size - 1)) { + printf("Minidump error src 0x%p-0x%p\n", src, src + size - 1); + goto donot_cpy; + } + if (!md_is_uboot_addr(dst) || !md_is_uboot_addr(dst + size - 1)) { + printf("Minidump error dst 0x%p-0x%p\n", dst, dst + size - 1); + goto donot_cpy; + } + if (size) + memcpy(dst, src, size); +donot_cpy: + phdr++; + shdr++; + phdr_next++; + shdr_next++; + } + + if (ehdr->e_phnum != i) + ehdr->e_phnum = i; + if ((ehdr->e_phnum + 3) != ehdr->e_shnum) + ehdr->e_shnum = ehdr->e_phnum + 3; + + /* copy ehdr to ram image */ + memcpy(ram_image, (void *)ehdr, ehsize); + flush_cache((unsigned long)ram_image, elf_size); + printf("Minidump.elf 0x%x@0x%p\n", elf_size, ram_image); + return elf_size; +} +#else +static Elf32_Word rk_dump_elf32_image_phdr(void *ram_image, Elf32_Addr ehaddr, + Elf32_Word ehsize) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)ehaddr; + Elf32_Phdr *phdr = (Elf32_Phdr *)(ehaddr + ehdr->e_phoff); + Elf32_Word ram_image_size = 0; + int i; + + /* copy ehdr to ram image */ + memcpy(ram_image, (void *)ehdr, ehsize); + + /* save phdr space */ + for (i = 0; i < ehdr->e_phnum; ++i) { + void *src = (void *)(Elf32_Addr)phdr->p_paddr; + void *dst = ram_image + phdr->p_offset; + + if (phdr->p_filesz) + memcpy(dst, src, phdr->p_filesz); + if (phdr->p_filesz != phdr->p_memsz) + memset(dst + phdr->p_filesz, 0x00, + phdr->p_memsz - phdr->p_filesz); + ++phdr; + } + + phdr--; + ram_image_size = phdr->p_memsz + phdr->p_offset; + printf("Minidump.elf 0x%llx@0x%p\n", ram_image_size, ram_image); + return ram_image_size; +} +#endif + +void rk_minidump_init(void) +{ + struct md_global_toc *mdg_toc = (struct md_global_toc *)SMEM_BASE; + struct md_ss_toc *md_ss_toc = &mdg_toc->md_ss_toc[0]; + struct md_ss_region *mdreg; + + printf("Minidump: init...\n"); + mdg_toc->md_toc_init = 1; + mdg_toc->md_revision = 1; + mdg_toc->md_enable_status = 0; + + if (md_ss_toc->md_ss_enable_status == MD_SS_ENABLED) { + /* linux would set it 1, so we set it 0 here */ + md_ss_toc->md_ss_enable_status = 0; + flush_cache((unsigned long)md_ss_toc, 8); + mdreg = (struct md_ss_region *)md_ss_toc->md_ss_smem_regions_baseptr; + minidump_table = (struct md_table *)md_ss_toc->minidump_table; +#ifdef CONFIG_ARM64 + md_ss_toc->elf_size = rk_dump_elf64_image_phdr((void *)md_ss_toc->elf_header, + (Elf64_Addr)mdreg->region_base_address, + (Elf64_Xword)mdreg->region_size); +#else + md_ss_toc->elf_size = rk_dump_elf32_image_phdr((void *)md_ss_toc->elf_header, + (Elf32_Addr)mdreg->region_base_address, + (Elf32_Word)mdreg->region_size); +#endif + } +} + +#ifdef CONFIG_ARM64 +void rk_minidump_get_el64(void **ram_image_addr, Elf64_Xword *ram_image_size) +{ + struct md_global_toc *mdg_toc = (struct md_global_toc *)SMEM_BASE; + struct md_ss_toc *md_ss_toc = &mdg_toc->md_ss_toc[0]; + + *ram_image_addr = (void *)md_ss_toc->elf_header; + *ram_image_size = md_ss_toc->elf_size; +} +#else +void rk_minidump_get_el32(void **ram_image_addr, Elf32_Word *ram_image_size) +{ + struct md_global_toc *mdg_toc = (struct md_global_toc *)SMEM_BASE; + struct md_ss_toc *md_ss_toc = &mdg_toc->md_ss_toc[0]; + + *ram_image_addr = (void *)md_ss_toc->elf_header; + *ram_image_size = md_ss_toc->elf_size; +} +#endif diff --git a/u-boot/arch/arm/mach-rockchip/rv1106/rv1106.c b/u-boot/arch/arm/mach-rockchip/rv1106/rv1106.c index af28e4c33b..5be93f077f 100644 --- a/u-boot/arch/arm/mach-rockchip/rv1106/rv1106.c +++ b/u-boot/arch/arm/mach-rockchip/rv1106/rv1106.c @@ -404,9 +404,32 @@ void board_debug_uart_init(void) #endif } +#ifdef CONFIG_SUPPORT_USBPLUG +void board_set_iomux(enum if_type if_type, int devnum, int routing) +{ + switch (if_type) { + case IF_TYPE_MMC: + /* emmc iomux */ + writel(0xffff1111, GPIO4_IOC_BASE + GPIO4A_IOMUX_SEL_L); + writel(0xffff1111, GPIO4_IOC_BASE + GPIO4A_IOMUX_SEL_H); + writel(0x00ff0011, GPIO4_IOC_BASE + GPIO4B_IOMUX_SEL_L); + break; + case IF_TYPE_MTD: + /* fspi iomux */ + writel(0x0f000700, GPIO4_IOC_BASE + 0x0030); + writel(0xff002200, GPIO4_IOC_BASE + GPIO4A_IOMUX_SEL_L); + writel(0x0f0f0202, GPIO4_IOC_BASE + GPIO4A_IOMUX_SEL_H); + writel(0x00ff0022, GPIO4_IOC_BASE + GPIO4B_IOMUX_SEL_L); + break; + default: + break; + } +} +#endif + int arch_cpu_init(void) { -#ifdef CONFIG_SPL_BUILD +#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_SUPPORT_USBPLUG) /* Save chip version to OS_REG1[2:0] */ if (readl(ROM_VER_REG) == ROM_V2) writel((readl(CHIP_VER_REG) & ~CHIP_VER_MSK) | V(2), CHIP_VER_REG); diff --git a/u-boot/arch/arm/mach-rockchip/spl.c b/u-boot/arch/arm/mach-rockchip/spl.c index 85911687fd..bdb2a7c242 100644 --- a/u-boot/arch/arm/mach-rockchip/spl.c +++ b/u-boot/arch/arm/mach-rockchip/spl.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -153,7 +154,7 @@ void *memset(void *s, int c, size_t count) #ifdef CONFIG_SPL_DM_RESET static void brom_download(void) { - if (debug_uart_tstc() && debug_uart_getc() == 0x02) { + if (gd->console_evt == 0x02) { printf("ctrl+b: Bootrom download!\n"); writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); do_reset(NULL, 0, 0, NULL); @@ -161,6 +162,30 @@ static void brom_download(void) } #endif +static void spl_hotkey_init(void) +{ + /* If disable console, skip getting uart reg */ + if (!gd || gd->flags & GD_FLG_DISABLE_CONSOLE) + return; + if (!gd->have_console) + return; + + /* serial uclass only exists when enable CONFIG_SPL_FRAMEWORK */ +#ifdef CONFIG_SPL_FRAMEWORK + if (serial_tstc()) { + gd->console_evt = serial_getc(); +#else + if (debug_uart_tstc()) { + gd->console_evt = debug_uart_getc(); +#endif + if (gd->console_evt <= 0x1a) /* 'z' */ + printf("SPL Hotkey: ctrl+%c\n", + gd->console_evt + 'a' - 1); + } + + return; +} + void board_init_f(ulong dummy) { #ifdef CONFIG_SPL_FRAMEWORK @@ -209,12 +234,14 @@ void board_init_f(ulong dummy) /* Some SoCs like rk3036 does not use any frame work */ sdram_init(); #endif + /* Get hotkey and store in gd */ + spl_hotkey_init(); #ifdef CONFIG_SPL_DM_RESET brom_download(); #endif arch_cpu_init(); rk_board_init_f(); -#ifdef CONFIG_SPL_RAM_DEVICE +#if defined(CONFIG_SPL_RAM_DEVICE) && defined(CONFIG_SPL_PCIE_EP_SUPPORT) rockchip_pcie_ep_get_firmware(); #endif #if CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM) && !defined(CONFIG_SPL_BOARD_INIT) @@ -329,6 +356,9 @@ void spl_perform_fixups(struct spl_image_info *spl_image) { #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS atags_set_bootdev_by_spl_bootdevice(spl_image->boot_device); + #ifdef BUILD_SPL_TAG + atags_set_shared_fwver(FW_SPL, "spl-"BUILD_SPL_TAG); + #endif #endif return; } @@ -365,16 +395,27 @@ bool spl_is_low_power(void) void spl_next_stage(struct spl_image_info *spl) { + const char *reason[] = { "Recovery key", "Ctrl+c", "LowPwr", "Unknown" }; uint32_t reg_boot_mode; + int i = 0; if (spl_rockchip_dnl_key_pressed()) { + i = 0; spl->next_stage = SPL_NEXT_STAGE_UBOOT; - return; + goto out; } + + if (gd->console_evt == 0x03) { + i = 1; + spl->next_stage = SPL_NEXT_STAGE_UBOOT; + goto out; + } + #ifdef CONFIG_SPL_DM_FUEL_GAUGE if (spl_is_low_power()) { + i = 2; spl->next_stage = SPL_NEXT_STAGE_UBOOT; - return; + goto out; } #endif @@ -388,11 +429,19 @@ void spl_next_stage(struct spl_image_info *spl) spl->next_stage = SPL_NEXT_STAGE_KERNEL; break; default: - if ((reg_boot_mode & REBOOT_FLAG) != REBOOT_FLAG) + if ((reg_boot_mode & REBOOT_FLAG) != REBOOT_FLAG) { spl->next_stage = SPL_NEXT_STAGE_KERNEL; - else + } else { + i = 3; spl->next_stage = SPL_NEXT_STAGE_UBOOT; + } } + +out: + if (spl->next_stage == SPL_NEXT_STAGE_UBOOT) + printf("Enter uboot reason: %s\n", reason[i]); + + return; } #endif diff --git a/u-boot/arch/arm/mach-rockchip/spl_pcie_ep_boot.c b/u-boot/arch/arm/mach-rockchip/spl_pcie_ep_boot.c index 9d3a6a1364..7a24a1d192 100644 --- a/u-boot/arch/arm/mach-rockchip/spl_pcie_ep_boot.c +++ b/u-boot/arch/arm/mach-rockchip/spl_pcie_ep_boot.c @@ -186,6 +186,7 @@ static int rockchip_pcie_ep_set_bar_flag(void *dbi_base, u32 barno, int flags) static void pcie_bar_init(void *dbi_base) { void *resbar_base; + u32 val; writel(0, dbi_base + 0x10); writel(0, dbi_base + 0x14); @@ -194,15 +195,20 @@ static void pcie_bar_init(void *dbi_base) writel(0, dbi_base + 0x20); writel(0, dbi_base + 0x24); + /* Disable ASPM */ + val = readl(dbi_base + 0x7c); + val &= ~(3 << 10); + writel(val, dbi_base + 0x7c); + /* Resize BAR0 to support 4M 32bits */ resbar_base = dbi_base + PCI_RESBAR; - writel(0xfffff0, resbar_base + 0x4); + writel(0x40, resbar_base + 0x4); writel(0x2c0, resbar_base + 0x8); /* BAR2: 64M 64bits */ - writel(0xfffff0, resbar_base + 0x14); + writel(0x400, resbar_base + 0x14); writel(0x6c0, resbar_base + 0x18); /* BAR4: Fixed for EP wired register, 1M 32bits */ - writel(0xfffff0, resbar_base + 0x24); + writel(0x10, resbar_base + 0x24); writel(0xc0, resbar_base + 0x28); /* Set flags */ rockchip_pcie_ep_set_bar_flag(dbi_base, 0, PCI_BASE_ADDRESS_MEM_TYPE_32); @@ -333,7 +339,7 @@ static void pcie_update_atags(void) struct tag_ram_partition t_ram_part; if (!atags_is_available()) { - printf("RKEP: No ATAGS data found, create new!\n"); + printep("RKEP: No ATAGS data found, create new!\n"); atags_destroy(); } @@ -401,7 +407,27 @@ static void pcie_board_init(void) #define FIREWALL_PCIE_MASTER_SEC 0xfe0300f0 #define FIREWALL_PCIE_ACCESS 0xfe586040 #define CRU_PHYREF_ALT_GATE_CON (CRU_BASE_ADDR + 0x0c38) +#define PMU1_GRF_BASE 0xfd58a000 #define PMU_PWR_GATE_SFTCON1 0xfd8d8150 +#define PMU1_IOC_BASE 0xfd5F0000 +#define CRU_GLB_RST_CON_OFFSET (0xC10U) +#define CRU_GLB_SRST_FST_VALUE_OFFSET (0xC08U) + +void pcie_first_reset(void) +{ + printep("Fst Reset\n"); + mdelay(1); + + writel(0xFFDF, CRU_BASE_ADDR + CRU_GLB_RST_CON_OFFSET); + writel(0xffffffff, PMU1_GRF_BASE + 0x4); // reset width + writel(0x30003000, PMU1_GRF_BASE + 0x1c); // pmu1_grf pmu1_ioc hiold + writel(0x00f00020, PMU1_IOC_BASE + 0x0); //select tsad_shut_m0 iomux + writel(0xFDB9, CRU_BASE_ADDR + CRU_GLB_SRST_FST_VALUE_OFFSET); + + while (1) + ; +} + static void pcie_cru_init(void) { u32 phy0_mplla, phy1_mplla, t0 = 0, t1 = 0; @@ -463,7 +489,7 @@ static void pcie_cru_init(void) phy1_mplla = readl(PCIE3PHY_GRF_BASE + 0xA04); if (phy0_mplla != t0 || phy1_mplla != t1) { - printf("RKEP: GRF:904=%x, a04=%x...\n", phy0_mplla, phy1_mplla); + printep("RKEP: GRF:904=%x, a04=%x...\n", phy0_mplla, phy1_mplla); t0 = phy0_mplla; t1 = phy1_mplla; @@ -474,8 +500,17 @@ static void pcie_cru_init(void) udelay(10); } - /* PHY config: no config need for snps3.0phy */ + if (i >= timeout) { + printep("lock fail\n"); + mdelay(1); + pcie_first_reset(); + } + /* PHY config: no config need for snps3.0phy */ +} + +static void pcie_firewall_init(void) +{ /* Enable PCIe Access in firewall and master secure mode */ writel(0xffff0000, FIREWALL_PCIE_MASTER_SEC); writel(0x01800000, FIREWALL_PCIE_ACCESS); @@ -509,13 +544,31 @@ static const u16 phy_fw[] = { #define CRU_GATE_CON33 (CRU_BASE + 0x384) #define CRU_SOFTRST_CON12 (CRU_BASE + 0x430) #define CRU_SOFTRST_CON27 (CRU_BASE + 0x46c) +#define CRU_GLB_SRST_FST_OFFSET (0xD4U) #define PCIE30_PHY_GRF 0xFDCB8000 +#define SYS_GRF_BASE 0xFDC60000 + +void pcie_first_reset(void) +{ + printep("Fst Reset\n"); + mdelay(1); + + writel(0x00040004, CRU_BASE + 0x104); + writel(0x00700010, CRU_BASE); + writel(0x00100010, SYS_GRF_BASE + 0x508); + writel(0xFDB9, CRU_BASE + CRU_GLB_SRST_FST_OFFSET); + + while (1) + ; +} + void pcie_cru_init(void) { - u32 i, reg; + u32 i, reg, timeout = 500; void __iomem *mmio = (void __iomem *)0xFE8C0000; + u32 phy0_status0, phy0_status1, t0 = 0, t1 = 0; /* Enable phy and controoler clk */ writel(0xffff0000, PMUCRU_PMUGATE_CON02); @@ -548,20 +601,20 @@ void pcie_cru_init(void) writel(0x40000000, CRU_SOFTRST_CON27); udelay(5); - printf("RKEP: sram initial\n"); + printep("RKEP: sram initial\n"); while (1) { reg = readl(PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_STATUS0); if (RK3568_SRAM_INIT_DONE(reg)) break; } - printf("RKEP: sram init done\n"); + printep("RKEP: sram init done\n"); writel((0x3 << 8) | (0x3 << (8 + 16)), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9); //map to access sram for (i = 0; i < ARRAY_SIZE(phy_fw); i++) writel(phy_fw[i], mmio + (i << 2)); - printf("RKEP: snps pcie3phy FW update! size %ld\n", ARRAY_SIZE(phy_fw)); + printep("RKEP: snps pcie3phy FW update! size %ld\n", ARRAY_SIZE(phy_fw)); writel((0x0 << 8) | (0x3 << (8 + 16)), PCIE30_PHY_GRF + GRF_PCIE30PHY_RK3568_CON9); writel((0x1 << 14) | (0x1 << (14 + 16)), @@ -570,8 +623,35 @@ void pcie_cru_init(void) writel(0xffff0000, CRU_SOFTRST_CON12); writel(0x100010, PCIE_SNPS_APB_BASE + 0x180); + /* S-Phy: waiting for phy locked */ + for (i = 0; i < timeout; i++) { + phy0_status0 = readl(PCIE30_PHY_GRF + 0x80); + phy0_status1 = readl(PCIE30_PHY_GRF + 0x84); + + if (phy0_status0 != t0 || phy0_status1 != t1) { + printep("RKEP: GRF:0x80=%x, 0x84=%x...\n", phy0_status0, phy0_status1); + + t0 = phy0_status0; + t1 = phy0_status1; + if (RK3568_SRAM_INIT_DONE(phy0_status0)) + break; + } + + udelay(10); + } + + if (i >= timeout) { + printep("lock fail\n"); + mdelay(1); + pcie_first_reset(); + } + udelay(1); } + +static void pcie_firewall_init(void) +{ +} #endif static void pcie_ep_init(void) @@ -627,6 +707,12 @@ reinit: val = readl(dbi_base + 0x4); writel(val | 0x6, dbi_base + 0x4); + val = readl(apb_base + 0x10); + if (val & 0x4) { + printep("Link is reset, int status misc=%x\n", val); + retries++; + } + if (retries) /* Set app_dly2_done to enable app_ltssm_enable */ writel(0x80008, apb_base + 0x180); else /* Enable LTSSM */ @@ -674,10 +760,13 @@ void rockchip_pcie_ep_init(void) writel(0x1 << 23 | 0x1 << 21, PMU_PWR_GATE_SFTCON1); udelay(10); #endif + + pcie_firewall_init(); /* Re-in pcie initial */ val = readl(PCIE_SNPS_APB_BASE + 0x300); if (((val & 0x3ffff) & ((0x3 << 16))) == 0x30000) { printf("RKEP: already link up\n"); + pcie_devmode_update(RKEP_MODE_LOADER, RKEP_SMODE_LNKUP); return; } diff --git a/u-boot/arch/arm/mach-rockchip/usbplug.c b/u-boot/arch/arm/mach-rockchip/usbplug.c index 48794f8f6d..7cc87c6c3d 100644 --- a/u-boot/arch/arm/mach-rockchip/usbplug.c +++ b/u-boot/arch/arm/mach-rockchip/usbplug.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2020 Rockchip Electronics Co., Ltd. + * (C) Copyright 2020-2023 Rockchip Electronics Co., Ltd. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -12,46 +12,127 @@ DECLARE_GLOBAL_DATA_PTR; +struct bootdev_list { + u32 if_type; + u8 devnum; + u8 iomux_routing; +}; + +#if CONFIG_IS_ENABLED(ROCKCHIP_RK3588) +static const struct bootdev_list dev_list[] = { + {IF_TYPE_MMC, 0, 0}, + {IF_TYPE_MTD, 0, 0}, /* BLK_MTD_NAND */ + {IF_TYPE_MTD, 1, 0}, /* BLK_MTD_SPI_NAND FSPI M0 */ + {IF_TYPE_MTD, 1, 1}, /* BLK_MTD_SPI_NAND FSPI M1 */ + {IF_TYPE_MTD, 1, 2}, /* BLK_MTD_SPI_NAND FSPI M2 */ + {IF_TYPE_MTD, 2, 0}, /* BLK_MTD_SPI_NOR FSPI M0 */ + {IF_TYPE_MTD, 2, 1}, /* BLK_MTD_SPI_NOR FSPI M1 */ + {IF_TYPE_MTD, 2, 2}, /* BLK_MTD_SPI_NOR FSPI M2 */ + {IF_TYPE_RKNAND, 2, 0}, +}; +#else +static const struct bootdev_list dev_list[] = { + {IF_TYPE_MMC, 0, 0}, + {IF_TYPE_MTD, 0, 0}, /* BLK_MTD_NAND */ + {IF_TYPE_MTD, 1, 0}, /* BLK_MTD_SPI_NAND */ + {IF_TYPE_MTD, 2, 0}, /* BLK_MTD_SPI_NOR */ + {IF_TYPE_RKNAND, 0, 0}, +}; +#endif + +static struct blk_desc *boot_blk_desc; +struct blk_desc *rockchip_get_bootdev(void) +{ + return boot_blk_desc; +} + +__weak void board_set_iomux(enum if_type if_type, int devnum, int routing) +{ +} + +struct blk_desc *usbplug_blk_get_devnum_by_type(enum if_type if_type, int devnum) +{ + struct blk_desc *blk_desc = NULL; + u8 iomux_routing; + int i = 0; + + for (i = 0; i < ARRAY_SIZE(dev_list); i++) { + if (if_type != dev_list[i].if_type || devnum != dev_list[i].devnum) + continue; + iomux_routing = dev_list[i].iomux_routing; + switch (if_type) { +#ifdef CONFIG_MMC + case IF_TYPE_MMC: + board_set_iomux(if_type, devnum, iomux_routing); + mmc_initialize(gd->bd); + break; +#endif + case IF_TYPE_MTD: + board_set_iomux(if_type, devnum, iomux_routing); + break; + default: + printf("Bootdev 0x%x is not support\n", if_type); + return NULL; + } + + printf("scandev: %s %d m%d\n", blk_get_if_type_name(if_type), devnum, iomux_routing); + blk_desc = blk_get_devnum_by_type(if_type, devnum); + if (blk_desc) + break; + } + + boot_blk_desc = blk_desc; + + return blk_desc; +} + static char *bootdev_rockusb_cmd(void) { - const char *devtype, *devnum; - const char *bootdev_list[] = { - "mmc", "0", - "mtd", "0", - "mtd", "1", - "mtd", "2", - "rknand", "0", - NULL, NULL, - }; + struct blk_desc *blk_desc = NULL; + u32 if_type = IF_TYPE_UNKNOWN; + u8 devnum, iomux_routing; char *cmd; int i = 0; - devtype = bootdev_list[0]; - devnum = bootdev_list[1]; - while (devtype) { - if (!strcmp("mmc", devtype)) + for (i = 0; i < ARRAY_SIZE(dev_list); i++) { + if_type = dev_list[i].if_type; + devnum = dev_list[i].devnum; + iomux_routing = dev_list[i].iomux_routing; + switch (if_type) { +#ifdef CONFIG_MMC + case IF_TYPE_MMC: + board_set_iomux(if_type, devnum, iomux_routing); mmc_initialize(gd->bd); - - if (blk_get_devnum_by_typename(devtype, atoi(devnum))) break; +#endif + case IF_TYPE_MTD: + board_set_iomux(if_type, devnum, iomux_routing); + break; + default: + printf("Bootdev 0x%x is not support\n", if_type); + return NULL; + } - i += 2; - devtype = bootdev_list[i]; - devnum = bootdev_list[i + 1]; + printf("Scandev: %s %d m%d\n", blk_get_if_type_name(if_type), devnum, iomux_routing); + blk_desc = blk_get_devnum_by_type(if_type, devnum); + if (blk_desc) + break; } - if (!devtype) { + boot_blk_desc = blk_desc; + + if (!if_type) { printf("No boot device\n"); return NULL; } - printf("Bootdev: %s %s\n", devtype, devnum); + printf("Bootdev: %s %d\n", blk_get_if_type_name(if_type), devnum); cmd = malloc(32); if (!cmd) return NULL; - snprintf(cmd, 32, "rockusb 0 %s %s", devtype, devnum); + snprintf(cmd, 32, "rockusb 0 %s %d", blk_get_if_type_name(if_type), devnum); return cmd; } diff --git a/u-boot/arch/arm/mach-rockchip/vendor.c b/u-boot/arch/arm/mach-rockchip/vendor.c index 2a146b75ba..3f9d5df8fb 100644 --- a/u-boot/arch/arm/mach-rockchip/vendor.c +++ b/u-boot/arch/arm/mach-rockchip/vendor.c @@ -11,6 +11,7 @@ #include #include #include +#include /* tag for vendor check */ #define VENDOR_TAG 0x524B5644 @@ -649,10 +650,10 @@ int vendor_storage_read(u16 id, void *pbuf, u16 size) */ int vendor_storage_write(u16 id, void *pbuf, u16 size) { - int cnt, ret = 0; - u32 i, next_index, align_size; - struct vendor_item *item; + u32 i, j, next_index, align_size, alloc_size, next_size; u16 part_size, max_item_num, offset, part_num; + struct vendor_item *item; + int cnt, ret = 0; /* init vendor storage */ if (!bootdev_type) { @@ -703,10 +704,35 @@ int vendor_storage_write(u16 id, void *pbuf, u16 size) /* If item already exist, update the item data */ for (i = 0; i < vendor_info.hdr->item_num; i++) { if ((item + i)->id == id) { - debug("[Vendor INFO]:Find the matching item, id=%d\n", id); - offset = (item + i)->offset; - memcpy((vendor_info.data + offset), pbuf, size); - (item + i)->size = size; + alloc_size = ((item + i)->size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); + if (size > alloc_size) { + if (vendor_info.hdr->free_size < align_size) + return -EINVAL; + debug("[Vendor INFO]:Find the matching item, id=%d and resize\n", id); + offset = (item + i)->offset; + for (j = i; j < vendor_info.hdr->item_num - 1; j++) { + (item + j)->id = (item + j + 1)->id; + (item + j)->size = (item + j + 1)->size; + (item + j)->offset = offset; + + next_size = ((item + j + 1)->size + VENDOR_BTYE_ALIGN) & (~VENDOR_BTYE_ALIGN); + memcpy((vendor_info.data + offset), + (vendor_info.data + (item + j + 1)->offset), + next_size); + offset += next_size; + } + (item + j)->id = id; + (item + j)->offset = offset; + (item + j)->size = size; + memcpy((vendor_info.data + offset), pbuf, size); + vendor_info.hdr->free_offset = offset + align_size; + vendor_info.hdr->free_size -= align_size - alloc_size; + } else { + debug("[Vendor INFO]:Find the matching item, id=%d\n", id); + offset = (item + i)->offset; + memcpy((vendor_info.data + offset), pbuf, size); + (item + i)->size = size; + } vendor_info.hdr->version++; *(vendor_info.version2) = vendor_info.hdr->version; vendor_info.hdr->next_index++; diff --git a/u-boot/arch/arm/mach-rockchip/vendor_misc.c b/u-boot/arch/arm/mach-rockchip/vendor_misc.c index c86d6aace4..8133f116cb 100644 --- a/u-boot/arch/arm/mach-rockchip/vendor_misc.c +++ b/u-boot/arch/arm/mach-rockchip/vendor_misc.c @@ -19,6 +19,7 @@ struct hdcpdata { unsigned char data[0]; }; +#ifndef CONFIG_SUPPORT_USBPLUG int vendor_handle_hdcp(struct vendor_item *vhead) { struct arm_smccc_res res; @@ -61,4 +62,4 @@ int vendor_handle_hdcp(struct vendor_item *vhead) return 0; } - +#endif diff --git a/u-boot/board/rockchip/evb_rk3528/evb_rk3528.c b/u-boot/board/rockchip/evb_rk3528/evb_rk3528.c index d0c1e5507e..df91be38ed 100644 --- a/u-boot/board/rockchip/evb_rk3528/evb_rk3528.c +++ b/u-boot/board/rockchip/evb_rk3528/evb_rk3528.c @@ -7,27 +7,79 @@ #include #include #include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_USB_DWC3 +#define CRU_BASE 0xff4a0000 +#define CRU_SOFTRST_CON33 0x0a84 + static struct dwc3_device dwc3_device_data = { - .maximum_speed = USB_SPEED_HIGH, + .maximum_speed = USB_SPEED_SUPER, .base = 0xfe500000, .dr_mode = USB_DR_MODE_PERIPHERAL, .index = 0, .dis_u2_susphy_quirk = 1, + .dis_u1u2_quirk = 1, .usb2_phyif_utmi_width = 16, }; -int usb_gadget_handle_interrupts(void) +int usb_gadget_handle_interrupts(int index) { dwc3_uboot_handle_interrupt(0); return 0; } +bool rkusb_usb3_capable(void) +{ + return true; +} + +static void usb_reset_otg_controller(void) +{ + writel(0x00020002, CRU_BASE + CRU_SOFTRST_CON33); + mdelay(1); + writel(0x00020000, CRU_BASE + CRU_SOFTRST_CON33); + mdelay(1); +} + int board_usb_init(int index, enum usb_init_type init) { + u32 ret = 0; + + usb_reset_otg_controller(); + +#if defined(CONFIG_SUPPORT_USBPLUG) + dwc3_device_data.maximum_speed = USB_SPEED_HIGH; + + if (rkusb_switch_usb3_enabled()) { + dwc3_device_data.maximum_speed = USB_SPEED_SUPER; + ret = rockchip_combphy_usb3_uboot_init(); + if (ret) { + rkusb_force_to_usb2(true); + dwc3_device_data.maximum_speed = USB_SPEED_HIGH; + } + } +#else + ret = rockchip_combphy_usb3_uboot_init(); + if (ret) { + rkusb_force_to_usb2(true); + dwc3_device_data.maximum_speed = USB_SPEED_HIGH; + } +#endif + return dwc3_uboot_init(&dwc3_device_data); } + +#if defined(CONFIG_SUPPORT_USBPLUG) +int board_usb_cleanup(int index, enum usb_init_type init) +{ + dwc3_uboot_exit(index); + return 0; +} +#endif + #endif diff --git a/u-boot/board/rockchip/evb_rk3588/evb_rk3588.c b/u-boot/board/rockchip/evb_rk3588/evb_rk3588.c index 81c5089944..fa72f37730 100644 --- a/u-boot/board/rockchip/evb_rk3588/evb_rk3588.c +++ b/u-boot/board/rockchip/evb_rk3588/evb_rk3588.c @@ -7,27 +7,79 @@ #include #include #include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_USB_DWC3 +#define CRU_BASE 0xfd7c0000 +#define CRU_SOFTRST_CON42 0x0aa8 + static struct dwc3_device dwc3_device_data = { - .maximum_speed = USB_SPEED_HIGH, + .maximum_speed = USB_SPEED_SUPER, .base = 0xfc000000, .dr_mode = USB_DR_MODE_PERIPHERAL, .index = 0, .dis_u2_susphy_quirk = 1, + .dis_u1u2_quirk = 1, .usb2_phyif_utmi_width = 16, }; -int usb_gadget_handle_interrupts(void) +int usb_gadget_handle_interrupts(int index) { dwc3_uboot_handle_interrupt(0); return 0; } +bool rkusb_usb3_capable(void) +{ + return true; +} + +static void usb_reset_otg_controller(void) +{ + writel(0x00100010, CRU_BASE + CRU_SOFTRST_CON42); + mdelay(1); + writel(0x00100000, CRU_BASE + CRU_SOFTRST_CON42); + mdelay(1); +} + int board_usb_init(int index, enum usb_init_type init) { + u32 ret = 0; + + usb_reset_otg_controller(); + +#if defined(CONFIG_SUPPORT_USBPLUG) + dwc3_device_data.maximum_speed = USB_SPEED_HIGH; + + if (rkusb_switch_usb3_enabled()) { + dwc3_device_data.maximum_speed = USB_SPEED_SUPER; + ret = rockchip_u3phy_uboot_init(); + if (ret) { + rkusb_force_to_usb2(true); + dwc3_device_data.maximum_speed = USB_SPEED_HIGH; + } + } +#else + ret = rockchip_u3phy_uboot_init(); + if (ret) { + rkusb_force_to_usb2(true); + dwc3_device_data.maximum_speed = USB_SPEED_HIGH; + } +#endif + return dwc3_uboot_init(&dwc3_device_data); } + +#if defined(CONFIG_SUPPORT_USBPLUG) +int board_usb_cleanup(int index, enum usb_init_type init) +{ + dwc3_uboot_exit(index); + return 0; +} +#endif + #endif diff --git a/u-boot/cmd/Kconfig b/u-boot/cmd/Kconfig index 1efdeae6c6..5b359ff846 100644 --- a/u-boot/cmd/Kconfig +++ b/u-boot/cmd/Kconfig @@ -929,6 +929,15 @@ config CMD_PCMCIA about 1990. These devices are typically removable memory or network cards using a standard 68-pin connector. +config CMD_PINMUX + bool "pinmux - show pins muxing" + depends on PINCTRL + default y if PINCTRL + help + Parse all available pin-controllers and show pins muxing. This + is useful for debug purpoer to check the pin muxing and to know if + a pin is configured as a GPIO or as an alternate function. + config CMD_READ bool "read - Read binary data from a partition" help diff --git a/u-boot/cmd/Makefile b/u-boot/cmd/Makefile index d4c12a3cc3..9a2d5f89d6 100644 --- a/u-boot/cmd/Makefile +++ b/u-boot/cmd/Makefile @@ -113,6 +113,7 @@ ifdef CONFIG_PCI obj-$(CONFIG_CMD_PCI) += pci.o endif obj-y += pcmcia.o +obj-$(CONFIG_CMD_PINMUX) += pinmux.o obj-$(CONFIG_CMD_PXE) += pxe.o obj-$(CONFIG_CMD_QFW) += qfw.o obj-$(CONFIG_CMD_READ) += read.o diff --git a/u-boot/cmd/atags.c b/u-boot/cmd/atags.c index 8bcf8b3203..6af5613957 100644 --- a/u-boot/cmd/atags.c +++ b/u-boot/cmd/atags.c @@ -179,6 +179,14 @@ static void atags_print_tag(struct tag *t) for (i = 0; i < ARRAY_SIZE(t->u.pstore.buf); i++) printf(" table[%d] = 0x%x@0x%x\n", i, t->u.pstore.buf[i].size, t->u.pstore.buf[i].addr); break; + case ATAG_FWVER: + printf("[fwver]:\n"); + printf(" magic = 0x%x\n", t->hdr.magic); + printf(" size = 0x%x\n\n", t->hdr.size << 2); + printf(" version = 0x%x\n", t->u.fwver.version); + for (i = 0; i < FW_MAX; i++) + printf(" ver[%d] = %s\n", i, t->u.fwver.ver[i]); + break; default: printf("%s: magic(%x) is not support\n", __func__, t->hdr.magic); } diff --git a/u-boot/cmd/demo.c b/u-boot/cmd/demo.c index 209dc4a57c..af49845b03 100644 --- a/u-boot/cmd/demo.c +++ b/u-boot/cmd/demo.c @@ -67,9 +67,8 @@ int do_demo_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) puts("Demo uclass entries:\n"); - for (i = 0, ret = uclass_first_device(UCLASS_DEMO, &dev); - dev; - ret = uclass_next_device(&dev)) { + for (i = 0, uclass_first_device(UCLASS_DEMO, &dev); dev; + uclass_next_device(&dev)) { printf("entry %d - instance %08x, ops %08x, platdata %08x\n", i++, map_to_sysmem(dev), map_to_sysmem(dev->driver->ops), diff --git a/u-boot/cmd/gpio.c b/u-boot/cmd/gpio.c index ecdc453918..878ac7ef21 100644 --- a/u-boot/cmd/gpio.c +++ b/u-boot/cmd/gpio.c @@ -68,14 +68,13 @@ static int do_gpio_status(bool all, const char *gpio_name) struct udevice *dev; int banklen; int flags; - int ret; flags = 0; if (gpio_name && !*gpio_name) gpio_name = NULL; - for (ret = uclass_first_device(UCLASS_GPIO, &dev); + for (uclass_first_device(UCLASS_GPIO, &dev); dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { const char *bank_name; int num_bits; @@ -111,7 +110,7 @@ static int do_gpio_status(bool all, const char *gpio_name) flags |= FLAG_SHOW_NEWLINE; } - return ret; + return 0; } #endif diff --git a/u-boot/cmd/pinmux.c b/u-boot/cmd/pinmux.c new file mode 100644 index 0000000000..de909a163d --- /dev/null +++ b/u-boot/cmd/pinmux.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include + +#define LIMIT_DEVNAME 30 + +static struct udevice *currdev; + +static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + const char *name; + int ret; + + switch (argc) { + case 2: + name = argv[1]; + ret = uclass_get_device_by_name(UCLASS_PINCTRL, name, &currdev); + if (ret) { + printf("Can't get the pin-controller: %s!\n", name); + return CMD_RET_FAILURE; + } + /* fall through */ + case 1: + if (!currdev) { + printf("Pin-controller device is not set!\n"); + return CMD_RET_USAGE; + } + + printf("dev: %s\n", currdev->name); + } + + return CMD_RET_SUCCESS; +} + +static int show_pinmux(struct udevice *dev) +{ + char pin_name[PINNAME_SIZE]; + char pin_mux[PINMUX_SIZE]; + int pins_count; + int i; + int ret; + + pins_count = pinctrl_get_pins_count(dev); + + if (pins_count == -ENOSYS) { + printf("Ops get_pins_count not supported\n"); + return pins_count; + } + + for (i = 0; i < pins_count; i++) { + ret = pinctrl_get_pin_name(dev, i, pin_name, PINNAME_SIZE); + if (ret == -ENOSYS) { + printf("Ops get_pin_name not supported\n"); + return ret; + } + + ret = pinctrl_get_pin_muxing(dev, i, pin_mux, PINMUX_SIZE); + if (ret) { + printf("Ops get_pin_muxing error (%d)\n", ret); + return ret; + } + + printf("%-*s: %-*s\n", PINNAME_SIZE, pin_name, + PINMUX_SIZE, pin_mux); + } + + return 0; +} + +static int do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + int ret = CMD_RET_USAGE; + + if (currdev && (argc < 2 || strcmp(argv[1], "-a"))) + return show_pinmux(currdev); + + if (argc < 2 || strcmp(argv[1], "-a")) + return ret; + + uclass_foreach_dev_probe(UCLASS_PINCTRL, dev) { + /* insert a separator between each pin-controller display */ + printf("--------------------------\n"); + printf("%s:\n", dev->name); + ret = show_pinmux(dev); + if (ret < 0) + printf("Can't display pin muxing for %s\n", + dev->name); + } + + return ret; +} + +static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct udevice *dev; + + printf("| %-*.*s| %-*.*s| %s\n", + LIMIT_DEVNAME, LIMIT_DEVNAME, "Device", + LIMIT_DEVNAME, LIMIT_DEVNAME, "Driver", + "Parent"); + + uclass_foreach_dev_probe(UCLASS_PINCTRL, dev) { + printf("| %-*.*s| %-*.*s| %s\n", + LIMIT_DEVNAME, LIMIT_DEVNAME, dev->name, + LIMIT_DEVNAME, LIMIT_DEVNAME, dev->driver->name, + dev->parent->name); + } + + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t pinmux_subcmd[] = { + U_BOOT_CMD_MKENT(dev, 2, 1, do_dev, "", ""), + U_BOOT_CMD_MKENT(list, 1, 1, do_list, "", ""), + U_BOOT_CMD_MKENT(status, 2, 1, do_status, "", ""), +}; + +static int do_pinmux(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *cmd; + + argc--; + argv++; + + cmd = find_cmd_tbl(argv[0], pinmux_subcmd, ARRAY_SIZE(pinmux_subcmd)); + if (!cmd || argc > cmd->maxargs) + return CMD_RET_USAGE; + + return cmd->cmd(cmdtp, flag, argc, argv); +} + +U_BOOT_CMD(pinmux, CONFIG_SYS_MAXARGS, 1, do_pinmux, + "show pin-controller muxing", + "list - list UCLASS_PINCTRL devices\n" + "pinmux dev [pincontroller-name] - select pin-controller device\n" + "pinmux status [-a] - print pin-controller muxing [for all]\n" +) diff --git a/u-boot/cmd/pmic.c b/u-boot/cmd/pmic.c index 970767cdfa..8c191ab258 100644 --- a/u-boot/cmd/pmic.c +++ b/u-boot/cmd/pmic.c @@ -50,27 +50,20 @@ static int do_dev(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct udevice *dev; - int ret; printf("| %-*.*s| %-*.*s| %s @ %s\n", LIMIT_DEV, LIMIT_DEV, "Name", LIMIT_PARENT, LIMIT_PARENT, "Parent name", "Parent uclass", "seq"); - for (ret = uclass_first_device(UCLASS_PMIC, &dev); dev; - ret = uclass_next_device(&dev)) { - if (ret) - continue; - + for (uclass_first_device(UCLASS_PMIC, &dev); dev; + uclass_next_device(&dev)) { printf("| %-*.*s| %-*.*s| %s @ %d\n", LIMIT_DEV, LIMIT_DEV, dev->name, LIMIT_PARENT, LIMIT_PARENT, dev->parent->name, dev_get_uclass_name(dev->parent), dev->parent->seq); } - if (ret) - return CMD_RET_FAILURE; - return CMD_RET_SUCCESS; } diff --git a/u-boot/cmd/regulator.c b/u-boot/cmd/regulator.c index b605255180..25aef95b2b 100644 --- a/u-boot/cmd/regulator.c +++ b/u-boot/cmd/regulator.c @@ -249,8 +249,8 @@ static int do_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Show all of them in a list, probing them as needed */ printf("%-20s %-10s %10s %10s %-10s\n", "Name", "Enabled", "uV", "mA", "Mode"); - for (ret = uclass_first_device(UCLASS_REGULATOR, &dev); dev; - ret = uclass_next_device(&dev)) + for (uclass_first_device(UCLASS_REGULATOR, &dev); dev; + uclass_next_device(&dev)) do_status_line(dev); return CMD_RET_SUCCESS; diff --git a/u-boot/cmd/rockusb.c b/u-boot/cmd/rockusb.c index 9792a828bb..38768b724d 100644 --- a/u-boot/cmd/rockusb.c +++ b/u-boot/cmd/rockusb.c @@ -151,6 +151,34 @@ cleanup: return ret; } +void rkusb_force_to_usb2(bool enable) +{ + if (g_rkusb) + g_rkusb->force_usb2 = enable; +} + +bool rkusb_force_usb2_enabled(void) +{ + if (!g_rkusb) + return true; + + return g_rkusb->force_usb2; +} + +void rkusb_switch_to_usb3_enable(bool enable) +{ + if (g_rkusb) + g_rkusb->switch_usb3 = enable; +} + +bool rkusb_switch_usb3_enabled(void) +{ + if (!g_rkusb) + return false; + + return g_rkusb->switch_usb3; +} + static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { const char *usb_controller; @@ -164,6 +192,7 @@ static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (argc != 4) return CMD_RET_USAGE; +re_enumerate: usb_controller = argv[1]; devtype = argv[2]; devnum = argv[3]; @@ -171,7 +200,7 @@ static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (!strcmp(devtype, "mmc") && !strcmp(devnum, "1")) { pr_err("Forbid to flash mmc 1(sdcard)\n"); return CMD_RET_FAILURE; - } else if (!strcmp(devtype, "nvme") && !strcmp(devnum, "0")) { + } else if ((!strcmp(devtype, "nvme") || !strcmp(devtype, "scsi")) && !strcmp(devnum, "0")) { /* * Add partnum ":0" to active 'allow_whole_dev' partition * search mechanism on multi storage, where there maybe not @@ -212,23 +241,34 @@ static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) goto cleanup_board; } - s = env_get("serial#"); - if (s) { - char *sn = (char *)calloc(strlen(s) + 1, sizeof(char)); - char *sn_p = sn; + if (rkusb_switch_usb3_enabled()) { + /* Maskrom usb3 serialnumber get from upgrade tool */ + rkusb_switch_to_usb3_enable(false); + } else { + s = env_get("serial#"); + if (s) { + char *sn = (char *)calloc(strlen(s) + 1, sizeof(char)); + char *sn_p = sn; - if (!sn) - goto cleanup_board; + if (!sn) + goto cleanup_board; - memcpy(sn, s, strlen(s)); - while (*sn_p) { - if (*sn_p == '\\' || *sn_p == '/') - *sn_p = '_'; - sn_p++; + memcpy(sn, s, strlen(s)); + while (*sn_p) { + if (*sn_p == '\\' || *sn_p == '/') + *sn_p = '_'; + sn_p++; + } + + g_dnl_set_serialnumber(sn); + free(sn); +#if defined(CONFIG_SUPPORT_USBPLUG) + } else { + char sn[9] = "Rockchip"; + + g_dnl_set_serialnumber(sn); +#endif } - - g_dnl_set_serialnumber(sn); - free(sn); } rc = g_dnl_register("rkusb_ums_dnl"); @@ -268,6 +308,16 @@ static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) rc = fsg_main_thread(NULL); if (rc) { + if (rc == -ENODEV && rkusb_usb3_capable() && + !rkusb_force_usb2_enabled()) { + printf("wait for usb3 connect timeout\n"); + rkusb_force_to_usb2(true); + g_dnl_unregister(); + usb_gadget_release(controller_index); + rkusb_fini(); + goto re_enumerate; + } + /* Check I/O error */ if (rc == -EIO) printf("\rCheck USB cable connection\n"); @@ -279,6 +329,14 @@ static int do_rkusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) rc = CMD_RET_SUCCESS; goto cleanup_register; } + + if (rkusb_switch_usb3_enabled()) { + printf("rockusb switch to usb3\n"); + g_dnl_unregister(); + usb_gadget_release(controller_index); + rkusb_fini(); + goto re_enumerate; + } } cleanup_register: diff --git a/u-boot/common/Kconfig b/u-boot/common/Kconfig index cc0753cb45..c276f701a8 100644 --- a/u-boot/common/Kconfig +++ b/u-boot/common/Kconfig @@ -680,6 +680,20 @@ config HASH and the algorithms it supports are defined in common/hash.c. See also CMD_HASH for command-line access. +config BOARD_RNG_SEED + bool "Provide /chosen/rng-seed property to the linux kernel" + help + Selecting this option requires the board to define a + board_rng_seed() function, which should return a buffer + which will be used to populate the /chosen/rng-seed property + in the device tree for the OS being booted. + + It is up to the board code (and more generally the whole + BSP) where and how to store (or generate) such a seed, how + to ensure a given seed is only used once, how to create a + new seed for use on subsequent boots, and whether or not the + kernel should account any entropy from the given seed. + endmenu menu "MT support" diff --git a/u-boot/common/Makefile b/u-boot/common/Makefile index e6f1c114c7..52cd612d15 100644 --- a/u-boot/common/Makefile +++ b/u-boot/common/Makefile @@ -165,6 +165,7 @@ obj-$(CONFIG_IO_TRACE) += iotrace.o obj-$(CONFIG_ANDROID_WRITE_KEYBOX) += write_keybox.o obj-$(CONFIG_ANDROID_KEYMASTER_CA) += keymaster.o obj-$(CONFIG_ANDROID_KEYMASTER_CA) += attestation_key.o +obj-$(CONFIG_ANDROID_KEYMASTER_CA) += id_attestation.o endif ifdef CONFIG_MP_BOOT diff --git a/u-boot/common/board_info.c b/u-boot/common/board_info.c index b2c6bd5715..1d0155ea24 100644 --- a/u-boot/common/board_info.c +++ b/u-boot/common/board_info.c @@ -5,8 +5,6 @@ #include #include #include -#include -#include int __weak checkboard(void) { @@ -35,11 +33,5 @@ int __weak show_board_info(void) printf("CPU: AArch32\n"); #endif - if (strstr(model, "rk3588") != NULL) { - printf("rpdzkj: pull down gpio0_b2 for init wifi\n"); - writel(0xFFFF0400, 0xFD8A0008); // direction out - writel(0xFFFE0000, 0xFD8A0000); // output low - } - return checkboard(); } diff --git a/u-boot/common/console.c b/u-boot/common/console.c index 4abe4d150b..629c2a6459 100644 --- a/u-boot/common/console.c +++ b/u-boot/common/console.c @@ -524,13 +524,6 @@ void putc(const char c) putc_to_ram(c); #endif -#ifdef CONFIG_DEBUG_UART - /* if we don't have a console yet, use the debug UART */ - if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) { - printch(c); - return; - } -#endif #ifdef CONFIG_CONSOLE_RECORD if (gd && (gd->flags & GD_FLG_RECORD) && gd->console_out.start) membuff_putbyte((struct membuff *)&gd->console_out, c); @@ -540,6 +533,13 @@ void putc(const char c) return; #endif +#ifdef CONFIG_DEBUG_UART + /* if we don't have a console yet, use the debug UART */ + if (!gd || !(gd->flags & GD_FLG_SERIAL_READY)) { + printch(c); + return; + } +#endif if (!gd->have_console) return pre_console_putc(c); diff --git a/u-boot/common/edid.c b/u-boot/common/edid.c index d7d224cc58..0e78c1319d 100644 --- a/u-boot/common/edid.c +++ b/u-boot/common/edid.c @@ -2639,8 +2639,8 @@ static bool drm_valid_hdmi_vic(u8 vic) return vic > 0 && vic < ARRAY_SIZE(edid_4k_modes); } -static void drm_add_hdmi_modes(struct hdmi_edid_data *data, - const struct drm_display_mode *mode) +void drm_add_hdmi_modes(struct hdmi_edid_data *data, + const struct drm_display_mode *mode) { struct drm_display_mode *mode_buf = data->mode_buf; diff --git a/u-boot/common/fdt_support.c b/u-boot/common/fdt_support.c index fa3d3e7af2..d6370891d7 100644 --- a/u-boot/common/fdt_support.c +++ b/u-boot/common/fdt_support.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -354,6 +355,7 @@ __weak char *board_fdt_chosen_bootargs(void *fdt) int fdt_chosen(void *fdt) { + struct abuf buf = {}; int nodeoffset; int err; char *str; /* used to set string properties */ @@ -369,6 +371,17 @@ int fdt_chosen(void *fdt) if (nodeoffset < 0) return nodeoffset; + if (IS_ENABLED(CONFIG_BOARD_RNG_SEED) && !board_rng_seed(&buf)) { + err = fdt_setprop(fdt, nodeoffset, "rng-seed", + abuf_data(&buf), abuf_size(&buf)); + abuf_uninit(&buf); + if (err < 0) { + printf("WARNING: could not set rng-seed %s.\n", + fdt_strerror(err)); + return err; + } + } + str = board_fdt_chosen_bootargs(fdt); if (str) { err = fdt_setprop(fdt, nodeoffset, "bootargs", str, diff --git a/u-boot/common/id_attestation.c b/u-boot/common/id_attestation.c new file mode 100644 index 0000000000..59890e805d --- /dev/null +++ b/u-boot/common/id_attestation.c @@ -0,0 +1,93 @@ +/* + * Copyright 2023, Rockchip Electronics Co., Ltd + * callen, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include "id_attestation.h" + + +#define ID_ATTESTATION_FILE "attestation_ids" +/* Maximum file name size.*/ +#define STORAGE_ID_LENGTH_MAX 64 + +void printAttestationIds(const AttestationIds *ids) +{ + printf("AttestationIds:\n"); + printf(" brand: %s\n", ids->brand); + printf(" device: %s\n", ids->device); + printf(" product: %s\n", ids->product); + printf(" serial: %s\n", ids->serial); + printf(" imei: %s\n", ids->imei); + printf(" second_imei: %s\n", ids->second_imei); + printf(" meid: %s\n", ids->meid); + printf(" manufacturer: %s\n", ids->manufacturer); + printf(" model: %s\n", ids->model); +} +uint32_t write_to_keymaster(u8 *filename, uint32_t filename_size, + u8 *data, uint32_t data_size); + +/* read id attestation digest len */ +uint32_t read_id_attestation_digest(const char *ids_digest_file, uint32_t *ids_digest_len) +{ + int len = sizeof(AttestationIds); + u8 ids_digest[len]; + + TEEC_Result ret = read_from_keymaster((u8 *)ids_digest_file, strlen(ids_digest_file), + (u8 *)ids_digest, len); + if (ret != TEEC_SUCCESS) + *ids_digest_len = 0; + else + *ids_digest_len = len; + MSG("%s file:%s ,digest_len=%d,ret=%x\n", __func__, ids_digest_file, *ids_digest_len, ret); + return ret; +} + +uint32_t write_id_attestation(const char *ids_file, AttestationIds *ids, uint32_t ids_len) +{ + TEEC_Result ret = write_to_keymaster((u8 *)ids_file, strlen(ids_file), + (u8 *)ids, ids_len); + MSG("%s ids_file=%s ret=%0x\n", __func__, ids_file, ret); + return ret; +} + +atap_result write_id_attestation_to_secure_storage(u8* received_data, uint32_t len) +{ + AttestationIds ids; + u32 ids_len; + AttestationIds ids_read; + char ids_file[STORAGE_ID_LENGTH_MAX] = { 0 }; + + ids_len = (received_data[5] << 8) | received_data[4]; + printf("%s size=%d\n", __func__, ids_len); + if (ids_len != sizeof(AttestationIds)) { + printf("%s AttestationIds size is %zu)\n", __func__, sizeof(AttestationIds)); + return ATAP_RESULT_ERROR_INVALID_HEAD; + } + memcpy(&ids, received_data + 8, len); +#if DEBUG + printAttestationIds(&ids); +#endif + /* now you have got the whole AttestationIds data....*/ + memcpy(ids_file, ID_ATTESTATION_FILE, sizeof(ID_ATTESTATION_FILE)); + TEEC_Result ret = read_from_keymaster((u8 *)ids_file, + strlen(ids_file), + (u8*)&ids_read, + sizeof(AttestationIds)); + MSG("read id attestation ret=%0x\n", ret); + if (ret == TEEC_SUCCESS) { + printf("id attestation already exsit,you cannot update it!"); +#if DEBUG + printAttestationIds(&ids_read); +#endif + ret = ATAP_RESULT_ERROR_ALREADY_EXSIT; + return ret; + } + ret = write_id_attestation(ids_file, &ids, ids_len); + printf("write id attestation : ret=%d\n", ret); + return ret; +} diff --git a/u-boot/common/image-android.c b/u-boot/common/image-android.c index a77c0f3510..d580eb61ce 100644 --- a/u-boot/common/image-android.c +++ b/u-boot/common/image-android.c @@ -1090,7 +1090,16 @@ extract_boot_image_v34_header(struct blk_desc *dev_desc, return NULL; } - /* Start from android-13 GKI, it doesn't assign 'os_version' */ + /* + * [Start from android-13 GKI, it doesn't assign 'os_version'] + * + * Android_12 or later are header_version >= 4. + * Android_13(GKI) introduce a new partition named "init_boot" and + * doesn't assign 'os_version' any more(ie. default 0). + * + * We only assign 'os_version' depend on whether there is + * init_boot partition or not. + */ if (boot_hdr->header_version >= 4 && boot_hdr->os_version == 0) { if (part_get_info_by_name(dev_desc, ANDROID_PARTITION_INIT_BOOT, &part) > 0) @@ -1171,7 +1180,25 @@ int populate_boot_info(const struct boot_img_hdr_v34 *boot_hdr, /* fixed in v3 */ hdr->page_size = 4096; hdr->header_version = boot_hdr->header_version; - hdr->os_version = boot_hdr->os_version; + /* + * [Start from android-13 GKI, it doesn't assign 'os_version'] + * + * Android_12 or later are header_version >= 4. + * Android_13(GKI) introduce a new partition named "init_boot" and + * doesn't assign 'os_version' any more(ie. default 0). + * + * We only assign 'os_version' depend on whether there is + * init_boot partition or not. + */ + if (boot_hdr->header_version >= 4 && boot_hdr->os_version == 0) { + if (init_boot_hdr) + hdr->os_version = 13 << 25; + + if (!hdr->os_version) + printf("WARN: it seems to be an invalid Android os_version: 0\n"); + } else { + hdr->os_version = boot_hdr->os_version; + } memset(hdr->name, 0, ANDR_BOOT_NAME_SIZE); strncpy(hdr->name, (const char *)vendor_boot_hdr->name, ANDR_BOOT_NAME_SIZE); diff --git a/u-boot/common/image-sig.c b/u-boot/common/image-sig.c index 4a07e86085..052eab6ef4 100644 --- a/u-boot/common/image-sig.c +++ b/u-boot/common/image-sig.c @@ -439,7 +439,7 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode, #if !defined(USE_HOSTCC) #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_FIT_HW_CRYPTO) && \ defined(CONFIG_SPL_ROCKCHIP_SECURE_OTP) - rsa_burn_key_hash(&info); + return rsa_burn_key_hash(&info); #endif #endif diff --git a/u-boot/common/spl/Kconfig b/u-boot/common/spl/Kconfig index dfa3fcde48..cc4d957195 100644 --- a/u-boot/common/spl/Kconfig +++ b/u-boot/common/spl/Kconfig @@ -884,7 +884,9 @@ config SPL_OPTEE config SPL_AB bool "Support AB system boot" - depends on SPL && SPL_EFI_PARTITION + depends on SPL && SPL_LIBDISK_SUPPORT + select SPL_MTD_WRITE if SPL_MTD_SUPPORT + select SPL_MMC_WRITE if SPL_MMC_SUPPORT help Enable this config to support AB system boot. diff --git a/u-boot/common/spl/Makefile b/u-boot/common/spl/Makefile index cf9d874f92..f06b4cdc82 100644 --- a/u-boot/common/spl/Makefile +++ b/u-boot/common/spl/Makefile @@ -25,10 +25,10 @@ endif ifdef CONFIG_SPL_BUILD obj-$(CONFIG_$(SPL_TPL_)BOOTROM_SUPPORT) += spl_bootrom.o ifdef CONFIG_SPL_KERNEL_BOOT_PREBUILT -ifdef CONFIG_ARM64 -obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit_tb_arm64.o -else -obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit_tb_arm32.o +ifeq ($(CONFIG_$(SPL_TPL_)LOAD_FIT),y) +obj-$(CONFIG_ARM64) += spl_fit_tb_arm64.o +obj-$(CONFIG_ROCKCHIP_RV1106) += spl_fit_tb_rv1106.o +obj-$(CONFIG_ROCKCHIP_RV1126) += spl_fit_tb_rv1126.o endif else obj-$(CONFIG_$(SPL_TPL_)LOAD_FIT) += spl_fit.o diff --git a/u-boot/common/spl/spl.c b/u-boot/common/spl/spl.c index bcb37ecb41..36c0f74a81 100644 --- a/u-boot/common/spl/spl.c +++ b/u-boot/common/spl/spl.c @@ -661,8 +661,13 @@ void preloader_console_init(void) gd->have_console = 1; +#ifdef BUILD_SPL_TAG + puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \ + U_BOOT_TIME "), fwver: "BUILD_SPL_TAG"\n"); +#else 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/u-boot/common/spl/spl_ab.c b/u-boot/common/spl/spl_ab.c index 842c36c9ba..b7fd5f21c0 100644 --- a/u-boot/common/spl/spl_ab.c +++ b/u-boot/common/spl/spl_ab.c @@ -284,6 +284,35 @@ static int spl_save_metadata_if_changed(struct blk_desc *dev_desc, return 0; } +static void spl_slot_set_unbootable(AvbABSlotData* slot) +{ + slot->priority = 0; + slot->tries_remaining = 0; + slot->successful_boot = 0; +} + +/* Ensure all unbootable and/or illegal states are marked as the + * canonical 'unbootable' state, e.g. priority=0, tries_remaining=0, + * and successful_boot=0. + */ +static void spl_slot_normalize(AvbABSlotData* slot) +{ + if (slot->priority > 0) { + if (slot->tries_remaining == 0 && !slot->successful_boot) { + /* We've exhausted all tries -> unbootable. */ + spl_slot_set_unbootable(slot); + } + if (slot->tries_remaining > 0 && slot->successful_boot) { + /* Illegal state - avb_ab_mark_slot_successful() and so on + * will clear tries_remaining when setting successful_boot. + */ + spl_slot_set_unbootable(slot); + } + } else { + spl_slot_set_unbootable(slot); + } +} + /* If verify fail in a/b system, then decrease 1. */ int spl_ab_decrease_tries(struct blk_desc *dev_desc) { @@ -309,6 +338,13 @@ int spl_ab_decrease_tries(struct blk_desc *dev_desc) memcpy(&ab_data_orig, &ab_data, sizeof(AvbABData)); + /* Ensure data is normalized, e.g. illegal states will be marked as + * unbootable and all unbootable states are represented with + * (priority=0, tries_remaining=0, successful_boot=0). + */ + spl_slot_normalize(&ab_data.slots[0]); + spl_slot_normalize(&ab_data.slots[1]); + /* ... and decrement tries remaining, if applicable. */ if (!ab_data.slots[slot_index].successful_boot && ab_data.slots[slot_index].tries_remaining > 0) diff --git a/u-boot/common/spl/spl_fit_tb_rv1106.S b/u-boot/common/spl/spl_fit_tb_rv1106.S new file mode 100644 index 0000000000..fc24ececef --- /dev/null +++ b/u-boot/common/spl/spl_fit_tb_rv1106.S @@ -0,0 +1,12882 @@ + .arch armv7-a + .eabi_attribute 20, 1 + .eabi_attribute 21, 1 + .eabi_attribute 23, 3 + .eabi_attribute 24, 1 + .eabi_attribute 25, 1 + .eabi_attribute 26, 2 + .eabi_attribute 30, 4 + .eabi_attribute 34, 0 + .eabi_attribute 18, 2 + .file "spl_fit_tb.c" + .text +.Ltext0: + .cfi_sections .debug_frame + .section .text.spl_fit_get_image_name.isra.0,"ax",%progbits + .align 1 + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_fit_get_image_name.isra.0, %function +spl_fit_get_image_name.isra.0: +.LFB236: + .file 1 "common/spl/spl_fit_tb.c" + .loc 1 81 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 0, uses_anonymous_args = 0 +.LVL0: + push {r0, r1, r4, r5, r6, r7, r8, lr} + .cfi_def_cfa_offset 32 + .cfi_offset 4, -24 + .cfi_offset 5, -20 + .cfi_offset 6, -16 + .cfi_offset 7, -12 + .cfi_offset 8, -8 + .cfi_offset 14, -4 + .loc 1 81 0 + mov r5, r0 + mov r8, r1 + mov r7, r2 + mov r6, r3 + .loc 1 90 0 + bl fit_find_config_node +.LVL1: + .loc 1 91 0 + subs r4, r0, #0 + bge .L2 + .loc 1 93 0 + ldr r0, .L11 +.LVL2: + .loc 1 97 0 + ldr r7, .L11+4 +.LVL3: + .loc 1 98 0 + ldr r8, .L11+8 +.LVL4: + .loc 1 93 0 + bl printf +.LVL5: + .loc 1 94 0 + mov r1, r4 + mov r0, r5 + bl fdt_first_subnode +.LVL6: + mov r6, r0 +.LVL7: +.L3: + cmp r6, #0 + bge .L4 +.LVL8: +.L1: + .loc 1 121 0 + mov r0, r4 + add sp, sp, #8 + .cfi_remember_state + .cfi_def_cfa_offset 24 + @ sp needed + pop {r4, r5, r6, r7, r8, pc} +.LVL9: +.L4: + .cfi_restore_state + .loc 1 97 0 + add r3, sp, #4 + mov r2, r7 + mov r1, r6 + mov r0, r5 +.LVL10: + bl fdt_getprop +.LVL11: + .loc 1 98 0 + mov r1, r0 + mov r0, r8 +.LVL12: + bl printf +.LVL13: + .loc 1 96 0 + mov r1, r6 + mov r0, r5 + bl fdt_next_subnode +.LVL14: + mov r6, r0 +.LVL15: + b .L3 +.LVL16: +.L2: + .loc 1 104 0 + mov r0, r5 +.LVL17: + add r3, sp, #4 + mov r2, r8 + mov r1, r4 + bl fdt_getprop +.LVL18: + .loc 1 105 0 + mov r5, r0 +.LVL19: + cbz r0, .L8 + movs r4, #0 +.LVL20: +.L6: + .loc 1 111 0 + cmp r4, r7 + blt .L7 + .loc 1 119 0 + str r0, [r6] + .loc 1 120 0 + movs r4, #0 +.LVL21: + b .L1 +.LVL22: +.L7: + .loc 1 112 0 + movs r1, #0 + bl strchr +.LVL23: + .loc 1 113 0 + adds r0, r0, #1 +.LVL24: + beq .L10 + ldr r2, [sp, #4] + subs r3, r0, r5 + cmp r3, r2 + bge .L10 + .loc 1 111 0 + adds r4, r4, #1 +.LVL25: + b .L6 +.LVL26: +.L8: + .loc 1 107 0 + mvn r4, #21 +.LVL27: + b .L1 +.LVL28: +.L10: + .loc 1 115 0 + mvn r4, #6 +.LVL29: + b .L1 +.L12: + .align 2 +.L11: + .word .LC4 + .word .LC5 + .word .LC6 + .cfi_endproc +.LFE236: + .size spl_fit_get_image_name.isra.0, .-spl_fit_get_image_name.isra.0 + .section .text.spl_fit_get_image_node,"ax",%progbits + .align 1 + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_fit_get_image_node, %function +spl_fit_get_image_node: +.LFB222: + .loc 1 137 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 0, uses_anonymous_args = 0 +.LVL30: + push {r0, r1, r2, r4, r5, lr} + .cfi_def_cfa_offset 24 + .cfi_offset 4, -12 + .cfi_offset 5, -8 + .cfi_offset 14, -4 + .loc 1 137 0 + mov r5, r1 + mov r1, r2 +.LVL31: + mov r2, r3 +.LVL32: + .loc 1 142 0 + add r3, sp, #4 +.LVL33: + .loc 1 137 0 + mov r4, r0 + .loc 1 142 0 + bl spl_fit_get_image_name.isra.0 +.LVL34: + .loc 1 143 0 + cbnz r0, .L13 + .loc 1 148 0 + ldr r2, [sp, #4] + mov r1, r5 + mov r0, r4 +.LVL35: + bl fdt_subnode_offset +.LVL36: + .loc 1 149 0 + cmp r0, #0 + .loc 1 151 0 + it lt + mvnlt r0, #21 +.LVL37: +.L13: + .loc 1 155 0 + add sp, sp, #12 + .cfi_def_cfa_offset 12 + @ sp needed + pop {r4, r5, pc} + .cfi_endproc +.LFE222: + .size spl_fit_get_image_node, .-spl_fit_get_image_node + .global __aeabi_idivmod + .global __aeabi_idiv + .section .text.spl_load_fit_image,"ax",%progbits + .align 1 + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_load_fit_image, %function +spl_load_fit_image: +.LFB226: + .loc 1 215 0 + .cfi_startproc + @ args = 8, pretend = 0, frame = 48 + @ frame_needed = 0, uses_anonymous_args = 0 +.LVL38: + push {r4, r5, r6, r7, r8, r10, fp, lr} + .cfi_def_cfa_offset 32 + .cfi_offset 4, -32 + .cfi_offset 5, -28 + .cfi_offset 6, -24 + .cfi_offset 7, -20 + .cfi_offset 8, -16 + .cfi_offset 10, -12 + .cfi_offset 11, -8 + .cfi_offset 14, -4 + sub sp, sp, #56 + .cfi_def_cfa_offset 88 + .loc 1 215 0 + mov r4, r2 + ldr r5, [sp, #88] + .loc 1 225 0 + add r2, sp, #56 +.LVL39: + .loc 1 215 0 + mov r7, r3 + .loc 1 225 0 + movs r3, #255 +.LVL40: + .loc 1 215 0 + str r1, [sp, #20] + .loc 1 225 0 + strb r3, [r2, #-29]! +.LVL41: + .loc 1 242 0 + mov r1, r5 +.LVL42: + .loc 1 229 0 + ldr r3, [r0] + .loc 1 215 0 + mov r8, r0 + .loc 1 242 0 + mov r0, r4 +.LVL43: + .loc 1 215 0 + ldr r6, [sp, #92] + .loc 1 229 0 + str r3, [sp, #12] +.LVL44: + .loc 1 242 0 + bl fit_image_get_comp +.LVL45: + .loc 1 245 0 + add r2, sp, #44 + mov r1, r5 + mov r0, r4 + bl fit_image_get_load +.LVL46: + cbz r0, .L17 + .loc 1 246 0 + ldr r3, [r6, #8] + str r3, [sp, #44] +.L17: + .loc 1 248 0 + ldrb r3, [sp, #27] @ zero_extendqisi2 + cmp r3, #0 + beq .L18 + .loc 1 248 0 is_stmt 0 discriminator 1 + cmp r3, #6 + beq .L18 + .loc 1 250 0 is_stmt 1 + add r2, sp, #40 + mov r1, r5 + mov r0, r4 + bl fit_image_get_comp_addr +.LVL47: + cbz r0, .L19 + .loc 1 251 0 + ldr r3, [sp, #44] + add r3, r3, #1048576 +.L70: + .loc 1 253 0 + str r3, [sp, #40] +.L19: + .loc 1 256 0 + add r2, sp, #28 + mov r1, r5 + mov r0, r4 + bl fit_image_get_data_position +.LVL48: + cbz r0, .L20 + .loc 1 258 0 + add r2, sp, #28 + mov r1, r5 + mov r0, r4 + bl fit_image_get_data_offset +.LVL49: + cmp r0, #0 + bne .L21 + .loc 1 259 0 + ldr r3, [sp, #28] + add r7, r7, r3 +.LVL50: + str r7, [sp, #28] +.LVL51: +.L20: + .loc 1 265 0 + add r2, sp, #36 + mov r1, r5 + mov r0, r4 + bl fit_image_get_data_size +.LVL52: + cmp r0, #0 + bne .L40 + .loc 1 268 0 + ldr r7, [sp, #40] + adds r7, r7, #63 + bic r3, r7, #63 + .loc 1 270 0 + cmp r3, #-16777216 + .loc 1 268 0 + str r3, [sp, #8] +.LVL53: + .loc 1 270 0 + bcc .L22 + .loc 1 272 0 + ldr r1, [sp, #36] + movs r0, #64 + bl memalign_simple +.LVL54: + str r0, [sp, #8] +.LVL55: +.L22: +.LBB36: +.LBB37: + .loc 1 178 0 + ldr r3, [r8, #12] +.LBE37: +.LBE36: + .loc 1 274 0 + ldr r10, [sp, #36] + .loc 1 276 0 + ldr r0, [sp, #28] + .loc 1 274 0 + str r10, [sp, #32] +.LVL56: +.LBB40: +.LBB38: + .loc 1 178 0 + cmp r3, #0 + beq .L23 + .loc 1 179 0 + and fp, r0, #63 +.LVL57: +.L24: +.LBE38: +.LBE40: +.LBB41: +.LBB42: + .loc 1 187 0 + add r10, r10, fp +.LVL58: + .loc 1 189 0 + cbnz r3, .L25 + .loc 1 192 0 + ldr r1, [r8, #8] + add r0, r10, r1 + subs r0, r0, #1 + bl __aeabi_idiv +.LVL59: + mov r10, r0 +.LVL60: +.L25: +.LBE42: +.LBE41: + .loc 1 280 0 + mov r1, r5 + mov r0, r4 + bl fit_image_is_preload +.LVL61: + .loc 1 282 0 + str r0, [sp, #16] + cbz r0, .L26 + .loc 1 283 0 + ldr r2, [sp, #12] + movs r3, #1 + strb r3, [r2, #14] +.L26: + .loc 1 285 0 + ldr r3, [r8, #16] + .loc 1 286 0 + ldr r0, [sp, #28] +.LVL62: + .loc 1 285 0 + mov r7, r3 +.LBB43: +.LBB44: + .loc 1 164 0 + ldr r3, [r8, #12] + cmp r3, #0 + beq .L27 + .loc 1 165 0 + bic r0, r0, #63 +.LVL63: +.L28: +.LBE44: +.LBE43: + .loc 1 285 0 + ldr r1, [sp, #20] + mov r2, r10 + ldr r3, [sp, #8] + add r1, r1, r0 + mov r0, r8 + blx r7 +.LVL64: + cmp r10, r0 + bne .L37 + .loc 1 292 0 + ldr r3, [sp, #8] + add r3, r3, fp + str r3, [sp, #48] + .loc 1 293 0 + ldr r3, [sp, #16] + cbz r3, .L30 + .loc 1 294 0 + ldr r3, [sp, #12] + ldr r2, [sp, #12] + .loc 1 295 0 + ldr r0, .L72 + .loc 1 294 0 + ldrb r3, [r3, #14] @ zero_extendqisi2 + bic r3, r3, #1 + strb r3, [r2, #14] + .loc 1 295 0 + bl printf +.LVL65: +.L31: + .loc 1 348 0 + cbz r6, .L71 + .loc 1 349 0 + ldr r3, [sp, #44] + .loc 1 351 0 + mov r1, r5 + ldr r2, .L72+4 + mov r0, r4 + .loc 1 349 0 + str r3, [r6, #8] + .loc 1 350 0 + ldr r3, [sp, #32] + str r3, [r6, #32] + .loc 1 351 0 + bl fdt_getprop_u32 +.LVL66: + str r0, [r6, #12] +.L71: + .loc 1 354 0 + movs r0, #0 +.LVL67: +.L16: + .loc 1 355 0 + add sp, sp, #56 + .cfi_remember_state + .cfi_def_cfa_offset 32 + @ sp needed + pop {r4, r5, r6, r7, r8, r10, fp, pc} +.LVL68: +.L18: + .cfi_restore_state + .loc 1 253 0 + ldr r3, [sp, #44] + b .L70 +.LVL69: +.L23: +.LBB46: +.LBB39: + .loc 1 181 0 + ldr r1, [r8, #8] + str r3, [sp, #16] + bl __aeabi_idivmod +.LVL70: + ldr r3, [sp, #16] + mov fp, r1 + b .L24 +.LVL71: +.L27: +.LBE39: +.LBE46: +.LBB47: +.LBB45: + .loc 1 167 0 + ldr r1, [r8, #8] + bl __aeabi_idiv +.LVL72: + b .L28 +.LVL73: +.L68: +.LBE45: +.LBE47: + .loc 1 306 0 + ldr r3, [sp, #52] + str r3, [sp, #48] +.LVL74: +.L30: + .loc 1 310 0 + ldrb r3, [sp, #27] @ zero_extendqisi2 +.LBB48: +.LBB49: + .file 2 "include/image.h" + .loc 2 1006 0 + movs r2, #0 + mov r1, r5 + mov r0, r4 +.LBE49: +.LBE48: + .loc 1 310 0 + cbz r3, .L32 +.LVL75: + .loc 1 310 0 is_stmt 0 discriminator 1 + cmp r3, #6 + beq .L32 +.LVL76: +.LBB52: +.LBB50: + .loc 2 1006 0 is_stmt 1 + bl fdt_get_name +.LVL77: +.LBE50: +.LBE52: + .loc 1 313 0 + movs r3, #0 +.LBB53: +.LBB51: + .loc 2 1006 0 + mov r7, r0 +.LVL78: +.LBE51: +.LBE53: + .loc 1 313 0 + ldr r2, .L72+8 + mov r1, r5 + mov r0, r4 + .loc 1 311 0 + ldr r10, [sp, #44] + .loc 1 313 0 + bl fdt_getprop +.LVL79: + .loc 1 311 0 + ldr r3, [sp, #48] + mov r1, r7 + mov r2, r10 + str r3, [sp] + mov r3, r0 + ldr r0, .L72+12 + bl printf +.LVL80: +.L33: + .loc 1 323 0 + ldr r3, [sp, #32] + mov r1, r5 + ldr r2, [sp, #48] + mov r0, r4 + bl fit_image_verify_with_data +.LVL81: + cbz r0, .L38 + .loc 1 328 0 + add r3, sp, #32 + add r2, sp, #44 + mov r1, r5 + str r3, [sp] + mov r0, r4 + add r3, sp, #48 + str r8, [sp, #4] + bl board_fit_image_post_process +.LVL82: + .loc 1 331 0 + ldr r0, .L72+16 + bl puts +.LVL83: + .loc 1 345 0 + ldr r2, [sp, #32] + ldr r1, [sp, #48] + ldr r0, [sp, #44] + bl memcpy +.LVL84: + b .L31 +.LVL85: +.L32: +.LBB54: +.LBB55: + .loc 2 1006 0 + bl fdt_get_name +.LVL86: +.LBE55: +.LBE54: + .loc 1 316 0 + ldr r2, [sp, #44] + mov r1, r0 + ldr r0, .L72+20 + bl printf +.LVL87: + b .L33 +.LVL88: +.L37: + .loc 1 288 0 + mvn r0, #4 + b .L16 +.LVL89: +.L38: + .loc 1 325 0 + mov r0, #-1 + b .L16 +.LVL90: +.L21: + .loc 1 300 0 + add r3, sp, #32 + add r2, sp, #52 + mov r1, r5 + mov r0, r4 + bl fit_image_get_data +.LVL91: + cmp r0, #0 + beq .L68 + .loc 1 301 0 + ldr r0, .L72+24 + bl puts +.LVL92: +.L40: + .loc 1 266 0 + mvn r0, #1 +.LVL93: + b .L16 +.L73: + .align 2 +.L72: + .word .LC7 + .word .LC13 + .word .LC9 + .word .LC10 + .word .LC12 + .word .LC11 + .word .LC8 + .cfi_endproc +.LFE226: + .size spl_load_fit_image, .-spl_load_fit_image + .section .text.spl_fit_append_fdt,"ax",%progbits + .align 1 + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_fit_append_fdt, %function +spl_fit_append_fdt: +.LFB227: + .loc 1 360 0 + .cfi_startproc + @ args = 8, pretend = 0, frame = 48 + @ frame_needed = 0, uses_anonymous_args = 0 +.LVL94: + push {r4, r5, r6, r7, lr} + .cfi_def_cfa_offset 20 + .cfi_offset 4, -20 + .cfi_offset 5, -16 + .cfi_offset 6, -12 + .cfi_offset 7, -8 + .cfi_offset 14, -4 + mov r5, r3 + sub sp, sp, #60 + .cfi_def_cfa_offset 80 + .loc 1 360 0 + mov r4, r0 + mov r6, r1 + mov r7, r2 + .loc 1 365 0 + movs r3, #0 +.LVL95: + ldr r2, .L76 +.LVL96: + ldr r1, [sp, #80] +.LVL97: + mov r0, r5 +.LVL98: + bl spl_fit_get_image_node +.LVL99: + .loc 1 366 0 + cmp r0, #0 + blt .L74 + .loc 1 375 0 + ldr r2, [r4, #32] + .loc 1 376 0 + mov r1, r7 + .loc 1 375 0 + ldr r3, [r4, #8] + add r3, r3, r2 + .loc 1 376 0 + mov r2, r5 + .loc 1 375 0 + str r3, [sp, #20] + .loc 1 376 0 + add r3, sp, #12 + stm sp, {r0, r3} + mov r0, r6 +.LVL100: + ldr r3, [sp, #84] + bl spl_load_fit_image +.LVL101: + .loc 1 379 0 + cmp r0, #0 + blt .L74 + .loc 1 383 0 + ldr r0, [sp, #20] +.LVL102: + .loc 1 386 0 + mov r1, #8192 + .loc 1 383 0 + str r0, [r4, #20] + .loc 1 386 0 + bl fdt_shrink_to_minimum +.LVL103: +.L74: + .loc 1 390 0 + add sp, sp, #60 + .cfi_def_cfa_offset 20 + @ sp needed + pop {r4, r5, r6, r7, pc} +.LVL104: +.L77: + .align 2 +.L76: + .word .LC0 + .cfi_endproc +.LFE227: + .size spl_fit_append_fdt, .-spl_fit_append_fdt + .section .text.spl_fit_load_blob,"ax",%progbits + .align 1 + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_fit_load_blob, %function +spl_fit_load_blob: +.LFB231: + .loc 1 432 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 +.LVL105: + ldr r2, [r2, #4] +.LVL106: + push {r3, r4, r5, r6, r7, lr} + .cfi_def_cfa_offset 24 + .cfi_offset 3, -24 + .cfi_offset 4, -20 + .cfi_offset 5, -16 + .cfi_offset 6, -12 + .cfi_offset 7, -8 + .cfi_offset 14, -4 + .loc 1 432 0 + mov r4, r0 + mov r5, r1 + rev r2, r2 +.LVL107: + .loc 1 445 0 + addw r2, r2, #511 +.LVL108: + .loc 1 446 0 + bic r0, r2, #510 +.LVL109: + bic r0, r0, #1 + str r0, [r3] + .loc 1 465 0 + ldr r3, .L81 +.LVL110: + ldr r1, [r4, #8] +.LVL111: + subs r3, r3, r1 + subs r3, r3, r0 + .loc 1 466 0 + bic r6, r3, #63 +.LVL112: +.LBB62: +.LBB63: + .loc 1 189 0 + ldr r3, [r4, #12] + cbnz r3, .L79 + .loc 1 192 0 + add r0, r0, r1 +.LVL113: + subs r0, r0, #1 + bl __aeabi_idiv +.LVL114: +.L79: +.LBE63: +.LBE62: + .loc 1 468 0 + mov r2, r0 + ldr r7, [r4, #16] + mov r3, r6 + mov r1, r5 + mov r0, r4 + blx r7 +.LVL115: + .loc 1 471 0 + cmp r0, #0 + .loc 1 475 0 + ite ne + movne r0, r6 +.LVL116: + moveq r0, #0 + pop {r3, r4, r5, r6, r7, pc} +.LVL117: +.L82: + .align 2 +.L81: + .word 2097089 + .cfi_endproc +.LFE231: + .size spl_fit_load_blob, .-spl_fit_load_blob + .section .text.fit_config_verify,"ax",%progbits + .align 1 + .weak fit_config_verify + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type fit_config_verify, %function +fit_config_verify: +.LFB213: + .loc 1 25 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL118: + .loc 1 27 0 + movs r0, #0 +.LVL119: + bx lr + .cfi_endproc +.LFE213: + .size fit_config_verify, .-fit_config_verify + .section .text.mtd_part_parse,"ax",%progbits + .align 1 + .weak mtd_part_parse + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type mtd_part_parse, %function +mtd_part_parse: +.LFB214: + .loc 1 30 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL120: + .loc 1 32 0 + movs r0, #0 +.LVL121: + bx lr + .cfi_endproc +.LFE214: + .size mtd_part_parse, .-mtd_part_parse + .section .text.spl_get_current_slot,"ax",%progbits + .align 1 + .weak spl_get_current_slot + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_get_current_slot, %function +spl_get_current_slot: +.LFB215: + .loc 1 35 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL122: + .loc 1 37 0 + mov r0, #-1 +.LVL123: + bx lr + .cfi_endproc +.LFE215: + .size spl_get_current_slot, .-spl_get_current_slot + .section .text.spl_load_meta,"ax",%progbits + .align 1 + .weak spl_load_meta + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_load_meta, %function +spl_load_meta: +.LFB216: + .loc 1 40 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 +.LVL124: + push {r3, lr} + .cfi_def_cfa_offset 8 + .cfi_offset 3, -8 + .cfi_offset 14, -4 + .loc 1 41 0 + ldr r0, .L87 +.LVL125: + bl printf +.LVL126: + .loc 1 44 0 + mov r0, #-1 + pop {r3, pc} +.L88: + .align 2 +.L87: + .word .LC14 + .cfi_endproc +.LFE216: + .size spl_load_meta, .-spl_load_meta + .section .text.fdt_bootargs_append_ab,"ax",%progbits + .align 1 + .weak fdt_bootargs_append_ab + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type fdt_bootargs_append_ab, %function +fdt_bootargs_append_ab: +.LFB238: + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + mov r0, #-1 + bx lr + .cfi_endproc +.LFE238: + .size fdt_bootargs_append_ab, .-fdt_bootargs_append_ab + .section .text.fdt_bootargs_append,"ax",%progbits + .align 1 + .weak fdt_bootargs_append + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type fdt_bootargs_append, %function +fdt_bootargs_append: +.LFB218: + .loc 1 52 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL127: + .loc 1 54 0 + mov r0, #-1 +.LVL128: + bx lr + .cfi_endproc +.LFE218: + .size fdt_bootargs_append, .-fdt_bootargs_append + .section .text.rk_meta_bootargs_append,"ax",%progbits + .align 1 + .weak rk_meta_bootargs_append + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type rk_meta_bootargs_append, %function +rk_meta_bootargs_append: +.LFB219: + .loc 1 57 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL129: + bx lr + .cfi_endproc +.LFE219: + .size rk_meta_bootargs_append, .-rk_meta_bootargs_append + .section .text.fit_rollback_index_verify,"ax",%progbits + .align 1 + .weak fit_rollback_index_verify + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type fit_rollback_index_verify, %function +fit_rollback_index_verify: +.LFB220: + .loc 1 62 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL130: + .loc 1 63 0 + mov r1, #-1 +.LVL131: + .loc 1 67 0 + movs r0, #0 +.LVL132: + .loc 1 63 0 + str r1, [r2] + .loc 1 64 0 + str r1, [r3] + .loc 1 67 0 + bx lr + .cfi_endproc +.LFE220: + .size fit_rollback_index_verify, .-fit_rollback_index_verify + .section .text.spl_fit_standalone_release,"ax",%progbits + .align 1 + .weak spl_fit_standalone_release + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_fit_standalone_release, %function +spl_fit_standalone_release: +.LFB230: + .loc 1 425 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL133: + .loc 1 427 0 + movs r0, #0 +.LVL134: + bx lr + .cfi_endproc +.LFE230: + .size spl_fit_standalone_release, .-spl_fit_standalone_release + .section .text.spl_kernel_partition,"ax",%progbits + .align 1 + .weak spl_kernel_partition + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_kernel_partition, %function +spl_kernel_partition: +.LFB232: + .loc 1 481 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. +.LVL135: + .loc 1 483 0 + ldr r0, .L95 +.LVL136: + bx lr +.L96: + .align 2 +.L95: + .word .LC15 + .cfi_endproc +.LFE232: + .size spl_kernel_partition, .-spl_kernel_partition + .section .text.spl_load_simple_fit,"ax",%progbits + .align 1 + .global spl_load_simple_fit + .syntax unified + .thumb + .thumb_func + .fpu softvfp + .type spl_load_simple_fit, %function +spl_load_simple_fit: +.LFB235: + .loc 1 846 0 + .cfi_startproc + @ args = 0, pretend = 0, frame = 184 + @ frame_needed = 1, uses_anonymous_args = 0 +.LVL137: + push {r4, r5, r6, r7, r8, r10, fp, lr} + .cfi_def_cfa_offset 32 + .cfi_offset 4, -32 + .cfi_offset 5, -28 + .cfi_offset 6, -24 + .cfi_offset 7, -20 + .cfi_offset 8, -16 + .cfi_offset 10, -12 + .cfi_offset 11, -8 + .cfi_offset 14, -4 + sub sp, sp, #200 + .cfi_def_cfa_offset 232 + mov r5, r3 + add r7, sp, #16 + .cfi_def_cfa 7, 216 +.LVL138: + .loc 1 846 0 + mov r4, r0 + ldr r3, [r3] +.LVL139: + mov fp, r1 + str r2, [r7, #24] +.LVL140: + .loc 1 862 0 + ldr r2, .L174 +.LVL141: + rev r3, r3 +.LVL142: + cmp r3, r2 + str r2, [r7] + beq .L98 + .loc 1 863 0 + ldr r0, .L174+4 +.LVL143: +.L173: +.LBB84: +.LBB85: + .loc 1 658 0 + bl printf +.LVL144: +.L172: + .loc 1 680 0 + mvn r3, #21 + b .L97 +.LVL145: +.L98: +.LBE85: +.LBE84: + .loc 1 867 0 + ldr r3, [r0, #28] + cmp r3, #2 + bne .L100 + .loc 1 868 0 + bl spl_load_meta +.LVL146: +.L100: +.LBB97: +.LBB93: + .loc 1 632 0 + mov r2, r5 + add r3, r7, #40 + ldr r1, [r7, #24] + mov r0, fp + bl spl_fit_load_blob +.LVL147: + .loc 1 633 0 + mov r5, r0 +.LVL148: + cmp r0, #0 + beq .L101 + .loc 1 639 0 + ldr r1, .L174+8 + bl fdt_path_offset +.LVL149: + .loc 1 640 0 + subs r3, r0, #0 + str r3, [r7, #28] + blt .L101 + .loc 1 646 0 + bl fit_board_verify_required_sigs +.LVL150: + .loc 1 656 0 + movs r1, #0 + mov r0, r5 + bl fit_conf_get_node +.LVL151: + .loc 1 657 0 + subs r1, r0, #0 + bgt .L102 + .loc 1 658 0 + ldr r0, .L174+12 +.LVL152: + b .L173 +.LVL153: +.L102: + .loc 1 662 0 + mov r0, r5 +.LVL154: + bl fit_config_verify +.LVL155: + .loc 1 663 0 + cbz r0, .L104 + .loc 1 664 0 + mov r1, r0 + str r0, [r7, #28] +.LVL156: + ldr r0, .L174+16 +.LVL157: + bl printf +.LVL158: + ldr r3, [r7, #28] +.LVL159: +.L97: +.LBE93: +.LBE97: + .loc 1 881 0 + mov r0, r3 + adds r7, r7, #184 + .cfi_remember_state + .cfi_def_cfa_offset 32 + mov sp, r7 + .cfi_def_cfa_register 13 + @ sp needed + pop {r4, r5, r6, r7, r8, r10, fp, pc} +.LVL160: +.L104: + .cfi_restore_state +.LBB98: +.LBB94: + .loc 1 667 0 + ldr r0, .L174+20 +.LVL161: + bl printf +.LVL162: + .loc 1 672 0 + add r3, r7, #48 + add r2, r7, #44 + ldr r1, .L174+24 + mov r0, r5 + bl fit_rollback_index_verify +.LVL163: + .loc 1 674 0 + mov r6, r0 + cbz r0, .L105 + .loc 1 675 0 + mov r1, r0 + ldr r0, .L174+28 +.LVL164: + bl printf +.LVL165: + mov r3, r6 + b .L97 +.LVL166: +.L105: + .loc 1 677 0 + ldr r1, [r7, #44] + ldr r2, [r7, #48] + cmp r1, r2 + bcs .L106 + .loc 1 678 0 + ldr r0, .L174+32 +.LVL167: + bl printf +.LVL168: + b .L172 +.LVL169: +.L106: + .loc 1 684 0 + adds r6, r1, #1 + bne .L107 + adds r0, r2, #1 +.LVL170: + beq .L108 +.L107: + .loc 1 685 0 + ldr r0, .L174+36 + bl printf +.LVL171: +.L108: + .loc 1 697 0 + ldr r10, .L174+64 +.LBE94: +.LBE98: + .loc 1 846 0 + movs r6, #0 +.LVL172: +.L112: +.LBB99: +.LBB95: + .loc 1 697 0 + mov r3, r6 + mov r2, r10 + ldr r1, [r7, #28] + mov r0, r5 + bl spl_fit_get_image_node +.LVL173: + .loc 1 699 0 + subs r8, r0, #0 + blt .L109 + .loc 1 702 0 + add r3, r7, #104 + str r8, [sp] + str r3, [sp, #4] + mov r2, r5 + ldr r3, [r7, #40] + mov r0, fp +.LVL174: + ldr r1, [r7, #24] + bl spl_load_fit_image +.LVL175: + .loc 1 704 0 + mov r3, r0 + cmp r0, #0 + bne .L97 + .loc 1 707 0 + add r2, r7, #36 + mov r1, r8 + mov r0, r5 +.LVL176: + bl fit_get_desc +.LVL177: + .loc 1 708 0 + mov r3, r0 + cmp r0, #0 + bne .L97 + .loc 1 711 0 + ldr r3, [r7, #116] + .loc 1 714 0 + ldr r0, [r7, #36] +.LVL178: + .loc 1 711 0 + adds r3, r3, #1 + .loc 1 712 0 + itt eq + ldreq r3, [r7, #112] + streq r3, [r7, #116] + .loc 1 714 0 + ldr r1, [r7, #116] + bl spl_fit_standalone_release +.LVL179: + .loc 1 715 0 + mov r2, r0 + cbz r0, .L111 + .loc 1 716 0 + ldr r1, [r7, #36] + ldr r0, .L174+40 +.LVL180: + bl printf +.LVL181: +.L111: + .loc 1 696 0 + adds r6, r6, #1 +.LVL182: + b .L112 +.LVL183: +.L109: + .loc 1 730 0 + movs r3, #0 + ldr r2, .L174+44 + ldr r1, [r7, #28] + mov r0, r5 + bl spl_fit_get_image_node +.LVL184: + .loc 1 736 0 + subs r8, r0, #0 + bge .L140 + .loc 1 738 0 + movs r3, #0 + ldr r2, .L174+48 + ldr r1, [r7, #28] + mov r0, r5 +.LVL185: + bl spl_fit_get_image_node +.LVL186: + .loc 1 746 0 + ldr r3, [r4, #28] + .loc 1 738 0 + mov r8, r0 +.LVL187: + .loc 1 746 0 + cmp r3, #2 + bne .L114 + .loc 1 748 0 + ldr r0, .L174+52 +.LVL188: + bl atags_get_tag +.LVL189: + .loc 1 749 0 + cmp r0, #0 + beq .L114 + .loc 1 750 0 + ldr r6, [r0, #16] + cmp r6, #1 + bne .L114 + .loc 1 751 0 + movs r3, #5 + strb r3, [r4, #4] +.LVL190: +.L115: +.LBB86: + .loc 1 793 0 + movs r3, #0 + .loc 1 795 0 + ldr r2, .L174+48 + .loc 1 793 0 + strb r3, [r7, #35] + .loc 1 795 0 + mov r0, r5 + mov r3, r6 + ldr r1, [r7, #28] + bl spl_fit_get_image_node +.LVL191: + .loc 1 796 0 + subs r10, r0, #0 + blt .L118 +.LVL192: +.LBB87: +.LBB88: + .loc 1 420 0 + add r2, r7, #35 +.LVL193: + mov r1, r10 + mov r0, r5 +.LVL194: + bl fit_image_get_os +.LVL195: +.LBE88: +.LBE87: + .loc 1 803 0 + ldr r3, [r4, #28] + cmp r3, #2 + bne .L119 + ldrb r3, [r7, #35] @ zero_extendqisi2 + cmp r3, #17 + beq .L126 +.L119: + .loc 1 807 0 + add r8, r7, #104 + str r10, [sp] + str r8, [sp, #4] + mov r2, r5 + ldr r3, [r7, #40] + mov r0, fp + ldr r1, [r7, #24] + bl spl_load_fit_image +.LVL196: + .loc 1 809 0 + cmp r0, #0 + blt .L126 + .loc 1 812 0 + ldrb r3, [r7, #35] @ zero_extendqisi2 + cmp r3, #17 + bne .L121 + .loc 1 813 0 + ldr r3, [r7, #40] + mov r1, fp + mov r0, r8 +.LVL197: + str r3, [sp, #4] + ldr r3, [r7, #28] + str r3, [sp] + mov r3, r5 + ldr r2, [r7, #24] + bl spl_fit_append_fdt +.LVL198: + .loc 1 815 0 + ldr r3, [r7, #124] + str r3, [r4, #20] +.L121: + .loc 1 822 0 + ldr r3, [r4, #12] + adds r3, r3, #1 + bne .L122 + .loc 1 823 0 + ldr r3, [r7, #116] + .loc 1 822 0 + adds r2, r3, #1 + .loc 1 824 0 + it ne + strne r3, [r4, #12] +.L122: + .loc 1 827 0 + ldr r8, [r4, #20] + cmp r8, #0 + beq .L126 +.LVL199: +.LBB89: +.LBB90: + .loc 1 400 0 + add r3, r7, #60 + mov r2, r6 + ldr r1, .L174+48 + mov r0, r5 + bl spl_fit_get_image_name.isra.0 +.LVL200: + .loc 1 402 0 + cmp r0, #0 + blt .L126 + .loc 1 405 0 + mov r3, r6 + ldr r2, .L174+48 + ldr r1, [r7, #28] + mov r0, r5 +.LVL201: + bl spl_fit_get_image_node +.LVL202: + .loc 1 407 0 + ldr r3, [r7, #60] + .loc 1 409 0 + mov r1, r0 + .loc 1 405 0 + mov r10, r0 +.LVL203: + .loc 1 409 0 + ldr r2, .L174+56 + mov r0, r5 +.LVL204: + .loc 1 407 0 + str r3, [r7, #20] + ldr r3, [r7, #112] + str r3, [r7, #16] + ldr r3, [r7, #136] + str r3, [r7, #12] + ldr r3, [r7, #116] + str r3, [r7, #8] + .loc 1 409 0 + movs r3, #0 + bl fdt_getprop +.LVL205: + .loc 1 410 0 + movs r3, #0 + .loc 1 409 0 + str r0, [r7, #4] + .loc 1 410 0 + ldr r2, .L174+60 + mov r1, r10 + mov r0, r5 + bl fdt_getprop +.LVL206: + .loc 1 407 0 + str r0, [sp, #12] + mov r1, r6 + ldr r3, [r7, #4] + mov r0, r8 + str r3, [sp, #8] + ldr r3, [r7, #8] + str r3, [sp, #4] + ldr r3, [r7, #12] + str r3, [sp] + ldr r3, [r7, #16] + ldr r2, [r7, #20] + bl fdt_record_loadable +.LVL207: +.L126: +.LBE90: +.LBE89: +.LBE86: + .loc 1 792 0 + adds r6, r6, #1 +.LVL208: + b .L115 +.LVL209: +.L114: + .loc 1 758 0 + cmp r8, #0 + blt .L101 + movs r6, #1 +.LVL210: +.L113: + .loc 1 765 0 + str r4, [sp, #4] + mov r2, r5 + str r8, [sp] + mov r0, fp + ldr r3, [r7, #40] + ldr r1, [r7, #24] + bl spl_load_fit_image +.LVL211: + .loc 1 767 0 + mov r3, r0 + cmp r0, #0 + bne .L97 +.LVL212: +.LBB91: +.LBB92: + .loc 1 420 0 + adds r2, r4, #4 +.LVL213: + mov r1, r8 + mov r0, r5 +.LVL214: + bl fit_image_get_os +.LVL215: +.LBE92: +.LBE91: + .loc 1 774 0 + cbz r0, .L116 + .loc 1 778 0 + movs r3, #17 + strb r3, [r4, #4] +.L116: + .loc 1 785 0 + ldrb r3, [r4, #4] @ zero_extendqisi2 + cmp r3, #17 + bne .L115 + .loc 1 786 0 + ldr r3, [r7, #40] + mov r1, fp + mov r0, r4 + str r3, [sp, #4] + ldr r3, [r7, #28] + str r3, [sp] + mov r3, r5 + ldr r2, [r7, #24] + bl spl_fit_append_fdt +.LVL216: + b .L115 +.LVL217: +.L140: + .loc 1 721 0 + movs r6, #0 + b .L113 +.L175: + .align 2 +.L174: + .word -804389139 + .word .LC16 + .word .LC17 + .word .LC18 + .word .LC19 + .word .LC20 + .word -237076478 + .word .LC21 + .word .LC22 + .word .LC23 + .word .LC25 + .word .LC26 + .word .LC27 + .word 1413546071 + .word .LC28 + .word .LC29 + .word .LC24 +.LVL218: +.L118: + .loc 1 838 0 + ldr r3, [r4, #12] + subs r3, r3, #1 + adds r3, r3, #3 + bls .L125 + .loc 1 839 0 + ldr r3, [r4, #8] + str r3, [r4, #12] +.L125: +.LVL219: +.LBE95: +.LBE99: +.LBB100: +.LBB101: + .loc 1 498 0 + ldr r3, .L176 + .loc 1 488 0 + str sp, [r7, #20] + .loc 1 498 0 + ldm r3, {r0, r1, r2} + add r3, r7, #48 + stm r3, {r0, r1, r2} +.LVL220: + .loc 1 500 0 + ldr r3, [fp, #8] + adds r3, r3, #7 + bic r3, r3, #7 + sub sp, sp, r3 +.LVL221: + .loc 1 507 0 + ldr r3, [r4, #28] + .loc 1 500 0 + add r6, sp, #16 +.LVL222: + .loc 1 507 0 + cmp r3, #2 + bne .L138 +.LVL223: + .loc 1 514 0 + mov r1, fp + mov r0, r4 + bl spl_kernel_partition +.LVL224: + .loc 1 515 0 + add r2, r7, #104 + mov r1, r0 + ldr r0, [fp] +.LVL225: + bl part_get_info_by_name +.LVL226: + cmp r0, #0 + bgt .L127 + .loc 1 516 0 + ldr r1, .L176+4 + ldr r0, .L176+8 +.L170: + .loc 1 529 0 + bl printf +.LVL227: +.L171: + .loc 1 530 0 + mvn r3, #21 +.LVL228: +.L128: + ldr sp, [r7, #20] +.LVL229: +.LBE101: +.LBE100: + .loc 1 876 0 + b .L97 +.LVL230: +.L127: +.LBB105: +.LBB104: + .loc 1 519 0 + ldr r3, [r7, #104] + .loc 1 523 0 + movs r2, #1 + ldr r5, [fp, #16] + mov r0, fp + .loc 1 519 0 + str r3, [r7, #28] +.LVL231: + .loc 1 523 0 + mov r3, r6 +.LVL232: + ldr r1, [r7, #28] + blx r5 +.LVL233: + cmp r0, #1 + bne .L141 +.LVL234: + ldr r3, [r6] + .loc 1 528 0 + ldr r2, [r7] + rev r3, r3 +.LVL235: + cmp r3, r2 + beq .L129 + .loc 1 529 0 + ldr r1, .L176+4 + ldr r0, .L176+12 + b .L170 +.L129: + .loc 1 533 0 + mov r2, r6 + add r3, r7, #44 + ldr r1, [r7, #28] + mov r0, fp + bl spl_fit_load_blob +.LVL236: + .loc 1 534 0 + mov r6, r0 +.LVL237: + cmp r0, #0 + beq .L142 + .loc 1 543 0 + movs r1, #0 + bl fit_conf_get_node +.LVL238: + .loc 1 544 0 + subs r1, r0, #0 + bgt .L130 + .loc 1 545 0 + ldr r0, .L176+16 +.LVL239: + bl printf +.LVL240: + b .L171 +.LVL241: +.L130: + .loc 1 549 0 + mov r0, r6 +.LVL242: + bl fit_config_verify +.LVL243: + .loc 1 550 0 + cbz r0, .L131 + .loc 1 551 0 + mov r1, r0 + str r0, [r7, #28] +.LVL244: + ldr r0, .L176+20 +.LVL245: + bl printf +.LVL246: + ldr r3, [r7, #28] + b .L128 +.LVL247: +.L131: + str r0, [r7, #16] + .loc 1 554 0 + ldr r0, .L176+24 +.LVL248: + bl printf +.LVL249: + .loc 1 556 0 + ldr r1, .L176+28 + mov r0, r6 + bl fdt_path_offset +.LVL250: + .loc 1 557 0 + subs r3, r0, #0 + str r3, [r7, #24] +.LVL251: + blt .L143 + ldr r3, [r7, #16] + mov r5, r3 +.LVL252: +.L137: +.LBB102: + .loc 1 564 0 + add r3, r7, #48 + ldr r1, [r7, #24] + ldr r8, [r3, r5, lsl #2] + mov r0, r6 + movs r3, #0 + mov r2, r8 + bl spl_fit_get_image_node +.LVL253: + .loc 1 569 0 + cmp r0, #0 + blt .L133 + .loc 1 574 0 + add r3, r7, #60 + .loc 1 567 0 + ldr r10, [fp] + .loc 1 574 0 + mov r2, r6 + stm sp, {r0, r3} + mov r0, fp +.LVL254: + ldr r3, [r7, #44] + ldr r1, [r7, #28] + bl spl_load_fit_image +.LVL255: + .loc 1 576 0 + mov r3, r0 + cmp r0, #0 + bne .L128 + .loc 1 580 0 + ldr r1, .L176+32 + mov r0, r8 +.LVL256: + bl strcmp +.LVL257: + cbnz r0, .L134 + .loc 1 590 0 + ldr r3, [r10, #4] + .loc 1 581 0 + ldr r8, [r7, #68] + .loc 1 590 0 + cmp r3, #1 + .loc 1 581 0 + str r8, [r4, #20] + .loc 1 590 0 + bne .L135 + .loc 1 591 0 + mov r0, r10 + bl mtd_part_parse +.LVL258: + mov r1, r0 + mov r0, r8 + bl fdt_bootargs_append +.LVL259: +.L135: + .loc 1 595 0 + ldr r0, [r7, #68] + bl rk_meta_bootargs_append +.LVL260: +.L133: +.LBE102: + .loc 1 563 0 + adds r5, r5, #1 +.LVL261: + cmp r5, #3 + bne .L137 +.LVL262: +.L138: + .loc 1 615 0 + movs r3, #0 + b .L128 +.LVL263: +.L134: +.LBB103: + .loc 1 597 0 + ldr r1, .L176+36 + mov r0, r8 + bl strcmp +.LVL264: + cmp r0, #0 + bne .L133 + .loc 1 601 0 + ldr r3, [r7, #68] + str r3, [r4, #16] + b .L133 +.LVL265: +.L141: +.LBE103: + .loc 1 525 0 + mvn r3, #4 + b .L128 +.LVL266: +.L142: + .loc 1 536 0 + mvn r3, #18 + b .L128 +.LVL267: +.L143: + .loc 1 557 0 + ldr r3, [r7, #24] + b .L128 +.LVL268: +.L101: +.LBE104: +.LBE105: +.LBB106: +.LBB96: + .loc 1 635 0 + mov r3, #-1 +.LVL269: + b .L97 +.L177: + .align 2 +.L176: + .word .LANCHOR1 + .word .LANCHOR0 + .word .LC30 + .word .LC31 + .word .LC18 + .word .LC19 + .word .LC20 + .word .LC17 + .word .LC0 + .word .LC1 +.LBE96: +.LBE106: + .cfi_endproc +.LFE235: + .size spl_load_simple_fit, .-spl_load_simple_fit + .section .rodata + .align 2 + .set .LANCHOR1,. + 0 +.LC32: + .word .LC0 + .word .LC1 + .word .LC2 + .section .rodata.__func__.9886,"a",%progbits + .set .LANCHOR0,. + 0 + .type __func__.9886, %object + .size __func__.9886, 20 +__func__.9886: + .ascii "spl_load_kernel_fit\000" + .section .rodata.spl_fit_get_image_name.isra.0.str1.1,"aMS",%progbits,1 +.LC4: + .ascii "No matching DT out of these options:\012\000" +.LC5: + .ascii "description\000" +.LC6: + .ascii " %s\012\000" + .section .rodata.spl_kernel_partition.str1.1,"aMS",%progbits,1 +.LC15: + .ascii "boot\000" + .section .rodata.spl_load_fit_image.str1.1,"aMS",%progbits,1 +.LC7: + .ascii "## Preload the image OK.\012\000" +.LC8: + .ascii "Cannot get image data/size\012\000" +.LC9: + .ascii "compression\000" +.LC10: + .ascii "## Checking %s 0x%08lx (%s @0x%08lx) ... \000" +.LC11: + .ascii "## Checking %s 0x%08lx ... \000" +.LC12: + .ascii "OK\012\000" +.LC13: + .ascii "entry\000" + .section .rodata.spl_load_meta.str1.1,"aMS",%progbits,1 +.LC14: + .ascii "No load cfg image.\012\000" + .section .rodata.spl_load_simple_fit.str1.1,"aMS",%progbits,1 +.LC16: + .ascii "Not fit magic\012\000" +.LC17: + .ascii "/images\000" +.LC18: + .ascii "No default config node\012\000" +.LC19: + .ascii "fit verify configure failed, ret=%d\012\000" +.LC20: + .ascii "\012\000" +.LC21: + .ascii "fit failed to get rollback index, ret=%d\012\000" +.LC22: + .ascii "fit reject rollback: %d < %d(min)\012\000" +.LC23: + .ascii "rollback index: %d >= %d(min), OK\012\000" +.LC24: + .ascii "standalone\000" +.LC25: + .ascii "%s: start standalone fail, ret=%d\012\000" +.LC26: + .ascii "firmware\000" +.LC27: + .ascii "loadables\000" +.LC28: + .ascii "type\000" +.LC29: + .ascii "os\000" +.LC30: + .ascii "%s: no partition\012\000" +.LC31: + .ascii "%s: Not fit magic\012\000" + .section .rodata.str1.1,"aMS",%progbits,1 +.LC0: + .ascii "fdt\000" +.LC1: + .ascii "kernel\000" +.LC2: + .ascii "ramdisk\000" + .text +.Letext0: + .file 3 "include/common.h" + .file 4 "./arch/arm/include/asm/types.h" + .file 5 "./arch/arm/include/asm/posix_types.h" + .file 6 "include/linux/types.h" + .file 7 "include/errno.h" + .file 8 "include/linux/string.h" + .file 9 "include/efi.h" + .file 10 "include/blk.h" + .file 11 "include/ide.h" + .file 12 "include/part.h" + .file 13 "include/flash.h" + .file 14 "include/lmb.h" + .file 15 "include/asm-generic/u-boot.h" + .file 16 "./arch/arm/include/asm/u-boot-arm.h" + .file 17 "include/linux/libfdt_env.h" + .file 18 "include/linux/../../scripts/dtc/libfdt/fdt.h" + .file 19 "include/linux/libfdt.h" + .file 20 "include/u-boot/sha1.h" + .file 21 "include/u-boot/sha256.h" + .file 22 "include/net.h" + .file 23 "include/malloc.h" + .file 24 "./arch/arm/include/asm/spl.h" + .file 25 "include/spl.h" + .file 26 "./arch/arm/include/asm/arch/rk_atags.h" + .file 27 "include/linux/byteorder/swab.h" + .file 28 "include/linux/../../scripts/dtc/libfdt/libfdt.h" + .file 29 "include/fdt_support.h" + .file 30 "include/stdio.h" + .section .debug_info,"",%progbits +.Ldebug_info0: + .4byte 0x3138 + .2byte 0x4 + .4byte .Ldebug_abbrev0 + .byte 0x4 + .uleb128 0x1 + .4byte .LASF460 + .byte 0xc + .4byte .LASF461 + .4byte .LASF462 + .4byte .Ldebug_ranges0+0xb8 + .4byte 0 + .4byte .Ldebug_line0 + .uleb128 0x2 + .4byte .LASF4 + .byte 0x3 + .byte 0xd + .4byte 0x30 + .uleb128 0x3 + .byte 0x1 + .byte 0x8 + .4byte .LASF0 + .uleb128 0x3 + .byte 0x4 + .byte 0x7 + .4byte .LASF1 + .uleb128 0x3 + .byte 0x2 + .byte 0x7 + .4byte .LASF2 + .uleb128 0x4 + .4byte .LASF24 + .byte 0x7 + .byte 0xc + .4byte 0x50 + .uleb128 0x5 + .byte 0x4 + .byte 0x5 + .ascii "int\000" + .uleb128 0x3 + .byte 0x1 + .byte 0x6 + .4byte .LASF3 + .uleb128 0x2 + .4byte .LASF5 + .byte 0x4 + .byte 0xc + .4byte 0x30 + .uleb128 0x3 + .byte 0x2 + .byte 0x5 + .4byte .LASF6 + .uleb128 0x2 + .4byte .LASF7 + .byte 0x4 + .byte 0x12 + .4byte 0x7b + .uleb128 0x3 + .byte 0x4 + .byte 0x7 + .4byte .LASF8 + .uleb128 0x3 + .byte 0x8 + .byte 0x5 + .4byte .LASF9 + .uleb128 0x3 + .byte 0x8 + .byte 0x7 + .4byte .LASF10 + .uleb128 0x6 + .ascii "u8\000" + .byte 0x4 + .byte 0x1f + .4byte 0x30 + .uleb128 0x7 + .4byte 0x90 + .uleb128 0x6 + .ascii "u32\000" + .byte 0x4 + .byte 0x25 + .4byte 0x7b + .uleb128 0x6 + .ascii "u64\000" + .byte 0x4 + .byte 0x28 + .4byte 0x89 + .uleb128 0x2 + .4byte .LASF11 + .byte 0x4 + .byte 0x35 + .4byte 0x37 + .uleb128 0x2 + .4byte .LASF12 + .byte 0x4 + .byte 0x36 + .4byte 0x37 + .uleb128 0x3 + .byte 0x4 + .byte 0x7 + .4byte .LASF13 + .uleb128 0x7 + .4byte 0xcb + .uleb128 0x8 + .byte 0x4 + .4byte 0xe4 + .uleb128 0x3 + .byte 0x1 + .byte 0x8 + .4byte .LASF14 + .uleb128 0x7 + .4byte 0xdd + .uleb128 0x3 + .byte 0x4 + .byte 0x5 + .4byte .LASF15 + .uleb128 0x2 + .4byte .LASF16 + .byte 0x5 + .byte 0x25 + .4byte 0x7b + .uleb128 0x8 + .byte 0x4 + .4byte 0xdd + .uleb128 0x2 + .4byte .LASF17 + .byte 0x6 + .byte 0x1b + .4byte 0x37 + .uleb128 0x2 + .4byte .LASF18 + .byte 0x6 + .byte 0x35 + .4byte 0xf0 + .uleb128 0x2 + .4byte .LASF19 + .byte 0x6 + .byte 0x59 + .4byte 0x3e + .uleb128 0x2 + .4byte .LASF20 + .byte 0x6 + .byte 0x5b + .4byte 0x37 + .uleb128 0x2 + .4byte .LASF21 + .byte 0x6 + .byte 0x69 + .4byte 0x5e + .uleb128 0x7 + .4byte 0x12d + .uleb128 0x2 + .4byte .LASF22 + .byte 0x6 + .byte 0x6b + .4byte 0x70 + .uleb128 0x2 + .4byte .LASF23 + .byte 0x6 + .byte 0x97 + .4byte 0x70 + .uleb128 0x9 + .byte 0x4 + .uleb128 0x4 + .4byte .LASF25 + .byte 0x8 + .byte 0xb + .4byte 0xfb + .uleb128 0xa + .byte 0x10 + .byte 0x9 + .byte 0x1f + .4byte 0x173 + .uleb128 0xb + .ascii "b\000" + .byte 0x9 + .byte 0x20 + .4byte 0x173 + .byte 0 + .byte 0 + .uleb128 0xc + .4byte 0x90 + .4byte 0x183 + .uleb128 0xd + .4byte 0xcb + .byte 0xf + .byte 0 + .uleb128 0x2 + .4byte .LASF26 + .byte 0x9 + .byte 0x21 + .4byte 0x160 + .uleb128 0xc + .4byte 0x9f + .4byte 0x19e + .uleb128 0xd + .4byte 0xcb + .byte 0x4 + .byte 0 + .uleb128 0x3 + .byte 0x1 + .byte 0x2 + .4byte .LASF27 + .uleb128 0xc + .4byte 0xdd + .4byte 0x1b0 + .uleb128 0xe + .byte 0 + .uleb128 0xf + .4byte .LASF28 + .byte 0x9 + .2byte 0x140 + .4byte 0x1a5 + .uleb128 0xf + .4byte .LASF29 + .byte 0x9 + .2byte 0x143 + .4byte 0x1a5 + .uleb128 0xf + .4byte .LASF30 + .byte 0x9 + .2byte 0x143 + .4byte 0x1a5 + .uleb128 0x2 + .4byte .LASF31 + .byte 0xa + .byte 0x11 + .4byte 0x122 + .uleb128 0x10 + .4byte .LASF50 + .byte 0x4 + .4byte 0x7b + .byte 0xa + .byte 0x18 + .4byte 0x25c + .uleb128 0x11 + .4byte .LASF32 + .byte 0 + .uleb128 0x11 + .4byte .LASF33 + .byte 0x1 + .uleb128 0x11 + .4byte .LASF34 + .byte 0x2 + .uleb128 0x11 + .4byte .LASF35 + .byte 0x3 + .uleb128 0x11 + .4byte .LASF36 + .byte 0x4 + .uleb128 0x11 + .4byte .LASF37 + .byte 0x5 + .uleb128 0x11 + .4byte .LASF38 + .byte 0x6 + .uleb128 0x11 + .4byte .LASF39 + .byte 0x7 + .uleb128 0x11 + .4byte .LASF40 + .byte 0x8 + .uleb128 0x11 + .4byte .LASF41 + .byte 0x9 + .uleb128 0x11 + .4byte .LASF42 + .byte 0xa + .uleb128 0x11 + .4byte .LASF43 + .byte 0xb + .uleb128 0x11 + .4byte .LASF44 + .byte 0xc + .uleb128 0x11 + .4byte .LASF45 + .byte 0xd + .uleb128 0x11 + .4byte .LASF46 + .byte 0xe + .uleb128 0x11 + .4byte .LASF47 + .byte 0xf + .uleb128 0x11 + .4byte .LASF48 + .byte 0x10 + .uleb128 0x11 + .4byte .LASF49 + .byte 0x11 + .byte 0 + .uleb128 0x10 + .4byte .LASF51 + .byte 0x4 + .4byte 0x7b + .byte 0xa + .byte 0x3d + .4byte 0x285 + .uleb128 0x11 + .4byte .LASF52 + .byte 0 + .uleb128 0x11 + .4byte .LASF53 + .byte 0x1 + .uleb128 0x11 + .4byte .LASF54 + .byte 0x2 + .uleb128 0x11 + .4byte .LASF55 + .byte 0x3 + .byte 0 + .uleb128 0x12 + .byte 0x10 + .byte 0xa + .byte 0x62 + .4byte 0x2a4 + .uleb128 0x13 + .4byte .LASF56 + .byte 0xa + .byte 0x63 + .4byte 0x13d + .uleb128 0x13 + .4byte .LASF57 + .byte 0xa + .byte 0x64 + .4byte 0x183 + .byte 0 + .uleb128 0x14 + .4byte .LASF72 + .byte 0x7c + .byte 0xa + .byte 0x49 + .4byte 0x383 + .uleb128 0x15 + .4byte .LASF50 + .byte 0xa + .byte 0x4e + .4byte 0x1df + .byte 0 + .uleb128 0x15 + .4byte .LASF58 + .byte 0xa + .byte 0x4f + .4byte 0x50 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF59 + .byte 0xa + .byte 0x50 + .4byte 0x30 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF60 + .byte 0xa + .byte 0x51 + .4byte 0x30 + .byte 0x9 + .uleb128 0xb + .ascii "lun\000" + .byte 0xa + .byte 0x52 + .4byte 0x30 + .byte 0xa + .uleb128 0x15 + .4byte .LASF61 + .byte 0xa + .byte 0x53 + .4byte 0x30 + .byte 0xb + .uleb128 0x15 + .4byte .LASF62 + .byte 0xa + .byte 0x54 + .4byte 0x30 + .byte 0xc + .uleb128 0x15 + .4byte .LASF63 + .byte 0xa + .byte 0x55 + .4byte 0x30 + .byte 0xd + .uleb128 0x15 + .4byte .LASF64 + .byte 0xa + .byte 0x56 + .4byte 0x30 + .byte 0xe + .uleb128 0xb + .ascii "lba\000" + .byte 0xa + .byte 0x5b + .4byte 0x1d4 + .byte 0x10 + .uleb128 0x15 + .4byte .LASF65 + .byte 0xa + .byte 0x5c + .4byte 0x37 + .byte 0x14 + .uleb128 0x15 + .4byte .LASF66 + .byte 0xa + .byte 0x5d + .4byte 0x50 + .byte 0x18 + .uleb128 0x15 + .4byte .LASF67 + .byte 0xa + .byte 0x5e + .4byte 0x383 + .byte 0x1c + .uleb128 0x15 + .4byte .LASF68 + .byte 0xa + .byte 0x5f + .4byte 0x393 + .byte 0x45 + .uleb128 0x15 + .4byte .LASF69 + .byte 0xa + .byte 0x60 + .4byte 0x3a3 + .byte 0x5a + .uleb128 0x15 + .4byte .LASF51 + .byte 0xa + .byte 0x61 + .4byte 0x25c + .byte 0x64 + .uleb128 0x16 + .4byte 0x285 + .byte 0x68 + .uleb128 0x15 + .4byte .LASF70 + .byte 0xa + .byte 0x6c + .4byte 0x3b8 + .byte 0x78 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0x393 + .uleb128 0xd + .4byte 0xcb + .byte 0x28 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0x3a3 + .uleb128 0xd + .4byte 0xcb + .byte 0x14 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0x3b3 + .uleb128 0xd + .4byte 0xcb + .byte 0x8 + .byte 0 + .uleb128 0x17 + .4byte .LASF84 + .uleb128 0x8 + .byte 0x4 + .4byte 0x3b3 + .uleb128 0x8 + .byte 0x4 + .4byte 0x3c4 + .uleb128 0x18 + .uleb128 0xc + .4byte 0x122 + .4byte 0x3d0 + .uleb128 0xe + .byte 0 + .uleb128 0x4 + .4byte .LASF71 + .byte 0xb + .byte 0x10 + .4byte 0x3c5 + .uleb128 0xc + .4byte 0x30 + .4byte 0x3eb + .uleb128 0xd + .4byte 0xcb + .byte 0x5 + .byte 0 + .uleb128 0x14 + .4byte .LASF73 + .byte 0x8 + .byte 0xc + .byte 0xf + .4byte 0x410 + .uleb128 0x15 + .4byte .LASF74 + .byte 0xc + .byte 0x10 + .4byte 0xfb + .byte 0 + .uleb128 0x15 + .4byte .LASF75 + .byte 0xc + .byte 0x11 + .4byte 0x429 + .byte 0x4 + .byte 0 + .uleb128 0x7 + .4byte 0x3eb + .uleb128 0x19 + .4byte 0x50 + .4byte 0x429 + .uleb128 0x1a + .4byte 0x50 + .uleb128 0x1a + .4byte 0x50 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0x415 + .uleb128 0x14 + .4byte .LASF76 + .byte 0x50 + .byte 0xc + .byte 0x3e + .4byte 0x484 + .uleb128 0x15 + .4byte .LASF77 + .byte 0xc + .byte 0x3f + .4byte 0x1d4 + .byte 0 + .uleb128 0x15 + .4byte .LASF78 + .byte 0xc + .byte 0x40 + .4byte 0x1d4 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF65 + .byte 0xc + .byte 0x41 + .4byte 0x122 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF74 + .byte 0xc + .byte 0x42 + .4byte 0x484 + .byte 0xc + .uleb128 0x15 + .4byte .LASF62 + .byte 0xc + .byte 0x43 + .4byte 0x484 + .byte 0x2c + .uleb128 0x15 + .4byte .LASF79 + .byte 0xc + .byte 0x44 + .4byte 0x50 + .byte 0x4c + .byte 0 + .uleb128 0xc + .4byte 0x25 + .4byte 0x494 + .uleb128 0xd + .4byte 0xcb + .byte 0x1f + .byte 0 + .uleb128 0x2 + .4byte .LASF80 + .byte 0xc + .byte 0x4e + .4byte 0x42f + .uleb128 0xc + .4byte 0x410 + .4byte 0x4aa + .uleb128 0xe + .byte 0 + .uleb128 0x7 + .4byte 0x49f + .uleb128 0x4 + .4byte .LASF73 + .byte 0xc + .byte 0xe1 + .4byte 0x4aa + .uleb128 0x8 + .byte 0x4 + .4byte 0x2a4 + .uleb128 0x1b + .2byte 0xa10 + .byte 0xd + .byte 0x13 + .4byte 0x514 + .uleb128 0x15 + .4byte .LASF78 + .byte 0xd + .byte 0x14 + .4byte 0x122 + .byte 0 + .uleb128 0x15 + .4byte .LASF81 + .byte 0xd + .byte 0x15 + .4byte 0x117 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF82 + .byte 0xd + .byte 0x16 + .4byte 0x122 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF77 + .byte 0xd + .byte 0x17 + .4byte 0x514 + .byte 0xc + .uleb128 0x1c + .4byte .LASF83 + .byte 0xd + .byte 0x18 + .4byte 0x525 + .2byte 0x80c + .uleb128 0x1d + .ascii "mtd\000" + .byte 0xd + .byte 0x31 + .4byte 0x53b + .2byte 0xa0c + .byte 0 + .uleb128 0xc + .4byte 0x122 + .4byte 0x525 + .uleb128 0x1e + .4byte 0xcb + .2byte 0x1ff + .byte 0 + .uleb128 0xc + .4byte 0x25 + .4byte 0x536 + .uleb128 0x1e + .4byte 0xcb + .2byte 0x1ff + .byte 0 + .uleb128 0x17 + .4byte .LASF85 + .uleb128 0x8 + .byte 0x4 + .4byte 0x536 + .uleb128 0x2 + .4byte .LASF86 + .byte 0xd + .byte 0x37 + .4byte 0x4c0 + .uleb128 0xc + .4byte 0x541 + .4byte 0x557 + .uleb128 0xe + .byte 0 + .uleb128 0x4 + .4byte .LASF87 + .byte 0xd + .byte 0x39 + .4byte 0x54c + .uleb128 0x3 + .byte 0x8 + .byte 0x4 + .4byte .LASF88 + .uleb128 0x14 + .4byte .LASF89 + .byte 0x8 + .byte 0xe + .byte 0x10 + .4byte 0x58e + .uleb128 0x15 + .4byte .LASF90 + .byte 0xe + .byte 0x11 + .4byte 0xb5 + .byte 0 + .uleb128 0x15 + .4byte .LASF78 + .byte 0xe + .byte 0x12 + .4byte 0xc0 + .byte 0x4 + .byte 0 + .uleb128 0x14 + .4byte .LASF91 + .byte 0x90 + .byte 0xe + .byte 0x15 + .4byte 0x5bf + .uleb128 0xb + .ascii "cnt\000" + .byte 0xe + .byte 0x16 + .4byte 0x37 + .byte 0 + .uleb128 0x15 + .4byte .LASF78 + .byte 0xe + .byte 0x17 + .4byte 0xc0 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF92 + .byte 0xe + .byte 0x18 + .4byte 0x5bf + .byte 0x8 + .byte 0 + .uleb128 0xc + .4byte 0x569 + .4byte 0x5cf + .uleb128 0xd + .4byte 0xcb + .byte 0x10 + .byte 0 + .uleb128 0x1f + .ascii "lmb\000" + .2byte 0x120 + .byte 0xe + .byte 0x1b + .4byte 0x5f5 + .uleb128 0x15 + .4byte .LASF93 + .byte 0xe + .byte 0x1c + .4byte 0x58e + .byte 0 + .uleb128 0x15 + .4byte .LASF94 + .byte 0xe + .byte 0x1d + .4byte 0x58e + .byte 0x90 + .byte 0 + .uleb128 0x20 + .ascii "lmb\000" + .byte 0xe + .byte 0x20 + .4byte 0x5cf + .uleb128 0xa + .byte 0x10 + .byte 0xf + .byte 0x5b + .4byte 0x621 + .uleb128 0x15 + .4byte .LASF77 + .byte 0xf + .byte 0x5c + .4byte 0xaa + .byte 0 + .uleb128 0x15 + .4byte .LASF78 + .byte 0xf + .byte 0x5d + .4byte 0xaa + .byte 0x8 + .byte 0 + .uleb128 0x14 + .4byte .LASF95 + .byte 0x68 + .byte 0xf + .byte 0x1b + .4byte 0x712 + .uleb128 0x15 + .4byte .LASF96 + .byte 0xf + .byte 0x1c + .4byte 0x37 + .byte 0 + .uleb128 0x15 + .4byte .LASF97 + .byte 0xf + .byte 0x1d + .4byte 0xc0 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF98 + .byte 0xf + .byte 0x1e + .4byte 0x37 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF99 + .byte 0xf + .byte 0x1f + .4byte 0x37 + .byte 0xc + .uleb128 0x15 + .4byte .LASF100 + .byte 0xf + .byte 0x20 + .4byte 0x37 + .byte 0x10 + .uleb128 0x15 + .4byte .LASF101 + .byte 0xf + .byte 0x21 + .4byte 0x37 + .byte 0x14 + .uleb128 0x15 + .4byte .LASF102 + .byte 0xf + .byte 0x22 + .4byte 0x37 + .byte 0x18 + .uleb128 0x15 + .4byte .LASF103 + .byte 0xf + .byte 0x24 + .4byte 0x37 + .byte 0x1c + .uleb128 0x15 + .4byte .LASF104 + .byte 0xf + .byte 0x25 + .4byte 0x37 + .byte 0x20 + .uleb128 0x15 + .4byte .LASF105 + .byte 0xf + .byte 0x26 + .4byte 0x37 + .byte 0x24 + .uleb128 0x15 + .4byte .LASF106 + .byte 0xf + .byte 0x31 + .4byte 0x37 + .byte 0x28 + .uleb128 0x15 + .4byte .LASF107 + .byte 0xf + .byte 0x32 + .4byte 0x37 + .byte 0x2c + .uleb128 0x15 + .4byte .LASF108 + .byte 0xf + .byte 0x33 + .4byte 0x3db + .byte 0x30 + .uleb128 0x15 + .4byte .LASF109 + .byte 0xf + .byte 0x34 + .4byte 0x3e + .byte 0x36 + .uleb128 0x15 + .4byte .LASF110 + .byte 0xf + .byte 0x35 + .4byte 0x37 + .byte 0x38 + .uleb128 0x15 + .4byte .LASF111 + .byte 0xf + .byte 0x36 + .4byte 0x37 + .byte 0x3c + .uleb128 0x15 + .4byte .LASF112 + .byte 0xf + .byte 0x57 + .4byte 0x122 + .byte 0x40 + .uleb128 0x15 + .4byte .LASF113 + .byte 0xf + .byte 0x58 + .4byte 0x122 + .byte 0x44 + .uleb128 0x15 + .4byte .LASF114 + .byte 0xf + .byte 0x5e + .4byte 0x712 + .byte 0x48 + .byte 0 + .uleb128 0xc + .4byte 0x600 + .4byte 0x722 + .uleb128 0xd + .4byte 0xcb + .byte 0x1 + .byte 0 + .uleb128 0x2 + .4byte .LASF115 + .byte 0xf + .byte 0x60 + .4byte 0x621 + .uleb128 0x4 + .4byte .LASF116 + .byte 0x10 + .byte 0x13 + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF117 + .byte 0x10 + .byte 0x14 + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF118 + .byte 0x10 + .byte 0x15 + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF119 + .byte 0x10 + .byte 0x16 + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF120 + .byte 0x10 + .byte 0x17 + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF121 + .byte 0x10 + .byte 0x18 + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF122 + .byte 0x10 + .byte 0x19 + .4byte 0x122 + .uleb128 0x2 + .4byte .LASF123 + .byte 0x11 + .byte 0x11 + .4byte 0x148 + .uleb128 0x14 + .4byte .LASF124 + .byte 0x28 + .byte 0x12 + .byte 0x39 + .4byte 0x80a + .uleb128 0x15 + .4byte .LASF125 + .byte 0x12 + .byte 0x3a + .4byte 0x77a + .byte 0 + .uleb128 0x15 + .4byte .LASF126 + .byte 0x12 + .byte 0x3b + .4byte 0x77a + .byte 0x4 + .uleb128 0x15 + .4byte .LASF127 + .byte 0x12 + .byte 0x3c + .4byte 0x77a + .byte 0x8 + .uleb128 0x15 + .4byte .LASF128 + .byte 0x12 + .byte 0x3d + .4byte 0x77a + .byte 0xc + .uleb128 0x15 + .4byte .LASF129 + .byte 0x12 + .byte 0x3e + .4byte 0x77a + .byte 0x10 + .uleb128 0x15 + .4byte .LASF130 + .byte 0x12 + .byte 0x3f + .4byte 0x77a + .byte 0x14 + .uleb128 0x15 + .4byte .LASF131 + .byte 0x12 + .byte 0x40 + .4byte 0x77a + .byte 0x18 + .uleb128 0x15 + .4byte .LASF132 + .byte 0x12 + .byte 0x43 + .4byte 0x77a + .byte 0x1c + .uleb128 0x15 + .4byte .LASF133 + .byte 0x12 + .byte 0x46 + .4byte 0x77a + .byte 0x20 + .uleb128 0x15 + .4byte .LASF134 + .byte 0x12 + .byte 0x49 + .4byte 0x77a + .byte 0x24 + .byte 0 + .uleb128 0xf + .4byte .LASF135 + .byte 0x13 + .2byte 0x136 + .4byte 0x816 + .uleb128 0x8 + .byte 0x4 + .4byte 0x785 + .uleb128 0x21 + .byte 0x4 + .4byte 0x7b + .byte 0x2 + .byte 0x83 + .4byte 0x8d1 + .uleb128 0x11 + .4byte .LASF136 + .byte 0 + .uleb128 0x11 + .4byte .LASF137 + .byte 0x1 + .uleb128 0x11 + .4byte .LASF138 + .byte 0x2 + .uleb128 0x11 + .4byte .LASF139 + .byte 0x3 + .uleb128 0x11 + .4byte .LASF140 + .byte 0x4 + .uleb128 0x11 + .4byte .LASF141 + .byte 0x5 + .uleb128 0x11 + .4byte .LASF142 + .byte 0x6 + .uleb128 0x11 + .4byte .LASF143 + .byte 0x7 + .uleb128 0x11 + .4byte .LASF144 + .byte 0x8 + .uleb128 0x11 + .4byte .LASF145 + .byte 0x9 + .uleb128 0x11 + .4byte .LASF146 + .byte 0xa + .uleb128 0x11 + .4byte .LASF147 + .byte 0xb + .uleb128 0x11 + .4byte .LASF148 + .byte 0xc + .uleb128 0x11 + .4byte .LASF149 + .byte 0xd + .uleb128 0x11 + .4byte .LASF150 + .byte 0xe + .uleb128 0x11 + .4byte .LASF151 + .byte 0xf + .uleb128 0x11 + .4byte .LASF152 + .byte 0x10 + .uleb128 0x11 + .4byte .LASF153 + .byte 0x11 + .uleb128 0x11 + .4byte .LASF154 + .byte 0x12 + .uleb128 0x11 + .4byte .LASF155 + .byte 0x13 + .uleb128 0x11 + .4byte .LASF156 + .byte 0x14 + .uleb128 0x11 + .4byte .LASF157 + .byte 0x15 + .uleb128 0x11 + .4byte .LASF158 + .byte 0x16 + .uleb128 0x11 + .4byte .LASF159 + .byte 0x17 + .uleb128 0x11 + .4byte .LASF160 + .byte 0x18 + .uleb128 0x11 + .4byte .LASF161 + .byte 0x19 + .uleb128 0x11 + .4byte .LASF162 + .byte 0x1a + .uleb128 0x11 + .4byte .LASF163 + .byte 0x1b + .byte 0 + .uleb128 0x21 + .byte 0x4 + .4byte 0x7b + .byte 0x2 + .byte 0xf3 + .4byte 0x9b0 + .uleb128 0x11 + .4byte .LASF164 + .byte 0 + .uleb128 0x11 + .4byte .LASF165 + .byte 0x1 + .uleb128 0x11 + .4byte .LASF166 + .byte 0x2 + .uleb128 0x11 + .4byte .LASF167 + .byte 0x3 + .uleb128 0x11 + .4byte .LASF168 + .byte 0x4 + .uleb128 0x11 + .4byte .LASF169 + .byte 0x5 + .uleb128 0x11 + .4byte .LASF170 + .byte 0x6 + .uleb128 0x11 + .4byte .LASF171 + .byte 0x7 + .uleb128 0x11 + .4byte .LASF172 + .byte 0x8 + .uleb128 0x11 + .4byte .LASF173 + .byte 0x9 + .uleb128 0x11 + .4byte .LASF174 + .byte 0xa + .uleb128 0x11 + .4byte .LASF175 + .byte 0xb + .uleb128 0x11 + .4byte .LASF176 + .byte 0xc + .uleb128 0x11 + .4byte .LASF177 + .byte 0xd + .uleb128 0x11 + .4byte .LASF178 + .byte 0xe + .uleb128 0x11 + .4byte .LASF179 + .byte 0xf + .uleb128 0x11 + .4byte .LASF180 + .byte 0x10 + .uleb128 0x11 + .4byte .LASF181 + .byte 0x11 + .uleb128 0x11 + .4byte .LASF182 + .byte 0x12 + .uleb128 0x11 + .4byte .LASF183 + .byte 0x13 + .uleb128 0x11 + .4byte .LASF184 + .byte 0x14 + .uleb128 0x11 + .4byte .LASF185 + .byte 0x15 + .uleb128 0x11 + .4byte .LASF186 + .byte 0x16 + .uleb128 0x11 + .4byte .LASF187 + .byte 0x17 + .uleb128 0x11 + .4byte .LASF188 + .byte 0x18 + .uleb128 0x11 + .4byte .LASF189 + .byte 0x19 + .uleb128 0x11 + .4byte .LASF190 + .byte 0x1a + .uleb128 0x11 + .4byte .LASF191 + .byte 0x1b + .uleb128 0x11 + .4byte .LASF192 + .byte 0x1c + .uleb128 0x11 + .4byte .LASF193 + .byte 0x1d + .uleb128 0x11 + .4byte .LASF194 + .byte 0x1e + .uleb128 0x11 + .4byte .LASF195 + .byte 0x1f + .uleb128 0x11 + .4byte .LASF196 + .byte 0x20 + .uleb128 0x11 + .4byte .LASF197 + .byte 0x21 + .uleb128 0x11 + .4byte .LASF198 + .byte 0x22 + .byte 0 + .uleb128 0x22 + .byte 0x4 + .4byte 0x7b + .byte 0x2 + .2byte 0x121 + .4byte 0x9ee + .uleb128 0x11 + .4byte .LASF199 + .byte 0 + .uleb128 0x11 + .4byte .LASF200 + .byte 0x1 + .uleb128 0x11 + .4byte .LASF201 + .byte 0x2 + .uleb128 0x11 + .4byte .LASF202 + .byte 0x3 + .uleb128 0x11 + .4byte .LASF203 + .byte 0x4 + .uleb128 0x11 + .4byte .LASF204 + .byte 0x5 + .uleb128 0x11 + .4byte .LASF205 + .byte 0x6 + .uleb128 0x11 + .4byte .LASF206 + .byte 0x7 + .byte 0 + .uleb128 0x23 + .4byte .LASF207 + .byte 0x40 + .byte 0x2 + .2byte 0x137 + .4byte 0xa98 + .uleb128 0x24 + .4byte .LASF208 + .byte 0x2 + .2byte 0x138 + .4byte 0x148 + .byte 0 + .uleb128 0x24 + .4byte .LASF209 + .byte 0x2 + .2byte 0x139 + .4byte 0x148 + .byte 0x4 + .uleb128 0x24 + .4byte .LASF210 + .byte 0x2 + .2byte 0x13a + .4byte 0x148 + .byte 0x8 + .uleb128 0x24 + .4byte .LASF211 + .byte 0x2 + .2byte 0x13b + .4byte 0x148 + .byte 0xc + .uleb128 0x24 + .4byte .LASF212 + .byte 0x2 + .2byte 0x13c + .4byte 0x148 + .byte 0x10 + .uleb128 0x24 + .4byte .LASF213 + .byte 0x2 + .2byte 0x13d + .4byte 0x148 + .byte 0x14 + .uleb128 0x24 + .4byte .LASF214 + .byte 0x2 + .2byte 0x13e + .4byte 0x148 + .byte 0x18 + .uleb128 0x24 + .4byte .LASF215 + .byte 0x2 + .2byte 0x13f + .4byte 0x12d + .byte 0x1c + .uleb128 0x24 + .4byte .LASF216 + .byte 0x2 + .2byte 0x140 + .4byte 0x12d + .byte 0x1d + .uleb128 0x24 + .4byte .LASF217 + .byte 0x2 + .2byte 0x141 + .4byte 0x12d + .byte 0x1e + .uleb128 0x24 + .4byte .LASF218 + .byte 0x2 + .2byte 0x142 + .4byte 0x12d + .byte 0x1f + .uleb128 0x24 + .4byte .LASF219 + .byte 0x2 + .2byte 0x143 + .4byte 0xa98 + .byte 0x20 + .byte 0 + .uleb128 0xc + .4byte 0x12d + .4byte 0xaa8 + .uleb128 0xd + .4byte 0xcb + .byte 0x1f + .byte 0 + .uleb128 0x25 + .4byte .LASF220 + .byte 0x2 + .2byte 0x144 + .4byte 0x9ee + .uleb128 0x7 + .4byte 0xaa8 + .uleb128 0x23 + .4byte .LASF221 + .byte 0x18 + .byte 0x2 + .2byte 0x146 + .4byte 0xb3b + .uleb128 0x24 + .4byte .LASF77 + .byte 0x2 + .2byte 0x147 + .4byte 0x122 + .byte 0 + .uleb128 0x26 + .ascii "end\000" + .byte 0x2 + .2byte 0x147 + .4byte 0x122 + .byte 0x4 + .uleb128 0x24 + .4byte .LASF222 + .byte 0x2 + .2byte 0x148 + .4byte 0x122 + .byte 0x8 + .uleb128 0x24 + .4byte .LASF223 + .byte 0x2 + .2byte 0x148 + .4byte 0x122 + .byte 0xc + .uleb128 0x24 + .4byte .LASF224 + .byte 0x2 + .2byte 0x149 + .4byte 0x122 + .byte 0x10 + .uleb128 0x24 + .4byte .LASF225 + .byte 0x2 + .2byte 0x14a + .4byte 0x12d + .byte 0x14 + .uleb128 0x24 + .4byte .LASF62 + .byte 0x2 + .2byte 0x14a + .4byte 0x12d + .byte 0x15 + .uleb128 0x26 + .ascii "os\000" + .byte 0x2 + .2byte 0x14a + .4byte 0x12d + .byte 0x16 + .uleb128 0x24 + .4byte .LASF226 + .byte 0x2 + .2byte 0x14b + .4byte 0x12d + .byte 0x17 + .byte 0 + .uleb128 0x25 + .4byte .LASF227 + .byte 0x2 + .2byte 0x14c + .4byte 0xab9 + .uleb128 0x27 + .4byte .LASF228 + .2byte 0x1e4 + .byte 0x2 + .2byte 0x152 + .4byte 0xcda + .uleb128 0x24 + .4byte .LASF229 + .byte 0x2 + .2byte 0x158 + .4byte 0xcda + .byte 0 + .uleb128 0x24 + .4byte .LASF230 + .byte 0x2 + .2byte 0x159 + .4byte 0xaa8 + .byte 0x4 + .uleb128 0x24 + .4byte .LASF231 + .byte 0x2 + .2byte 0x15a + .4byte 0x122 + .byte 0x44 + .uleb128 0x24 + .4byte .LASF232 + .byte 0x2 + .2byte 0x15d + .4byte 0xd7 + .byte 0x48 + .uleb128 0x24 + .4byte .LASF233 + .byte 0x2 + .2byte 0x15f + .4byte 0x153 + .byte 0x4c + .uleb128 0x24 + .4byte .LASF234 + .byte 0x2 + .2byte 0x160 + .4byte 0xd7 + .byte 0x50 + .uleb128 0x24 + .4byte .LASF235 + .byte 0x2 + .2byte 0x161 + .4byte 0x50 + .byte 0x54 + .uleb128 0x24 + .4byte .LASF236 + .byte 0x2 + .2byte 0x163 + .4byte 0x153 + .byte 0x58 + .uleb128 0x24 + .4byte .LASF237 + .byte 0x2 + .2byte 0x164 + .4byte 0xd7 + .byte 0x5c + .uleb128 0x24 + .4byte .LASF238 + .byte 0x2 + .2byte 0x165 + .4byte 0x50 + .byte 0x60 + .uleb128 0x24 + .4byte .LASF239 + .byte 0x2 + .2byte 0x167 + .4byte 0x153 + .byte 0x64 + .uleb128 0x24 + .4byte .LASF240 + .byte 0x2 + .2byte 0x168 + .4byte 0xd7 + .byte 0x68 + .uleb128 0x24 + .4byte .LASF241 + .byte 0x2 + .2byte 0x169 + .4byte 0x50 + .byte 0x6c + .uleb128 0x24 + .4byte .LASF242 + .byte 0x2 + .2byte 0x16b + .4byte 0x153 + .byte 0x70 + .uleb128 0x24 + .4byte .LASF243 + .byte 0x2 + .2byte 0x16c + .4byte 0xd7 + .byte 0x74 + .uleb128 0x24 + .4byte .LASF244 + .byte 0x2 + .2byte 0x16d + .4byte 0x50 + .byte 0x78 + .uleb128 0x26 + .ascii "os\000" + .byte 0x2 + .2byte 0x171 + .4byte 0xb3b + .byte 0x7c + .uleb128 0x26 + .ascii "ep\000" + .byte 0x2 + .2byte 0x172 + .4byte 0x122 + .byte 0x94 + .uleb128 0x24 + .4byte .LASF245 + .byte 0x2 + .2byte 0x174 + .4byte 0x122 + .byte 0x98 + .uleb128 0x24 + .4byte .LASF246 + .byte 0x2 + .2byte 0x174 + .4byte 0x122 + .byte 0x9c + .uleb128 0x24 + .4byte .LASF247 + .byte 0x2 + .2byte 0x176 + .4byte 0xfb + .byte 0xa0 + .uleb128 0x24 + .4byte .LASF248 + .byte 0x2 + .2byte 0x177 + .4byte 0x122 + .byte 0xa4 + .uleb128 0x24 + .4byte .LASF249 + .byte 0x2 + .2byte 0x179 + .4byte 0x122 + .byte 0xa8 + .uleb128 0x24 + .4byte .LASF250 + .byte 0x2 + .2byte 0x17a + .4byte 0x122 + .byte 0xac + .uleb128 0x24 + .4byte .LASF251 + .byte 0x2 + .2byte 0x17b + .4byte 0x122 + .byte 0xb0 + .uleb128 0x24 + .4byte .LASF252 + .byte 0x2 + .2byte 0x17c + .4byte 0x122 + .byte 0xb4 + .uleb128 0x26 + .ascii "kbd\000" + .byte 0x2 + .2byte 0x17d + .4byte 0xce0 + .byte 0xb8 + .uleb128 0x24 + .4byte .LASF253 + .byte 0x2 + .2byte 0x180 + .4byte 0x50 + .byte 0xbc + .uleb128 0x24 + .4byte .LASF254 + .byte 0x2 + .2byte 0x18d + .4byte 0x50 + .byte 0xc0 + .uleb128 0x26 + .ascii "lmb\000" + .byte 0x2 + .2byte 0x190 + .4byte 0x5cf + .byte 0xc4 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xaa8 + .uleb128 0x8 + .byte 0x4 + .4byte 0x722 + .uleb128 0x25 + .4byte .LASF255 + .byte 0x2 + .2byte 0x196 + .4byte 0xb47 + .uleb128 0xf + .4byte .LASF256 + .byte 0x2 + .2byte 0x198 + .4byte 0xce6 + .uleb128 0xc + .4byte 0x138 + .4byte 0xd09 + .uleb128 0xe + .byte 0 + .uleb128 0x7 + .4byte 0xcfe + .uleb128 0x4 + .4byte .LASF257 + .byte 0x14 + .byte 0x1a + .4byte 0xd09 + .uleb128 0x4 + .4byte .LASF258 + .byte 0x15 + .byte 0x7 + .4byte 0xd09 + .uleb128 0x8 + .byte 0x4 + .4byte 0x12d + .uleb128 0xc + .4byte 0xdd + .4byte 0xd3a + .uleb128 0xd + .4byte 0xcb + .byte 0x7 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0xd4a + .uleb128 0xd + .4byte 0xcb + .byte 0xf + .byte 0 + .uleb128 0xc + .4byte 0x9f + .4byte 0xd5a + .uleb128 0xd + .4byte 0xcb + .byte 0x7 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0xd6b + .uleb128 0x1e + .4byte 0xcb + .2byte 0x3ff + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0xd7b + .uleb128 0xd + .4byte 0xcb + .byte 0x1f + .byte 0 + .uleb128 0x4 + .4byte .LASF259 + .byte 0x3 + .byte 0xad + .4byte 0x122 + .uleb128 0xc + .4byte 0x90 + .4byte 0xd91 + .uleb128 0xe + .byte 0 + .uleb128 0x4 + .4byte .LASF260 + .byte 0x3 + .byte 0xaf + .4byte 0xd86 + .uleb128 0x4 + .4byte .LASF261 + .byte 0x3 + .byte 0xb0 + .4byte 0xd86 + .uleb128 0x4 + .4byte .LASF262 + .byte 0x3 + .byte 0xfe + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF263 + .byte 0x3 + .byte 0xff + .4byte 0x122 + .uleb128 0xf + .4byte .LASF264 + .byte 0x3 + .2byte 0x100 + .4byte 0x122 + .uleb128 0x14 + .4byte .LASF265 + .byte 0x4 + .byte 0x16 + .byte 0x2e + .4byte 0xde2 + .uleb128 0x15 + .4byte .LASF266 + .byte 0x16 + .byte 0x2f + .4byte 0x148 + .byte 0 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0x25 + .uleb128 0x14 + .4byte .LASF267 + .byte 0x40 + .byte 0x16 + .byte 0xa6 + .4byte 0xe85 + .uleb128 0x15 + .4byte .LASF74 + .byte 0x16 + .byte 0xa8 + .4byte 0xd3a + .byte 0 + .uleb128 0x15 + .4byte .LASF268 + .byte 0x16 + .byte 0xa9 + .4byte 0x3db + .byte 0x10 + .uleb128 0x15 + .4byte .LASF269 + .byte 0x16 + .byte 0xaa + .4byte 0xb5 + .byte 0x18 + .uleb128 0x15 + .4byte .LASF254 + .byte 0x16 + .byte 0xab + .4byte 0x50 + .byte 0x1c + .uleb128 0x15 + .4byte .LASF270 + .byte 0x16 + .byte 0xad + .4byte 0xe9f + .byte 0x20 + .uleb128 0x15 + .4byte .LASF271 + .byte 0x16 + .byte 0xae + .4byte 0xebe + .byte 0x24 + .uleb128 0x15 + .4byte .LASF272 + .byte 0x16 + .byte 0xaf + .4byte 0xed3 + .byte 0x28 + .uleb128 0x15 + .4byte .LASF273 + .byte 0x16 + .byte 0xb0 + .4byte 0xee4 + .byte 0x2c + .uleb128 0x15 + .4byte .LASF274 + .byte 0x16 + .byte 0xb4 + .4byte 0xed3 + .byte 0x30 + .uleb128 0x15 + .4byte .LASF275 + .byte 0x16 + .byte 0xb5 + .4byte 0xe99 + .byte 0x34 + .uleb128 0x15 + .4byte .LASF276 + .byte 0x16 + .byte 0xb6 + .4byte 0x50 + .byte 0x38 + .uleb128 0x15 + .4byte .LASF277 + .byte 0x16 + .byte 0xb7 + .4byte 0x153 + .byte 0x3c + .byte 0 + .uleb128 0x19 + .4byte 0x50 + .4byte 0xe99 + .uleb128 0x1a + .4byte 0xe99 + .uleb128 0x1a + .4byte 0xce0 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xde8 + .uleb128 0x8 + .byte 0x4 + .4byte 0xe85 + .uleb128 0x19 + .4byte 0x50 + .4byte 0xebe + .uleb128 0x1a + .4byte 0xe99 + .uleb128 0x1a + .4byte 0x153 + .uleb128 0x1a + .4byte 0x50 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xea5 + .uleb128 0x19 + .4byte 0x50 + .4byte 0xed3 + .uleb128 0x1a + .4byte 0xe99 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xec4 + .uleb128 0x28 + .4byte 0xee4 + .uleb128 0x1a + .4byte 0xe99 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xed9 + .uleb128 0x4 + .4byte .LASF278 + .byte 0x16 + .byte 0xbd + .4byte 0xe99 + .uleb128 0xc + .4byte 0x90 + .4byte 0xf05 + .uleb128 0xd + .4byte 0xcb + .byte 0x5 + .byte 0 + .uleb128 0xf + .4byte .LASF279 + .byte 0x16 + .2byte 0x1fd + .4byte 0xdc9 + .uleb128 0xf + .4byte .LASF280 + .byte 0x16 + .2byte 0x1fe + .4byte 0xdc9 + .uleb128 0xf + .4byte .LASF281 + .byte 0x16 + .2byte 0x200 + .4byte 0xdc9 + .uleb128 0xf + .4byte .LASF282 + .byte 0x16 + .2byte 0x205 + .4byte 0xd6b + .uleb128 0xf + .4byte .LASF283 + .byte 0x16 + .2byte 0x206 + .4byte 0xd6b + .uleb128 0xc + .4byte 0xdd + .4byte 0xf51 + .uleb128 0xd + .4byte 0xcb + .byte 0x3f + .byte 0 + .uleb128 0xf + .4byte .LASF284 + .byte 0x16 + .2byte 0x207 + .4byte 0xf41 + .uleb128 0xf + .4byte .LASF285 + .byte 0x16 + .2byte 0x209 + .4byte 0xef5 + .uleb128 0xf + .4byte .LASF286 + .byte 0x16 + .2byte 0x20a + .4byte 0xef5 + .uleb128 0xf + .4byte .LASF287 + .byte 0x16 + .2byte 0x20b + .4byte 0xdc9 + .uleb128 0xf + .4byte .LASF288 + .byte 0x16 + .2byte 0x20c + .4byte 0xdc9 + .uleb128 0xf + .4byte .LASF289 + .byte 0x16 + .2byte 0x20d + .4byte 0xde2 + .uleb128 0xc + .4byte 0xde2 + .4byte 0xfa9 + .uleb128 0xd + .4byte 0xcb + .byte 0x3 + .byte 0 + .uleb128 0xf + .4byte .LASF290 + .byte 0x16 + .2byte 0x20e + .4byte 0xf99 + .uleb128 0xf + .4byte .LASF291 + .byte 0x16 + .2byte 0x20f + .4byte 0xde2 + .uleb128 0xf + .4byte .LASF292 + .byte 0x16 + .2byte 0x210 + .4byte 0x50 + .uleb128 0xc + .4byte 0x9a + .4byte 0xfdd + .uleb128 0xd + .4byte 0xcb + .byte 0x5 + .byte 0 + .uleb128 0x7 + .4byte 0xfcd + .uleb128 0xf + .4byte .LASF293 + .byte 0x16 + .2byte 0x211 + .4byte 0xfdd + .uleb128 0xf + .4byte .LASF294 + .byte 0x16 + .2byte 0x212 + .4byte 0xfdd + .uleb128 0xf + .4byte .LASF295 + .byte 0x16 + .2byte 0x216 + .4byte 0x117 + .uleb128 0xf + .4byte .LASF296 + .byte 0x16 + .2byte 0x217 + .4byte 0x117 + .uleb128 0xf + .4byte .LASF297 + .byte 0x16 + .2byte 0x219 + .4byte 0x50 + .uleb128 0xf + .4byte .LASF298 + .byte 0x16 + .2byte 0x220 + .4byte 0xd5a + .uleb128 0xf + .4byte .LASF299 + .byte 0x16 + .2byte 0x222 + .4byte 0x9f + .uleb128 0xf + .4byte .LASF300 + .byte 0x16 + .2byte 0x224 + .4byte 0x9f + .uleb128 0x29 + .4byte .LASF301 + .byte 0x4 + .4byte 0x7b + .byte 0x16 + .2byte 0x286 + .4byte 0x106c + .uleb128 0x11 + .4byte .LASF302 + .byte 0 + .uleb128 0x11 + .4byte .LASF303 + .byte 0x1 + .uleb128 0x11 + .4byte .LASF304 + .byte 0x2 + .uleb128 0x11 + .4byte .LASF305 + .byte 0x3 + .byte 0 + .uleb128 0xf + .4byte .LASF306 + .byte 0x16 + .2byte 0x28c + .4byte 0x1042 + .uleb128 0xf + .4byte .LASF307 + .byte 0x17 + .2byte 0x3ba + .4byte 0x122 + .uleb128 0xf + .4byte .LASF308 + .byte 0x17 + .2byte 0x3bb + .4byte 0x122 + .uleb128 0xf + .4byte .LASF309 + .byte 0x17 + .2byte 0x3bc + .4byte 0x122 + .uleb128 0x4 + .4byte .LASF310 + .byte 0x18 + .byte 0x2b + .4byte 0x1a5 + .uleb128 0x4 + .4byte .LASF311 + .byte 0x18 + .byte 0x2b + .4byte 0x1a5 + .uleb128 0x14 + .4byte .LASF312 + .byte 0x2c + .byte 0x19 + .byte 0x1c + .4byte 0x1142 + .uleb128 0x15 + .4byte .LASF74 + .byte 0x19 + .byte 0x1d + .4byte 0xd7 + .byte 0 + .uleb128 0xb + .ascii "os\000" + .byte 0x19 + .byte 0x1e + .4byte 0x90 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF262 + .byte 0x19 + .byte 0x1f + .4byte 0x101 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF313 + .byte 0x19 + .byte 0x20 + .4byte 0x101 + .byte 0xc + .uleb128 0x15 + .4byte .LASF314 + .byte 0x19 + .byte 0x26 + .4byte 0x101 + .byte 0x10 + .uleb128 0x15 + .4byte .LASF315 + .byte 0x19 + .byte 0x28 + .4byte 0x153 + .byte 0x14 + .uleb128 0x15 + .4byte .LASF316 + .byte 0x19 + .byte 0x29 + .4byte 0x9f + .byte 0x18 + .uleb128 0x15 + .4byte .LASF317 + .byte 0x19 + .byte 0x2a + .4byte 0x9f + .byte 0x1c + .uleb128 0x15 + .4byte .LASF78 + .byte 0x19 + .byte 0x2b + .4byte 0x9f + .byte 0x20 + .uleb128 0x15 + .4byte .LASF318 + .byte 0x19 + .byte 0x2c + .4byte 0x9f + .byte 0x24 + .uleb128 0xb + .ascii "arg\000" + .byte 0x19 + .byte 0x2d + .4byte 0x153 + .byte 0x28 + .byte 0 + .uleb128 0x14 + .4byte .LASF319 + .byte 0x14 + .byte 0x19 + .byte 0x39 + .4byte 0x118b + .uleb128 0xb + .ascii "dev\000" + .byte 0x19 + .byte 0x3a + .4byte 0x153 + .byte 0 + .uleb128 0x15 + .4byte .LASF277 + .byte 0x19 + .byte 0x3b + .4byte 0x153 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF320 + .byte 0x19 + .byte 0x3c + .4byte 0x50 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF321 + .byte 0x19 + .byte 0x3d + .4byte 0xd7 + .byte 0xc + .uleb128 0x15 + .4byte .LASF322 + .byte 0x19 + .byte 0x3e + .4byte 0x11af + .byte 0x10 + .byte 0 + .uleb128 0x19 + .4byte 0x122 + .4byte 0x11a9 + .uleb128 0x1a + .4byte 0x11a9 + .uleb128 0x1a + .4byte 0x122 + .uleb128 0x1a + .4byte 0x122 + .uleb128 0x1a + .4byte 0x153 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0x1142 + .uleb128 0x8 + .byte 0x4 + .4byte 0x118b + .uleb128 0x8 + .byte 0x4 + .4byte 0x10b2 + .uleb128 0x8 + .byte 0x4 + .4byte 0x13d + .uleb128 0x14 + .4byte .LASF323 + .byte 0x28 + .byte 0x1a + .byte 0x4e + .4byte 0x122d + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x4f + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF324 + .byte 0x1a + .byte 0x50 + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF325 + .byte 0x1a + .byte 0x51 + .4byte 0xaa + .byte 0x8 + .uleb128 0x15 + .4byte .LASF326 + .byte 0x1a + .byte 0x52 + .4byte 0x9f + .byte 0x10 + .uleb128 0x15 + .4byte .LASF327 + .byte 0x1a + .byte 0x53 + .4byte 0x9f + .byte 0x14 + .uleb128 0xb + .ascii "id\000" + .byte 0x1a + .byte 0x54 + .4byte 0x9f + .byte 0x18 + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0x55 + .4byte 0x122d + .byte 0x1c + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0x56 + .4byte 0x9f + .byte 0x24 + .byte 0 + .uleb128 0xc + .4byte 0x9f + .4byte 0x123d + .uleb128 0xd + .4byte 0xcb + .byte 0x1 + .byte 0 + .uleb128 0x14 + .4byte .LASF329 + .byte 0x30 + .byte 0x1a + .byte 0x59 + .4byte 0x129e + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x5a + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF330 + .byte 0x1a + .byte 0x5b + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF58 + .byte 0x1a + .byte 0x5c + .4byte 0x9f + .byte 0x8 + .uleb128 0x15 + .4byte .LASF331 + .byte 0x1a + .byte 0x5d + .4byte 0x9f + .byte 0xc + .uleb128 0x15 + .4byte .LASF332 + .byte 0x1a + .byte 0x5e + .4byte 0x9f + .byte 0x10 + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0x5f + .4byte 0x129e + .byte 0x14 + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0x60 + .4byte 0x9f + .byte 0x2c + .byte 0 + .uleb128 0xc + .4byte 0x9f + .4byte 0x12ae + .uleb128 0xd + .4byte 0xcb + .byte 0x5 + .byte 0 + .uleb128 0x14 + .4byte .LASF333 + .byte 0xb8 + .byte 0x1a + .byte 0x63 + .4byte 0x1303 + .uleb128 0x15 + .4byte .LASF334 + .byte 0x1a + .byte 0x64 + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x65 + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF335 + .byte 0x1a + .byte 0x66 + .4byte 0x1303 + .byte 0x8 + .uleb128 0x15 + .4byte .LASF318 + .byte 0x1a + .byte 0x67 + .4byte 0x9f + .byte 0xa8 + .uleb128 0x15 + .4byte .LASF336 + .byte 0x1a + .byte 0x68 + .4byte 0x122d + .byte 0xac + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0x69 + .4byte 0x9f + .byte 0xb4 + .byte 0 + .uleb128 0xc + .4byte 0xaa + .4byte 0x1313 + .uleb128 0xd + .4byte 0xcb + .byte 0x13 + .byte 0 + .uleb128 0xa + .byte 0x18 + .byte 0x1a + .byte 0x6e + .4byte 0x134c + .uleb128 0x15 + .4byte .LASF74 + .byte 0x1a + .byte 0x6f + .4byte 0xd2a + .byte 0 + .uleb128 0x15 + .4byte .LASF337 + .byte 0x1a + .byte 0x70 + .4byte 0xaa + .byte 0x8 + .uleb128 0x15 + .4byte .LASF78 + .byte 0x1a + .byte 0x71 + .4byte 0x9f + .byte 0x10 + .uleb128 0x15 + .4byte .LASF318 + .byte 0x1a + .byte 0x72 + .4byte 0x9f + .byte 0x14 + .byte 0 + .uleb128 0xa + .byte 0x18 + .byte 0x1a + .byte 0x75 + .4byte 0x1385 + .uleb128 0x15 + .4byte .LASF74 + .byte 0x1a + .byte 0x76 + .4byte 0xd2a + .byte 0 + .uleb128 0x15 + .4byte .LASF337 + .byte 0x1a + .byte 0x77 + .4byte 0xaa + .byte 0x8 + .uleb128 0x15 + .4byte .LASF78 + .byte 0x1a + .byte 0x78 + .4byte 0x9f + .byte 0x10 + .uleb128 0x15 + .4byte .LASF318 + .byte 0x1a + .byte 0x79 + .4byte 0x9f + .byte 0x14 + .byte 0 + .uleb128 0x14 + .4byte .LASF338 + .byte 0x74 + .byte 0x1a + .byte 0x6c + .4byte 0x13da + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x6d + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF339 + .byte 0x1a + .byte 0x73 + .4byte 0x1313 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF340 + .byte 0x1a + .byte 0x7a + .4byte 0x134c + .byte 0x1c + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0x7c + .4byte 0x13da + .byte 0x34 + .uleb128 0x15 + .4byte .LASF341 + .byte 0x1a + .byte 0x7d + .4byte 0x9f + .byte 0x6c + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0x7e + .4byte 0x9f + .byte 0x70 + .byte 0 + .uleb128 0xc + .4byte 0xaa + .4byte 0x13ea + .uleb128 0xd + .4byte 0xcb + .byte 0x6 + .byte 0 + .uleb128 0x14 + .4byte .LASF342 + .byte 0x20 + .byte 0x1a + .byte 0x81 + .4byte 0x143f + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x82 + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF337 + .byte 0x1a + .byte 0x83 + .4byte 0xaa + .byte 0x4 + .uleb128 0x15 + .4byte .LASF78 + .byte 0x1a + .byte 0x84 + .4byte 0x9f + .byte 0xc + .uleb128 0x15 + .4byte .LASF318 + .byte 0x1a + .byte 0x85 + .4byte 0x9f + .byte 0x10 + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0x86 + .4byte 0x122d + .byte 0x14 + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0x87 + .4byte 0x9f + .byte 0x1c + .byte 0 + .uleb128 0x2a + .4byte .LASF343 + .2byte 0x324 + .byte 0x1a + .byte 0x8a + .4byte 0x1498 + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x8b + .4byte 0x9f + .byte 0 + .uleb128 0xb + .ascii "len\000" + .byte 0x1a + .byte 0x8c + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF336 + .byte 0x1a + .byte 0x8d + .4byte 0x1498 + .byte 0x8 + .uleb128 0x1c + .4byte .LASF344 + .byte 0x1a + .byte 0x8e + .4byte 0x9f + .2byte 0x308 + .uleb128 0x1c + .4byte .LASF94 + .byte 0x1a + .byte 0x8f + .4byte 0x18e + .2byte 0x30c + .uleb128 0x1c + .4byte .LASF328 + .byte 0x1a + .byte 0x90 + .4byte 0x9f + .2byte 0x320 + .byte 0 + .uleb128 0xc + .4byte 0x90 + .4byte 0x14a9 + .uleb128 0x1e + .4byte 0xcb + .2byte 0x2ff + .byte 0 + .uleb128 0xa + .byte 0x20 + .byte 0x1a + .byte 0x98 + .4byte 0x14d6 + .uleb128 0x15 + .4byte .LASF74 + .byte 0x1a + .byte 0x99 + .4byte 0xd3a + .byte 0 + .uleb128 0x15 + .4byte .LASF77 + .byte 0x1a + .byte 0x9a + .4byte 0xaa + .byte 0x10 + .uleb128 0x15 + .4byte .LASF78 + .byte 0x1a + .byte 0x9b + .4byte 0xaa + .byte 0x18 + .byte 0 + .uleb128 0x14 + .4byte .LASF345 + .byte 0xe8 + .byte 0x1a + .byte 0x93 + .4byte 0x152b + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0x94 + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF334 + .byte 0x1a + .byte 0x95 + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0x96 + .4byte 0x152b + .byte 0x8 + .uleb128 0x15 + .4byte .LASF346 + .byte 0x1a + .byte 0x9c + .4byte 0x153b + .byte 0x18 + .uleb128 0x15 + .4byte .LASF341 + .byte 0x1a + .byte 0x9e + .4byte 0x154b + .byte 0xd8 + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0x9f + .4byte 0x9f + .byte 0xe4 + .byte 0 + .uleb128 0xc + .4byte 0x9f + .4byte 0x153b + .uleb128 0xd + .4byte 0xcb + .byte 0x3 + .byte 0 + .uleb128 0xc + .4byte 0x14a9 + .4byte 0x154b + .uleb128 0xd + .4byte 0xcb + .byte 0x5 + .byte 0 + .uleb128 0xc + .4byte 0x9f + .4byte 0x155b + .uleb128 0xd + .4byte 0xcb + .byte 0x2 + .byte 0 + .uleb128 0x14 + .4byte .LASF347 + .byte 0x28 + .byte 0x1a + .byte 0xa2 + .4byte 0x15a4 + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0xa3 + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF74 + .byte 0x1a + .byte 0xa4 + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF318 + .byte 0x1a + .byte 0xa5 + .4byte 0x9f + .byte 0x8 + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0xa6 + .4byte 0x129e + .byte 0xc + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0xa7 + .4byte 0x9f + .byte 0x24 + .byte 0 + .uleb128 0x14 + .4byte .LASF348 + .byte 0x38 + .byte 0x1a + .byte 0xaa + .4byte 0x15e1 + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0xab + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF349 + .byte 0x1a + .byte 0xac + .4byte 0xd4a + .byte 0x4 + .uleb128 0x15 + .4byte .LASF94 + .byte 0x1a + .byte 0xad + .4byte 0x152b + .byte 0x24 + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0xae + .4byte 0x9f + .byte 0x34 + .byte 0 + .uleb128 0xa + .byte 0x8 + .byte 0x1a + .byte 0xb3 + .4byte 0x1602 + .uleb128 0x15 + .4byte .LASF325 + .byte 0x1a + .byte 0xb4 + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF78 + .byte 0x1a + .byte 0xb5 + .4byte 0x9f + .byte 0x4 + .byte 0 + .uleb128 0x14 + .4byte .LASF350 + .byte 0x88 + .byte 0x1a + .byte 0xb1 + .4byte 0x1633 + .uleb128 0x15 + .4byte .LASF130 + .byte 0x1a + .byte 0xb2 + .4byte 0x9f + .byte 0 + .uleb128 0xb + .ascii "buf\000" + .byte 0x1a + .byte 0xb6 + .4byte 0x1633 + .byte 0x4 + .uleb128 0x15 + .4byte .LASF328 + .byte 0x1a + .byte 0xb7 + .4byte 0x9f + .byte 0x84 + .byte 0 + .uleb128 0xc + .4byte 0x15e1 + .4byte 0x1643 + .uleb128 0xd + .4byte 0xcb + .byte 0xf + .byte 0 + .uleb128 0x14 + .4byte .LASF351 + .byte 0xc + .byte 0x1a + .byte 0xba + .4byte 0x1674 + .uleb128 0x15 + .4byte .LASF318 + .byte 0x1a + .byte 0xbb + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF352 + .byte 0x1a + .byte 0xbc + .4byte 0x9f + .byte 0x4 + .uleb128 0x15 + .4byte .LASF353 + .byte 0x1a + .byte 0xbd + .4byte 0x9f + .byte 0x8 + .byte 0 + .uleb128 0x14 + .4byte .LASF354 + .byte 0x8 + .byte 0x1a + .byte 0xc0 + .4byte 0x1699 + .uleb128 0x15 + .4byte .LASF78 + .byte 0x1a + .byte 0xc1 + .4byte 0x9f + .byte 0 + .uleb128 0x15 + .4byte .LASF125 + .byte 0x1a + .byte 0xc2 + .4byte 0x9f + .byte 0x4 + .byte 0 + .uleb128 0x2b + .2byte 0x324 + .byte 0x1a + .byte 0xc8 + .4byte 0x171c + .uleb128 0x13 + .4byte .LASF355 + .byte 0x1a + .byte 0xc9 + .4byte 0x1643 + .uleb128 0x13 + .4byte .LASF356 + .byte 0x1a + .byte 0xca + .4byte 0x11c1 + .uleb128 0x13 + .4byte .LASF357 + .byte 0x1a + .byte 0xcb + .4byte 0x123d + .uleb128 0x13 + .4byte .LASF358 + .byte 0x1a + .byte 0xcc + .4byte 0x12ae + .uleb128 0x13 + .4byte .LASF359 + .byte 0x1a + .byte 0xcd + .4byte 0x1385 + .uleb128 0x13 + .4byte .LASF360 + .byte 0x1a + .byte 0xce + .4byte 0x14d6 + .uleb128 0x13 + .4byte .LASF361 + .byte 0x1a + .byte 0xcf + .4byte 0x13ea + .uleb128 0x13 + .4byte .LASF362 + .byte 0x1a + .byte 0xd0 + .4byte 0x143f + .uleb128 0x2c + .ascii "soc\000" + .byte 0x1a + .byte 0xd1 + .4byte 0x155b + .uleb128 0x13 + .4byte .LASF363 + .byte 0x1a + .byte 0xd2 + .4byte 0x15a4 + .uleb128 0x13 + .4byte .LASF364 + .byte 0x1a + .byte 0xd3 + .4byte 0x1602 + .byte 0 + .uleb128 0x1f + .ascii "tag\000" + .2byte 0x32c + .byte 0x1a + .byte 0xc6 + .4byte 0x1740 + .uleb128 0xb + .ascii "hdr\000" + .byte 0x1a + .byte 0xc7 + .4byte 0x1674 + .byte 0 + .uleb128 0xb + .ascii "u\000" + .byte 0x1a + .byte 0xd4 + .4byte 0x1699 + .byte 0x8 + .byte 0 + .uleb128 0x2d + .4byte .LASF383 + .byte 0x1 + .2byte 0x34c + .4byte 0x50 + .4byte .LFB235 + .4byte .LFE235-.LFB235 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2035 + .uleb128 0x2e + .4byte .LASF365 + .byte 0x1 + .2byte 0x34c + .4byte 0x11b5 + .4byte .LLST67 + .uleb128 0x2e + .4byte .LASF366 + .byte 0x1 + .2byte 0x34d + .4byte 0x11a9 + .4byte .LLST68 + .uleb128 0x2e + .4byte .LASF367 + .byte 0x1 + .2byte 0x34d + .4byte 0x122 + .4byte .LLST69 + .uleb128 0x2f + .ascii "fit\000" + .byte 0x1 + .2byte 0x34d + .4byte 0x153 + .4byte .LLST70 + .uleb128 0x30 + .4byte .LASF368 + .byte 0x1 + .2byte 0x34f + .4byte 0x122 + .4byte .LLST71 + .uleb128 0x31 + .ascii "ret\000" + .byte 0x1 + .2byte 0x350 + .4byte 0x50 + .4byte .LLST72 + .uleb128 0x32 + .ascii "i\000" + .byte 0x1 + .2byte 0x351 + .4byte 0x50 + .byte 0 + .uleb128 0x33 + .4byte 0x2035 + .4byte .LBB84 + .4byte .Ldebug_ranges0+0x58 + .byte 0x1 + .2byte 0x366 + .4byte 0x1d8f + .uleb128 0x34 + .4byte 0x206a + .4byte .LLST73 + .uleb128 0x34 + .4byte 0x205e + .4byte .LLST74 + .uleb128 0x34 + .4byte 0x2052 + .4byte .LLST75 + .uleb128 0x34 + .4byte 0x2046 + .4byte .LLST76 + .uleb128 0x35 + .4byte .Ldebug_ranges0+0x58 + .uleb128 0x36 + .4byte 0x2076 + .uleb128 0x3 + .byte 0x91 + .sleb128 -112 + .uleb128 0x36 + .4byte 0x2082 + .uleb128 0x3 + .byte 0x91 + .sleb128 -180 + .uleb128 0x36 + .4byte 0x208e + .uleb128 0x3 + .byte 0x91 + .sleb128 -176 + .uleb128 0x37 + .4byte 0x209a + .4byte .LLST77 + .uleb128 0x37 + .4byte 0x20a6 + .4byte .LLST78 + .uleb128 0x37 + .4byte 0x20b2 + .4byte .LLST79 + .uleb128 0x37 + .4byte 0x20be + .4byte .LLST80 + .uleb128 0x37 + .4byte 0x20ca + .4byte .LLST81 + .uleb128 0x37 + .4byte 0x20d6 + .4byte .LLST82 + .uleb128 0x37 + .4byte 0x20ed + .4byte .LLST83 + .uleb128 0x36 + .4byte 0x20f9 + .uleb128 0x3 + .byte 0x91 + .sleb128 -172 + .uleb128 0x36 + .4byte 0x2105 + .uleb128 0x3 + .byte 0x91 + .sleb128 -168 + .uleb128 0x38 + .4byte 0x2111 + .uleb128 0x39 + .4byte 0x20e0 + .uleb128 0x3a + .4byte .LBB86 + .4byte .LBE86-.LBB86 + .4byte 0x1aad + .uleb128 0x36 + .4byte 0x211a + .uleb128 0x3 + .byte 0x91 + .sleb128 -181 + .uleb128 0x3b + .4byte 0x23bc + .4byte .LBB87 + .4byte .LBE87-.LBB87 + .byte 0x1 + .2byte 0x31f + .4byte 0x18db + .uleb128 0x34 + .4byte 0x23e5 + .4byte .LLST84 + .uleb128 0x34 + .4byte 0x23d9 + .4byte .LLST85 + .uleb128 0x34 + .4byte 0x23cd + .4byte .LLST86 + .uleb128 0x3c + .4byte .LVL195 + .4byte 0x2fc5 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x3 + .byte 0x7d + .sleb128 107 + .byte 0 + .byte 0 + .uleb128 0x3b + .4byte 0x23f1 + .4byte .LBB89 + .4byte .LBE89-.LBB89 + .byte 0x1 + .2byte 0x33c + .4byte 0x1a24 + .uleb128 0x34 + .4byte 0x2432 + .4byte .LLST87 + .uleb128 0x34 + .4byte 0x2426 + .4byte .LLST88 + .uleb128 0x34 + .4byte 0x241a + .4byte .LLST89 + .uleb128 0x3e + .4byte 0x240e + .uleb128 0x34 + .4byte 0x2402 + .4byte .LLST90 + .uleb128 0x3f + .4byte .LBB90 + .4byte .LBE90-.LBB90 + .uleb128 0x37 + .4byte 0x243e + .4byte .LLST91 + .uleb128 0x36 + .4byte 0x244a + .uleb128 0x3 + .byte 0x91 + .sleb128 -156 + .uleb128 0x37 + .4byte 0x2456 + .4byte .LLST92 + .uleb128 0x40 + .4byte .LVL200 + .4byte 0x2e47 + .4byte 0x1966 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x5 + .byte 0x3 + .4byte .LC27 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x3 + .byte 0x7d + .sleb128 132 + .byte 0 + .uleb128 0x40 + .4byte .LVL202 + .4byte 0x2ace + .4byte 0x1991 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC27 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL205 + .4byte 0x2fd1 + .4byte 0x19b9 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC28 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL206 + .4byte 0x2fd1 + .4byte 0x19e1 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC29 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x3c + .4byte .LVL207 + .4byte 0x2fdd + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x4 + .byte 0x7d + .sleb128 92 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x4 + .byte 0x7d + .sleb128 88 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x4 + .byte 0x7d + .sleb128 84 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x4 + .byte 0x7d + .sleb128 80 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 8 + .uleb128 0x4 + .byte 0x7d + .sleb128 76 + .byte 0x6 + .byte 0 + .byte 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL191 + .4byte 0x2ace + .4byte 0x1a4f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC27 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL196 + .4byte 0x2595 + .4byte 0x1a7f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 96 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .byte 0 + .uleb128 0x3c + .4byte .LVL198 + .4byte 0x2463 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x4 + .byte 0x7d + .sleb128 96 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .byte 0 + .byte 0 + .uleb128 0x3b + .4byte 0x23bc + .4byte .LBB91 + .4byte .LBE91-.LBB91 + .byte 0x1 + .2byte 0x306 + .4byte 0x1af9 + .uleb128 0x34 + .4byte 0x23e5 + .4byte .LLST93 + .uleb128 0x34 + .4byte 0x23d9 + .4byte .LLST94 + .uleb128 0x34 + .4byte 0x23cd + .4byte .LLST95 + .uleb128 0x3c + .4byte .LVL215 + .4byte 0x2fc5 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x74 + .sleb128 4 + .byte 0 + .byte 0 + .uleb128 0x41 + .4byte .LVL144 + .4byte 0x2fe8 + .uleb128 0x40 + .4byte .LVL147 + .4byte 0x228f + .4byte 0x1b2b + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 96 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x3 + .byte 0x7d + .sleb128 112 + .byte 0 + .uleb128 0x40 + .4byte .LVL149 + .4byte 0x2ff3 + .4byte 0x1b48 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x5 + .byte 0x3 + .4byte .LC17 + .byte 0 + .uleb128 0x41 + .4byte .LVL150 + .4byte 0x2fff + .uleb128 0x40 + .4byte .LVL151 + .4byte 0x300b + .4byte 0x1b6a + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL155 + .4byte 0x2d9d + .4byte 0x1b7e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL158 + .4byte 0x2fe8 + .4byte 0x1b9d + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC19 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .byte 0 + .uleb128 0x40 + .4byte .LVL162 + .4byte 0x2fe8 + .4byte 0x1bb4 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC20 + .byte 0 + .uleb128 0x40 + .4byte .LVL163 + .4byte 0x2c24 + .4byte 0x1be0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x6 + .byte 0x11 + .sleb128 -237076478 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x3 + .byte 0x7d + .sleb128 116 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x3 + .byte 0x7d + .sleb128 120 + .byte 0 + .uleb128 0x40 + .4byte .LVL165 + .4byte 0x2fe8 + .4byte 0x1bfd + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC21 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL168 + .4byte 0x2fe8 + .4byte 0x1c14 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC22 + .byte 0 + .uleb128 0x40 + .4byte .LVL171 + .4byte 0x2fe8 + .4byte 0x1c2b + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC23 + .byte 0 + .uleb128 0x40 + .4byte .LVL173 + .4byte 0x2ace + .4byte 0x1c53 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL175 + .4byte 0x2595 + .4byte 0x1c84 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 96 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x3 + .byte 0x7d + .sleb128 176 + .byte 0 + .uleb128 0x40 + .4byte .LVL177 + .4byte 0x3017 + .4byte 0x1ca5 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x3 + .byte 0x7d + .sleb128 108 + .byte 0 + .uleb128 0x41 + .4byte .LVL179 + .4byte 0x2384 + .uleb128 0x40 + .4byte .LVL181 + .4byte 0x2fe8 + .4byte 0x1cc5 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC25 + .byte 0 + .uleb128 0x40 + .4byte .LVL184 + .4byte 0x2ace + .4byte 0x1cef + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC26 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL186 + .4byte 0x2ace + .4byte 0x1d19 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC27 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL189 + .4byte 0x3023 + .4byte 0x1d30 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0xc + .4byte 0x54410057 + .byte 0 + .uleb128 0x40 + .4byte .LVL211 + .4byte 0x2595 + .4byte 0x1d60 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x7d + .sleb128 96 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .byte 0 + .uleb128 0x3c + .4byte .LVL216 + .4byte 0x2463 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x4 + .byte 0x7d + .sleb128 96 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x4 + .byte 0x7d + .sleb128 100 + .byte 0x6 + .byte 0 + .byte 0 + .byte 0 + .uleb128 0x33 + .4byte 0x2143 + .4byte .LBB100 + .4byte .Ldebug_ranges0+0x88 + .byte 0x1 + .2byte 0x36a + .4byte 0x201b + .uleb128 0x34 + .4byte 0x2160 + .4byte .LLST96 + .uleb128 0x34 + .4byte 0x2154 + .4byte .LLST97 + .uleb128 0x35 + .4byte .Ldebug_ranges0+0x88 + .uleb128 0x36 + .4byte 0x216c + .uleb128 0x3 + .byte 0x91 + .sleb128 -168 + .uleb128 0x36 + .4byte 0x2178 + .uleb128 0x3 + .byte 0x91 + .sleb128 -156 + .uleb128 0x42 + .4byte 0x2184 + .4byte 0x2fb2 + .4byte .LLST99 + .uleb128 0x37 + .4byte 0x2190 + .4byte .LLST100 + .uleb128 0x36 + .4byte 0x219c + .uleb128 0x3 + .byte 0x91 + .sleb128 -172 + .uleb128 0x37 + .4byte 0x21a8 + .4byte .LLST101 + .uleb128 0x37 + .4byte 0x21b4 + .4byte .LLST102 + .uleb128 0x37 + .4byte 0x21c0 + .4byte .LLST103 + .uleb128 0x37 + .4byte 0x21cc + .4byte .LLST104 + .uleb128 0x37 + .4byte 0x21d6 + .4byte .LLST105 + .uleb128 0x37 + .4byte 0x21e2 + .4byte .LLST106 + .uleb128 0x36 + .4byte 0x21ee + .uleb128 0x3 + .byte 0x91 + .sleb128 -112 + .uleb128 0x37 + .4byte 0x2207 + .4byte .LLST107 + .uleb128 0x39 + .4byte 0x21fa + .uleb128 0x43 + .4byte .Ldebug_ranges0+0xa0 + .4byte 0x1eff + .uleb128 0x39 + .4byte 0x2214 + .uleb128 0x40 + .4byte .LVL253 + .4byte 0x2ace + .4byte 0x1e6d + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x77 + .sleb128 80 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL255 + .4byte 0x2595 + .4byte 0x1e97 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x77 + .sleb128 84 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x3 + .byte 0x77 + .sleb128 116 + .byte 0 + .uleb128 0x40 + .4byte .LVL257 + .4byte 0x302e + .4byte 0x1eb4 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x5 + .byte 0x3 + .4byte .LC0 + .byte 0 + .uleb128 0x40 + .4byte .LVL258 + .4byte 0x2d74 + .4byte 0x1ec8 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL259 + .4byte 0x2c99 + .4byte 0x1edc + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .byte 0 + .uleb128 0x41 + .4byte .LVL260 + .4byte 0x2c76 + .uleb128 0x3c + .4byte .LVL264 + .4byte 0x302e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x5 + .byte 0x3 + .4byte .LC1 + .byte 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL224 + .4byte 0x2256 + .4byte 0x1f19 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL226 + .4byte 0x3039 + .4byte 0x1f2e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x3 + .byte 0x77 + .sleb128 160 + .byte 0 + .uleb128 0x41 + .4byte .LVL227 + .4byte 0x2fe8 + .uleb128 0x44 + .4byte .LVL233 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .4byte 0x1f5d + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x77 + .sleb128 84 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x1 + .byte 0x31 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL236 + .4byte 0x228f + .4byte 0x1f86 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x7b + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x77 + .sleb128 84 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x3 + .byte 0x77 + .sleb128 100 + .byte 0 + .uleb128 0x40 + .4byte .LVL238 + .4byte 0x300b + .4byte 0x1f9f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL240 + .4byte 0x2fe8 + .4byte 0x1fb6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC18 + .byte 0 + .uleb128 0x40 + .4byte .LVL243 + .4byte 0x2d9d + .4byte 0x1fca + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL246 + .4byte 0x2fe8 + .4byte 0x1fe9 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC19 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x4 + .byte 0x77 + .sleb128 84 + .byte 0x6 + .byte 0 + .uleb128 0x40 + .4byte .LVL249 + .4byte 0x2fe8 + .4byte 0x2000 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC20 + .byte 0 + .uleb128 0x3c + .4byte .LVL250 + .4byte 0x2ff3 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x5 + .byte 0x3 + .4byte .LC17 + .byte 0 + .byte 0 + .byte 0 + .uleb128 0x45 + .4byte 0xd2 + .4byte .LLST98 + .uleb128 0x3c + .4byte .LVL146 + .4byte 0x2ce6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .byte 0 + .byte 0 + .uleb128 0x46 + .4byte .LASF378 + .byte 0x1 + .2byte 0x26b + .4byte 0x50 + .byte 0x1 + .4byte 0x2128 + .uleb128 0x47 + .4byte .LASF365 + .byte 0x1 + .2byte 0x26b + .4byte 0x11b5 + .uleb128 0x47 + .4byte .LASF366 + .byte 0x1 + .2byte 0x26c + .4byte 0x11a9 + .uleb128 0x47 + .4byte .LASF367 + .byte 0x1 + .2byte 0x26d + .4byte 0x122 + .uleb128 0x47 + .4byte .LASF369 + .byte 0x1 + .2byte 0x26d + .4byte 0x153 + .uleb128 0x48 + .4byte .LASF221 + .byte 0x1 + .2byte 0x26f + .4byte 0x10b2 + .uleb128 0x48 + .4byte .LASF370 + .byte 0x1 + .2byte 0x270 + .4byte 0xfb + .uleb128 0x48 + .4byte .LASF371 + .byte 0x1 + .2byte 0x271 + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF256 + .byte 0x1 + .2byte 0x272 + .4byte 0x50 + .uleb128 0x49 + .ascii "ret\000" + .byte 0x1 + .2byte 0x272 + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF276 + .byte 0x1 + .2byte 0x273 + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF372 + .byte 0x1 + .2byte 0x274 + .4byte 0x50 + .uleb128 0x49 + .ascii "fit\000" + .byte 0x1 + .2byte 0x275 + .4byte 0x153 + .uleb128 0x49 + .ascii "t\000" + .byte 0x1 + .2byte 0x276 + .4byte 0x2128 + .uleb128 0x4a + .4byte .LASF373 + .4byte 0x213e + .4byte .LASF378 + .uleb128 0x48 + .4byte .LASF374 + .byte 0x1 + .2byte 0x28e + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF375 + .byte 0x1 + .2byte 0x29e + .4byte 0x13d + .uleb128 0x48 + .4byte .LASF376 + .byte 0x1 + .2byte 0x29e + .4byte 0x13d + .uleb128 0x4b + .4byte .LASF463 + .byte 0x1 + .2byte 0x315 + .uleb128 0x4c + .uleb128 0x48 + .4byte .LASF377 + .byte 0x1 + .2byte 0x319 + .4byte 0x12d + .byte 0 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0x171c + .uleb128 0xc + .4byte 0xe4 + .4byte 0x213e + .uleb128 0xd + .4byte 0xcb + .byte 0x1c + .byte 0 + .uleb128 0x7 + .4byte 0x212e + .uleb128 0x46 + .4byte .LASF379 + .byte 0x1 + .2byte 0x1e6 + .4byte 0x50 + .byte 0x1 + .4byte 0x2222 + .uleb128 0x47 + .4byte .LASF365 + .byte 0x1 + .2byte 0x1e6 + .4byte 0x11b5 + .uleb128 0x47 + .4byte .LASF366 + .byte 0x1 + .2byte 0x1e7 + .4byte 0x11a9 + .uleb128 0x48 + .4byte .LASF256 + .byte 0x1 + .2byte 0x1f2 + .4byte 0x2222 + .uleb128 0x48 + .4byte .LASF221 + .byte 0x1 + .2byte 0x1f3 + .4byte 0x10b2 + .uleb128 0x48 + .4byte .LASF369 + .byte 0x1 + .2byte 0x1f4 + .4byte 0x2232 + .uleb128 0x48 + .4byte .LASF380 + .byte 0x1 + .2byte 0x1f5 + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF371 + .byte 0x1 + .2byte 0x1f6 + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF367 + .byte 0x1 + .2byte 0x1f7 + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF372 + .byte 0x1 + .2byte 0x1f8 + .4byte 0x50 + .uleb128 0x49 + .ascii "ret\000" + .byte 0x1 + .2byte 0x1f8 + .4byte 0x50 + .uleb128 0x49 + .ascii "i\000" + .byte 0x1 + .2byte 0x1f8 + .4byte 0x50 + .uleb128 0x49 + .ascii "fit\000" + .byte 0x1 + .2byte 0x1f9 + .4byte 0x153 + .uleb128 0x48 + .4byte .LASF381 + .byte 0x1 + .2byte 0x1ff + .4byte 0xd7 + .uleb128 0x48 + .4byte .LASF382 + .byte 0x1 + .2byte 0x200 + .4byte 0x494 + .uleb128 0x4a + .4byte .LASF373 + .4byte 0x2251 + .4byte .LASF379 + .uleb128 0x48 + .4byte .LASF374 + .byte 0x1 + .2byte 0x21d + .4byte 0x50 + .uleb128 0x4c + .uleb128 0x48 + .4byte .LASF370 + .byte 0x1 + .2byte 0x237 + .4byte 0x4ba + .byte 0 + .byte 0 + .uleb128 0xc + .4byte 0xd7 + .4byte 0x2232 + .uleb128 0xd + .4byte 0xcb + .byte 0x2 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0x2241 + .uleb128 0x4d + .4byte 0xcb + .byte 0 + .uleb128 0xc + .4byte 0xe4 + .4byte 0x2251 + .uleb128 0xd + .4byte 0xcb + .byte 0x13 + .byte 0 + .uleb128 0x7 + .4byte 0x2241 + .uleb128 0x2d + .4byte .LASF384 + .byte 0x1 + .2byte 0x1df + .4byte 0xd7 + .4byte .LFB232 + .4byte .LFE232-.LFB232 + .uleb128 0x1 + .byte 0x9c + .4byte 0x228f + .uleb128 0x2f + .ascii "spl\000" + .byte 0x1 + .2byte 0x1df + .4byte 0x11b5 + .4byte .LLST66 + .uleb128 0x4e + .4byte .LASF366 + .byte 0x1 + .2byte 0x1e0 + .4byte 0x11a9 + .uleb128 0x1 + .byte 0x51 + .byte 0 + .uleb128 0x4f + .4byte .LASF393 + .byte 0x1 + .2byte 0x1ad + .4byte 0x153 + .4byte .LFB231 + .4byte .LFE231-.LFB231 + .uleb128 0x1 + .byte 0x9c + .4byte 0x237e + .uleb128 0x2e + .4byte .LASF366 + .byte 0x1 + .2byte 0x1ad + .4byte 0x11a9 + .4byte .LLST47 + .uleb128 0x2e + .4byte .LASF367 + .byte 0x1 + .2byte 0x1ae + .4byte 0x122 + .4byte .LLST48 + .uleb128 0x2e + .4byte .LASF369 + .byte 0x1 + .2byte 0x1ae + .4byte 0x153 + .4byte .LLST49 + .uleb128 0x2e + .4byte .LASF371 + .byte 0x1 + .2byte 0x1af + .4byte 0x237e + .4byte .LLST50 + .uleb128 0x50 + .4byte .LASF385 + .byte 0x1 + .2byte 0x1b1 + .4byte 0x50 + .byte 0x3f + .uleb128 0x30 + .4byte .LASF334 + .byte 0x1 + .2byte 0x1b2 + .4byte 0x122 + .4byte .LLST51 + .uleb128 0x30 + .4byte .LASF78 + .byte 0x1 + .2byte 0x1b3 + .4byte 0x122 + .4byte .LLST52 + .uleb128 0x48 + .4byte .LASF386 + .byte 0x1 + .2byte 0x1b4 + .4byte 0x50 + .uleb128 0x31 + .ascii "fit\000" + .byte 0x1 + .2byte 0x1b5 + .4byte 0x153 + .4byte .LLST53 + .uleb128 0x3b + .4byte 0x2a4e + .4byte .LBB62 + .4byte .LBE62-.LBB62 + .byte 0x1 + .2byte 0x1d3 + .4byte 0x2362 + .uleb128 0x34 + .4byte 0x2a74 + .4byte .LLST54 + .uleb128 0x34 + .4byte 0x2a69 + .4byte .LLST55 + .uleb128 0x34 + .4byte 0x2a5e + .4byte .LLST56 + .byte 0 + .uleb128 0x51 + .4byte .LVL115 + .uleb128 0x2 + .byte 0x77 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0x50 + .uleb128 0x2d + .4byte .LASF387 + .byte 0x1 + .2byte 0x1a8 + .4byte 0x50 + .4byte .LFB230 + .4byte .LFE230-.LFB230 + .uleb128 0x1 + .byte 0x9c + .4byte 0x23bc + .uleb128 0x2f + .ascii "id\000" + .byte 0x1 + .2byte 0x1a8 + .4byte 0xfb + .4byte .LLST65 + .uleb128 0x4e + .4byte .LASF313 + .byte 0x1 + .2byte 0x1a8 + .4byte 0x101 + .uleb128 0x1 + .byte 0x51 + .byte 0 + .uleb128 0x46 + .4byte .LASF388 + .byte 0x1 + .2byte 0x19f + .4byte 0x50 + .byte 0x1 + .4byte 0x23f1 + .uleb128 0x52 + .ascii "fit\000" + .byte 0x1 + .2byte 0x19f + .4byte 0x3be + .uleb128 0x47 + .4byte .LASF389 + .byte 0x1 + .2byte 0x19f + .4byte 0x50 + .uleb128 0x52 + .ascii "os\000" + .byte 0x1 + .2byte 0x19f + .4byte 0xd24 + .byte 0 + .uleb128 0x46 + .4byte .LASF390 + .byte 0x1 + .2byte 0x188 + .4byte 0x50 + .byte 0x1 + .4byte 0x2463 + .uleb128 0x52 + .ascii "fit\000" + .byte 0x1 + .2byte 0x188 + .4byte 0x3be + .uleb128 0x47 + .4byte .LASF256 + .byte 0x1 + .2byte 0x188 + .4byte 0x50 + .uleb128 0x47 + .4byte .LASF276 + .byte 0x1 + .2byte 0x188 + .4byte 0x50 + .uleb128 0x47 + .4byte .LASF391 + .byte 0x1 + .2byte 0x189 + .4byte 0x153 + .uleb128 0x47 + .4byte .LASF392 + .byte 0x1 + .2byte 0x189 + .4byte 0x11b5 + .uleb128 0x49 + .ascii "ret\000" + .byte 0x1 + .2byte 0x18b + .4byte 0x50 + .uleb128 0x48 + .4byte .LASF74 + .byte 0x1 + .2byte 0x18d + .4byte 0xfb + .uleb128 0x48 + .4byte .LASF372 + .byte 0x1 + .2byte 0x18e + .4byte 0x50 + .byte 0 + .uleb128 0x53 + .4byte .LASF394 + .byte 0x1 + .2byte 0x165 + .4byte 0x50 + .4byte .LFB227 + .4byte .LFE227-.LFB227 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2580 + .uleb128 0x2e + .4byte .LASF365 + .byte 0x1 + .2byte 0x165 + .4byte 0x11b5 + .4byte .LLST39 + .uleb128 0x2e + .4byte .LASF366 + .byte 0x1 + .2byte 0x166 + .4byte 0x11a9 + .4byte .LLST40 + .uleb128 0x2e + .4byte .LASF367 + .byte 0x1 + .2byte 0x166 + .4byte 0x122 + .4byte .LLST41 + .uleb128 0x2f + .ascii "fit\000" + .byte 0x1 + .2byte 0x167 + .4byte 0x153 + .4byte .LLST42 + .uleb128 0x2e + .4byte .LASF256 + .byte 0x1 + .2byte 0x167 + .4byte 0x50 + .4byte .LLST43 + .uleb128 0x2e + .4byte .LASF371 + .byte 0x1 + .2byte 0x167 + .4byte 0x122 + .4byte .LLST44 + .uleb128 0x54 + .4byte .LASF221 + .byte 0x1 + .2byte 0x169 + .4byte 0x10b2 + .uleb128 0x3 + .byte 0x91 + .sleb128 -68 + .uleb128 0x30 + .4byte .LASF372 + .byte 0x1 + .2byte 0x16a + .4byte 0x50 + .4byte .LLST45 + .uleb128 0x31 + .ascii "ret\000" + .byte 0x1 + .2byte 0x16a + .4byte 0x50 + .4byte .LLST46 + .uleb128 0x55 + .4byte .LASF373 + .4byte 0x2590 + .uleb128 0x40 + .4byte .LVL99 + .4byte 0x2ace + .4byte 0x253f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x3 + .byte 0x91 + .sleb128 0 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL101 + .4byte 0x2595 + .4byte 0x256e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x77 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x3 + .byte 0x91 + .sleb128 4 + .byte 0x6 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x3 + .byte 0x91 + .sleb128 -68 + .byte 0 + .uleb128 0x3c + .4byte .LVL103 + .4byte 0x3044 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x3 + .byte 0xa + .2byte 0x2000 + .byte 0 + .byte 0 + .uleb128 0xc + .4byte 0xe4 + .4byte 0x2590 + .uleb128 0xd + .4byte 0xcb + .byte 0x12 + .byte 0 + .uleb128 0x7 + .4byte 0x2580 + .uleb128 0x56 + .4byte .LASF395 + .byte 0x1 + .byte 0xd4 + .4byte 0x50 + .4byte .LFB226 + .4byte .LFE226-.LFB226 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2a4e + .uleb128 0x57 + .4byte .LASF366 + .byte 0x1 + .byte 0xd4 + .4byte 0x11a9 + .4byte .LLST15 + .uleb128 0x57 + .4byte .LASF367 + .byte 0x1 + .byte 0xd4 + .4byte 0x122 + .4byte .LLST16 + .uleb128 0x58 + .ascii "fit\000" + .byte 0x1 + .byte 0xd5 + .4byte 0x153 + .4byte .LLST17 + .uleb128 0x57 + .4byte .LASF371 + .byte 0x1 + .byte 0xd5 + .4byte 0x122 + .4byte .LLST18 + .uleb128 0x57 + .4byte .LASF372 + .byte 0x1 + .byte 0xd5 + .4byte 0x50 + .4byte .LLST19 + .uleb128 0x57 + .4byte .LASF221 + .byte 0x1 + .byte 0xd6 + .4byte 0x11b5 + .4byte .LLST20 + .uleb128 0x59 + .4byte .LASF396 + .byte 0x1 + .byte 0xd8 + .4byte 0x50 + .uleb128 0x2 + .byte 0x91 + .sleb128 -60 + .uleb128 0x59 + .4byte .LASF397 + .byte 0x1 + .byte 0xd9 + .4byte 0x10c + .uleb128 0x2 + .byte 0x91 + .sleb128 -56 + .uleb128 0x5a + .ascii "len\000" + .byte 0x1 + .byte 0xda + .4byte 0x50 + .uleb128 0x2 + .byte 0x91 + .sleb128 -52 + .uleb128 0x5b + .4byte .LASF78 + .byte 0x1 + .byte 0xdb + .4byte 0x122 + .uleb128 0x59 + .4byte .LASF398 + .byte 0x1 + .byte 0xdc + .4byte 0x122 + .uleb128 0x2 + .byte 0x91 + .sleb128 -48 + .uleb128 0x59 + .4byte .LASF262 + .byte 0x1 + .byte 0xdc + .4byte 0x122 + .uleb128 0x2 + .byte 0x91 + .sleb128 -44 + .uleb128 0x5c + .4byte .LASF399 + .byte 0x1 + .byte 0xdc + .4byte 0x122 + .4byte .LLST21 + .uleb128 0x5a + .ascii "src\000" + .byte 0x1 + .byte 0xdd + .4byte 0x153 + .uleb128 0x2 + .byte 0x91 + .sleb128 -40 + .uleb128 0x5c + .4byte .LASF400 + .byte 0x1 + .byte 0xde + .4byte 0x122 + .4byte .LLST22 + .uleb128 0x5b + .4byte .LASF401 + .byte 0x1 + .byte 0xdf + .4byte 0x50 + .uleb128 0x5d + .4byte .LASF385 + .byte 0x1 + .byte 0xe0 + .4byte 0x50 + .byte 0x3f + .uleb128 0x59 + .4byte .LASF402 + .byte 0x1 + .byte 0xe1 + .4byte 0x12d + .uleb128 0x2 + .byte 0x91 + .sleb128 -61 + .uleb128 0x5c + .4byte .LASF62 + .byte 0x1 + .byte 0xe1 + .4byte 0x12d + .4byte .LLST23 + .uleb128 0x59 + .4byte .LASF336 + .byte 0x1 + .byte 0xe2 + .4byte 0x3be + .uleb128 0x2 + .byte 0x91 + .sleb128 -36 + .uleb128 0x5c + .4byte .LASF403 + .byte 0x1 + .byte 0xe3 + .4byte 0x19e + .4byte .LLST24 + .uleb128 0x5c + .4byte .LASF404 + .byte 0x1 + .byte 0xe4 + .4byte 0x19e + .4byte .LLST25 + .uleb128 0x5c + .4byte .LASF370 + .byte 0x1 + .byte 0xe5 + .4byte 0x4ba + .4byte .LLST26 + .uleb128 0x5e + .ascii "out\000" + .byte 0x1 + .2byte 0x15b + .4byte .L31 + .uleb128 0x33 + .4byte 0x2a80 + .4byte .LBB36 + .4byte .Ldebug_ranges0+0 + .byte 0x1 + .2byte 0x114 + .4byte 0x2727 + .uleb128 0x34 + .4byte 0x2a9b + .4byte .LLST27 + .uleb128 0x34 + .4byte 0x2a90 + .4byte .LLST28 + .byte 0 + .uleb128 0x3b + .4byte 0x2a4e + .4byte .LBB41 + .4byte .LBE41-.LBB41 + .byte 0x1 + .2byte 0x115 + .4byte 0x2753 + .uleb128 0x3e + .4byte 0x2a74 + .uleb128 0x34 + .4byte 0x2a69 + .4byte .LLST29 + .uleb128 0x34 + .4byte 0x2a5e + .4byte .LLST30 + .byte 0 + .uleb128 0x33 + .4byte 0x2aa7 + .4byte .LBB43 + .4byte .Ldebug_ranges0+0x20 + .byte 0x1 + .2byte 0x11e + .4byte 0x277a + .uleb128 0x34 + .4byte 0x2ac2 + .4byte .LLST31 + .uleb128 0x34 + .4byte 0x2ab7 + .4byte .LLST32 + .byte 0 + .uleb128 0x33 + .4byte 0x2dd3 + .4byte .LBB48 + .4byte .Ldebug_ranges0+0x38 + .byte 0x1 + .2byte 0x137 + .4byte 0x27c5 + .uleb128 0x34 + .4byte 0x2dfc + .4byte .LLST33 + .uleb128 0x34 + .4byte 0x2df0 + .4byte .LLST34 + .uleb128 0x34 + .4byte 0x2de4 + .4byte .LLST35 + .uleb128 0x3c + .4byte .LVL77 + .4byte 0x304f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .byte 0 + .uleb128 0x3b + .4byte 0x2dd3 + .4byte .LBB54 + .4byte .LBE54-.LBB54 + .byte 0x1 + .2byte 0x13c + .4byte 0x27fe + .uleb128 0x34 + .4byte 0x2dfc + .4byte .LLST36 + .uleb128 0x34 + .4byte 0x2df0 + .4byte .LLST37 + .uleb128 0x34 + .4byte 0x2de4 + .4byte .LLST38 + .uleb128 0x41 + .4byte .LVL86 + .4byte 0x304f + .byte 0 + .uleb128 0x40 + .4byte .LVL45 + .4byte 0x305b + .4byte 0x281e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -61 + .byte 0 + .uleb128 0x40 + .4byte .LVL46 + .4byte 0x3067 + .4byte 0x283e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -44 + .byte 0 + .uleb128 0x40 + .4byte .LVL47 + .4byte 0x3073 + .4byte 0x285e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -48 + .byte 0 + .uleb128 0x40 + .4byte .LVL48 + .4byte 0x307f + .4byte 0x287e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -60 + .byte 0 + .uleb128 0x40 + .4byte .LVL49 + .4byte 0x308b + .4byte 0x289e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -60 + .byte 0 + .uleb128 0x40 + .4byte .LVL52 + .4byte 0x3097 + .4byte 0x28be + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -52 + .byte 0 + .uleb128 0x40 + .4byte .LVL54 + .4byte 0x30a3 + .4byte 0x28d2 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x8 + .byte 0x40 + .byte 0 + .uleb128 0x40 + .4byte .LVL61 + .4byte 0x30af + .4byte 0x28ec + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .byte 0 + .uleb128 0x5f + .4byte .LVL64 + .4byte 0x290a + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x4 + .byte 0x91 + .sleb128 -80 + .byte 0x6 + .byte 0 + .uleb128 0x40 + .4byte .LVL65 + .4byte 0x2fe8 + .4byte 0x2921 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC7 + .byte 0 + .uleb128 0x40 + .4byte .LVL66 + .4byte 0x30bb + .4byte 0x2944 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC13 + .byte 0 + .uleb128 0x40 + .4byte .LVL79 + .4byte 0x2fd1 + .4byte 0x296c + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x5 + .byte 0x3 + .4byte .LC9 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .uleb128 0x40 + .4byte .LVL80 + .4byte 0x2fe8 + .4byte 0x298f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC10 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x77 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x7a + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL81 + .4byte 0x30c7 + .4byte 0x29a9 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL82 + .4byte 0x30d3 + .4byte 0x29dd + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -44 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x91 + .sleb128 -40 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 0 + .uleb128 0x2 + .byte 0x91 + .sleb128 -56 + .uleb128 0x3d + .uleb128 0x2 + .byte 0x7d + .sleb128 4 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL83 + .4byte 0x30df + .4byte 0x29f4 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC12 + .byte 0 + .uleb128 0x41 + .4byte .LVL84 + .4byte 0x30ea + .uleb128 0x40 + .4byte .LVL87 + .4byte 0x2fe8 + .4byte 0x2a14 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC11 + .byte 0 + .uleb128 0x40 + .4byte .LVL91 + .4byte 0x30f6 + .4byte 0x2a3a + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x91 + .sleb128 -36 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x91 + .sleb128 -56 + .byte 0 + .uleb128 0x3c + .4byte .LVL92 + .4byte 0x30df + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC8 + .byte 0 + .byte 0 + .uleb128 0x60 + .4byte .LASF405 + .byte 0x1 + .byte 0xb8 + .4byte 0x50 + .byte 0x1 + .4byte 0x2a80 + .uleb128 0x61 + .4byte .LASF366 + .byte 0x1 + .byte 0xb8 + .4byte 0x11a9 + .uleb128 0x61 + .4byte .LASF406 + .byte 0x1 + .byte 0xb8 + .4byte 0x50 + .uleb128 0x61 + .4byte .LASF396 + .byte 0x1 + .byte 0xb9 + .4byte 0x50 + .byte 0 + .uleb128 0x60 + .4byte .LASF407 + .byte 0x1 + .byte 0xaa + .4byte 0x50 + .byte 0x1 + .4byte 0x2aa7 + .uleb128 0x61 + .4byte .LASF366 + .byte 0x1 + .byte 0xaa + .4byte 0x11a9 + .uleb128 0x61 + .4byte .LASF396 + .byte 0x1 + .byte 0xaa + .4byte 0x50 + .byte 0 + .uleb128 0x60 + .4byte .LASF408 + .byte 0x1 + .byte 0x9d + .4byte 0x50 + .byte 0x1 + .4byte 0x2ace + .uleb128 0x61 + .4byte .LASF366 + .byte 0x1 + .byte 0x9d + .4byte 0x11a9 + .uleb128 0x61 + .4byte .LASF396 + .byte 0x1 + .byte 0x9d + .4byte 0x50 + .byte 0 + .uleb128 0x62 + .4byte .LASF409 + .byte 0x1 + .byte 0x87 + .4byte 0x50 + .4byte .LFB222 + .4byte .LFE222-.LFB222 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2b96 + .uleb128 0x58 + .ascii "fit\000" + .byte 0x1 + .byte 0x87 + .4byte 0x3be + .4byte .LLST9 + .uleb128 0x57 + .4byte .LASF256 + .byte 0x1 + .byte 0x87 + .4byte 0x50 + .4byte .LLST10 + .uleb128 0x57 + .4byte .LASF62 + .byte 0x1 + .byte 0x88 + .4byte 0xd7 + .4byte .LLST11 + .uleb128 0x57 + .4byte .LASF276 + .byte 0x1 + .byte 0x88 + .4byte 0x50 + .4byte .LLST12 + .uleb128 0x5a + .ascii "str\000" + .byte 0x1 + .byte 0x8a + .4byte 0xfb + .uleb128 0x2 + .byte 0x91 + .sleb128 -20 + .uleb128 0x63 + .ascii "err\000" + .byte 0x1 + .byte 0x8b + .4byte 0x50 + .4byte .LLST13 + .uleb128 0x5c + .4byte .LASF372 + .byte 0x1 + .byte 0x8c + .4byte 0x50 + .4byte .LLST14 + .uleb128 0x40 + .4byte .LVL34 + .4byte 0x2e47 + .4byte 0x2b7f + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x3 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x3 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x91 + .sleb128 -20 + .uleb128 0x64 + .4byte 0x2bb1 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .byte 0 + .uleb128 0x3c + .4byte .LVL36 + .4byte 0x3102 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .byte 0 + .byte 0 + .uleb128 0x60 + .4byte .LASF410 + .byte 0x1 + .byte 0x51 + .4byte 0x50 + .byte 0x1 + .4byte 0x2c1e + .uleb128 0x65 + .ascii "fit\000" + .byte 0x1 + .byte 0x51 + .4byte 0x3be + .uleb128 0x61 + .4byte .LASF256 + .byte 0x1 + .byte 0x51 + .4byte 0x50 + .uleb128 0x61 + .4byte .LASF62 + .byte 0x1 + .byte 0x52 + .4byte 0xd7 + .uleb128 0x61 + .4byte .LASF276 + .byte 0x1 + .byte 0x52 + .4byte 0x50 + .uleb128 0x61 + .4byte .LASF411 + .byte 0x1 + .byte 0x53 + .4byte 0x2c1e + .uleb128 0x5b + .4byte .LASF74 + .byte 0x1 + .byte 0x55 + .4byte 0xd7 + .uleb128 0x66 + .ascii "str\000" + .byte 0x1 + .byte 0x55 + .4byte 0xd7 + .uleb128 0x5b + .4byte .LASF372 + .byte 0x1 + .byte 0x56 + .4byte 0x50 + .uleb128 0x5b + .4byte .LASF412 + .byte 0x1 + .byte 0x57 + .4byte 0x50 + .uleb128 0x66 + .ascii "len\000" + .byte 0x1 + .byte 0x58 + .4byte 0x50 + .uleb128 0x66 + .ascii "i\000" + .byte 0x1 + .byte 0x58 + .4byte 0x50 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xfb + .uleb128 0x67 + .4byte .LASF413 + .byte 0x1 + .byte 0x3c + .4byte 0x50 + .4byte .LFB220 + .4byte .LFE220-.LFB220 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2c76 + .uleb128 0x58 + .ascii "fit\000" + .byte 0x1 + .byte 0x3c + .4byte 0x3be + .4byte .LLST63 + .uleb128 0x57 + .4byte .LASF414 + .byte 0x1 + .byte 0x3c + .4byte 0x13d + .4byte .LLST64 + .uleb128 0x68 + .4byte .LASF415 + .byte 0x1 + .byte 0x3d + .4byte 0x11bb + .uleb128 0x1 + .byte 0x52 + .uleb128 0x68 + .4byte .LASF416 + .byte 0x1 + .byte 0x3d + .4byte 0x11bb + .uleb128 0x1 + .byte 0x53 + .byte 0 + .uleb128 0x69 + .4byte .LASF464 + .byte 0x1 + .byte 0x38 + .4byte .LFB219 + .4byte .LFE219-.LFB219 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2c99 + .uleb128 0x6a + .ascii "fdt\000" + .byte 0x1 + .byte 0x38 + .4byte 0x153 + .uleb128 0x1 + .byte 0x50 + .byte 0 + .uleb128 0x6b + .4byte .LASF465 + .byte 0x1 + .byte 0x33 + .4byte 0x50 + .byte 0x1 + .4byte 0x2cc0 + .uleb128 0x65 + .ascii "fdt\000" + .byte 0x1 + .byte 0x33 + .4byte 0x153 + .uleb128 0x61 + .4byte .LASF336 + .byte 0x1 + .byte 0x33 + .4byte 0xfb + .byte 0 + .uleb128 0x6c + .4byte .LASF466 + .byte 0x1 + .byte 0x2e + .4byte 0x50 + .4byte 0x2ce6 + .uleb128 0x65 + .ascii "fdt\000" + .byte 0x1 + .byte 0x2e + .4byte 0x153 + .uleb128 0x61 + .4byte .LASF417 + .byte 0x1 + .byte 0x2e + .4byte 0xfb + .byte 0 + .uleb128 0x67 + .4byte .LASF418 + .byte 0x1 + .byte 0x27 + .4byte 0x50 + .4byte .LFB216 + .4byte .LFE216-.LFB216 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2d31 + .uleb128 0x57 + .4byte .LASF365 + .byte 0x1 + .byte 0x27 + .4byte 0x11b5 + .4byte .LLST60 + .uleb128 0x57 + .4byte .LASF366 + .byte 0x1 + .byte 0x27 + .4byte 0x11a9 + .4byte .LLST61 + .uleb128 0x3c + .4byte .LVL126 + .4byte 0x2fe8 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC14 + .byte 0 + .byte 0 + .uleb128 0x67 + .4byte .LASF419 + .byte 0x1 + .byte 0x22 + .4byte 0x50 + .4byte .LFB215 + .4byte .LFE215-.LFB215 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2d74 + .uleb128 0x57 + .4byte .LASF420 + .byte 0x1 + .byte 0x22 + .4byte 0x4ba + .4byte .LLST59 + .uleb128 0x68 + .4byte .LASF421 + .byte 0x1 + .byte 0x22 + .4byte 0xfb + .uleb128 0x1 + .byte 0x51 + .uleb128 0x68 + .4byte .LASF417 + .byte 0x1 + .byte 0x22 + .4byte 0xfb + .uleb128 0x1 + .byte 0x52 + .byte 0 + .uleb128 0x67 + .4byte .LASF422 + .byte 0x1 + .byte 0x1d + .4byte 0xfb + .4byte .LFB214 + .4byte .LFE214-.LFB214 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2d9d + .uleb128 0x57 + .4byte .LASF420 + .byte 0x1 + .byte 0x1d + .4byte 0x4ba + .4byte .LLST58 + .byte 0 + .uleb128 0x67 + .4byte .LASF423 + .byte 0x1 + .byte 0x18 + .4byte 0x50 + .4byte .LFB213 + .4byte .LFE213-.LFB213 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2dd3 + .uleb128 0x58 + .ascii "fit\000" + .byte 0x1 + .byte 0x18 + .4byte 0x3be + .4byte .LLST57 + .uleb128 0x68 + .4byte .LASF374 + .byte 0x1 + .byte 0x18 + .4byte 0x50 + .uleb128 0x1 + .byte 0x51 + .byte 0 + .uleb128 0x46 + .4byte .LASF424 + .byte 0x2 + .2byte 0x3eb + .4byte 0xd7 + .byte 0x3 + .4byte 0x2e09 + .uleb128 0x47 + .4byte .LASF425 + .byte 0x2 + .2byte 0x3eb + .4byte 0x3be + .uleb128 0x47 + .4byte .LASF389 + .byte 0x2 + .2byte 0x3ec + .4byte 0x50 + .uleb128 0x52 + .ascii "len\000" + .byte 0x2 + .2byte 0x3ec + .4byte 0x237e + .byte 0 + .uleb128 0x46 + .4byte .LASF426 + .byte 0x2 + .2byte 0x2e1 + .4byte 0x13d + .byte 0x3 + .4byte 0x2e27 + .uleb128 0x52 + .ascii "hdr\000" + .byte 0x2 + .2byte 0x2e1 + .4byte 0x2e27 + .byte 0 + .uleb128 0x8 + .byte 0x4 + .4byte 0xab4 + .uleb128 0x60 + .4byte .LASF427 + .byte 0x1b + .byte 0x70 + .4byte 0x70 + .byte 0x3 + .4byte 0x2e47 + .uleb128 0x65 + .ascii "x\000" + .byte 0x1b + .byte 0x70 + .4byte 0x70 + .byte 0 + .uleb128 0x6d + .4byte 0x2b96 + .4byte .LFB236 + .4byte .LFE236-.LFB236 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2f8e + .uleb128 0x34 + .4byte 0x2ba6 + .4byte .LLST0 + .uleb128 0x34 + .4byte 0x2bbc + .4byte .LLST1 + .uleb128 0x34 + .4byte 0x2bc7 + .4byte .LLST2 + .uleb128 0x34 + .4byte 0x2bd2 + .4byte .LLST3 + .uleb128 0x6e + .4byte 0x2bb1 + .uleb128 0x6 + .byte 0xfa + .4byte 0x2bb1 + .byte 0x9f + .uleb128 0x37 + .4byte 0x2bdd + .4byte .LLST4 + .uleb128 0x37 + .4byte 0x2be8 + .4byte .LLST5 + .uleb128 0x37 + .4byte 0x2bf3 + .4byte .LLST6 + .uleb128 0x37 + .4byte 0x2bfe + .4byte .LLST7 + .uleb128 0x36 + .4byte 0x2c09 + .uleb128 0x2 + .byte 0x91 + .sleb128 -28 + .uleb128 0x37 + .4byte 0x2c14 + .4byte .LLST8 + .uleb128 0x40 + .4byte .LVL1 + .4byte 0x310e + .4byte 0x2ed3 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL5 + .4byte 0x2fe8 + .4byte 0x2eea + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x5 + .byte 0x3 + .4byte .LC4 + .byte 0 + .uleb128 0x40 + .4byte .LVL6 + .4byte 0x311a + .4byte 0x2f04 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL11 + .4byte 0x2fd1 + .4byte 0x2f2a + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x77 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x91 + .sleb128 -28 + .byte 0 + .uleb128 0x40 + .4byte .LVL13 + .4byte 0x2fe8 + .4byte 0x2f3e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL14 + .4byte 0x3125 + .4byte 0x2f58 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x76 + .sleb128 0 + .byte 0 + .uleb128 0x40 + .4byte .LVL18 + .4byte 0x2fd1 + .4byte 0x2f7e + .uleb128 0x3d + .uleb128 0x1 + .byte 0x50 + .uleb128 0x2 + .byte 0x75 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x2 + .byte 0x74 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x52 + .uleb128 0x2 + .byte 0x78 + .sleb128 0 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x53 + .uleb128 0x2 + .byte 0x91 + .sleb128 -28 + .byte 0 + .uleb128 0x3c + .4byte .LVL23 + .4byte 0x3130 + .uleb128 0x3d + .uleb128 0x1 + .byte 0x51 + .uleb128 0x1 + .byte 0x30 + .byte 0 + .byte 0 + .uleb128 0x6d + .4byte 0x2c99 + .4byte .LFB218 + .4byte .LFE218-.LFB218 + .uleb128 0x1 + .byte 0x9c + .4byte 0x2fb2 + .uleb128 0x34 + .4byte 0x2ca9 + .4byte .LLST62 + .uleb128 0x6e + .4byte 0x2cb4 + .uleb128 0x1 + .byte 0x51 + .byte 0 + .uleb128 0xc + .4byte 0xdd + .4byte 0x2fc5 + .uleb128 0x6f + .4byte 0xcb + .4byte 0x201b + .byte 0 + .uleb128 0x70 + .4byte .LASF428 + .4byte .LASF428 + .byte 0x2 + .2byte 0x3f6 + .uleb128 0x70 + .4byte .LASF429 + .4byte .LASF429 + .byte 0x1c + .2byte 0x2b2 + .uleb128 0x71 + .4byte .LASF430 + .4byte .LASF430 + .byte 0x1d + .byte 0xa3 + .uleb128 0x71 + .4byte .LASF431 + .4byte .LASF431 + .byte 0x1e + .byte 0x13 + .uleb128 0x70 + .4byte .LASF432 + .4byte .LASF432 + .byte 0x1c + .2byte 0x1a8 + .uleb128 0x70 + .4byte .LASF433 + .4byte .LASF433 + .byte 0x2 + .2byte 0x42f + .uleb128 0x70 + .4byte .LASF434 + .4byte .LASF434 + .byte 0x2 + .2byte 0x438 + .uleb128 0x70 + .4byte .LASF435 + .4byte .LASF435 + .byte 0x2 + .2byte 0x3f1 + .uleb128 0x71 + .4byte .LASF436 + .4byte .LASF436 + .byte 0x1a + .byte 0xf5 + .uleb128 0x71 + .4byte .LASF437 + .4byte .LASF437 + .byte 0x8 + .byte 0x27 + .uleb128 0x71 + .4byte .LASF438 + .4byte .LASF438 + .byte 0xc + .byte 0xc2 + .uleb128 0x71 + .4byte .LASF439 + .4byte .LASF439 + .byte 0x1d + .byte 0xe4 + .uleb128 0x70 + .4byte .LASF440 + .4byte .LASF440 + .byte 0x1c + .2byte 0x1c1 + .uleb128 0x70 + .4byte .LASF441 + .4byte .LASF441 + .byte 0x2 + .2byte 0x3f9 + .uleb128 0x70 + .4byte .LASF442 + .4byte .LASF442 + .byte 0x2 + .2byte 0x3fb + .uleb128 0x70 + .4byte .LASF443 + .4byte .LASF443 + .byte 0x2 + .2byte 0x3fd + .uleb128 0x70 + .4byte .LASF444 + .4byte .LASF444 + .byte 0x2 + .2byte 0x403 + .uleb128 0x70 + .4byte .LASF445 + .4byte .LASF445 + .byte 0x2 + .2byte 0x402 + .uleb128 0x70 + .4byte .LASF446 + .4byte .LASF446 + .byte 0x2 + .2byte 0x405 + .uleb128 0x70 + .4byte .LASF447 + .4byte .LASF447 + .byte 0x17 + .2byte 0x371 + .uleb128 0x70 + .4byte .LASF448 + .4byte .LASF448 + .byte 0x2 + .2byte 0x3fa + .uleb128 0x70 + .4byte .LASF449 + .4byte .LASF449 + .byte 0x2 + .2byte 0x5ab + .uleb128 0x70 + .4byte .LASF450 + .4byte .LASF450 + .byte 0x2 + .2byte 0x42a + .uleb128 0x70 + .4byte .LASF451 + .4byte .LASF451 + .byte 0x2 + .2byte 0x5a4 + .uleb128 0x71 + .4byte .LASF452 + .4byte .LASF452 + .byte 0x1e + .byte 0x11 + .uleb128 0x70 + .4byte .LASF453 + .4byte .LASF453 + .byte 0x17 + .2byte 0x16d + .uleb128 0x70 + .4byte .LASF454 + .4byte .LASF454 + .byte 0x2 + .2byte 0x400 + .uleb128 0x70 + .4byte .LASF455 + .4byte .LASF455 + .byte 0x1c + .2byte 0x182 + .uleb128 0x70 + .4byte .LASF456 + .4byte .LASF456 + .byte 0x2 + .2byte 0x5b9 + .uleb128 0x71 + .4byte .LASF457 + .4byte .LASF457 + .byte 0x1c + .byte 0xa9 + .uleb128 0x71 + .4byte .LASF458 + .4byte .LASF458 + .byte 0x1c + .byte 0xb6 + .uleb128 0x71 + .4byte .LASF459 + .4byte .LASF459 + .byte 0x8 + .byte 0x33 + .byte 0 + .section .debug_abbrev,"",%progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x55 + .uleb128 0x17 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x10 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x16 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3c + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x5 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .uleb128 0x6 + .uleb128 0x16 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x7 + .uleb128 0x26 + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x8 + .uleb128 0xf + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x9 + .uleb128 0xf + .byte 0 + .uleb128 0xb + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0xa + .uleb128 0x13 + .byte 0x1 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0xb + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0xc + .uleb128 0x1 + .byte 0x1 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0xd + .uleb128 0x21 + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2f + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0xe + .uleb128 0x21 + .byte 0 + .byte 0 + .byte 0 + .uleb128 0xf + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3c + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x10 + .uleb128 0x4 + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0xb + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x11 + .uleb128 0x28 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1c + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x12 + .uleb128 0x17 + .byte 0x1 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x13 + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x14 + .uleb128 0x13 + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x15 + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x16 + .uleb128 0xd + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x17 + .uleb128 0x13 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3c + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x18 + .uleb128 0x26 + .byte 0 + .byte 0 + .byte 0 + .uleb128 0x19 + .uleb128 0x15 + .byte 0x1 + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x1a + .uleb128 0x5 + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x1b + .uleb128 0x13 + .byte 0x1 + .uleb128 0xb + .uleb128 0x5 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x1c + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0x5 + .byte 0 + .byte 0 + .uleb128 0x1d + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0x5 + .byte 0 + .byte 0 + .uleb128 0x1e + .uleb128 0x21 + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2f + .uleb128 0x5 + .byte 0 + .byte 0 + .uleb128 0x1f + .uleb128 0x13 + .byte 0x1 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0xb + .uleb128 0x5 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x20 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3c + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x21 + .uleb128 0x4 + .byte 0x1 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x22 + .uleb128 0x4 + .byte 0x1 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x23 + .uleb128 0x13 + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x24 + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x25 + .uleb128 0x16 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x26 + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x38 + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x27 + .uleb128 0x13 + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0xb + .uleb128 0x5 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x28 + .uleb128 0x15 + .byte 0x1 + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x29 + .uleb128 0x4 + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0xb + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x2a + .uleb128 0x13 + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0xb + .uleb128 0x5 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x2b + .uleb128 0x17 + .byte 0x1 + .uleb128 0xb + .uleb128 0x5 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x2c + .uleb128 0xd + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x2d + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x2e + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2f + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x30 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x31 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x32 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1c + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x33 + .uleb128 0x1d + .byte 0x1 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x52 + .uleb128 0x1 + .uleb128 0x55 + .uleb128 0x17 + .uleb128 0x58 + .uleb128 0xb + .uleb128 0x59 + .uleb128 0x5 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x34 + .uleb128 0x5 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x35 + .uleb128 0xb + .byte 0x1 + .uleb128 0x55 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x36 + .uleb128 0x34 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x37 + .uleb128 0x34 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x38 + .uleb128 0xa + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x39 + .uleb128 0x34 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3a + .uleb128 0xb + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3b + .uleb128 0x1d + .byte 0x1 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x58 + .uleb128 0xb + .uleb128 0x59 + .uleb128 0x5 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3c + .uleb128 0x4109 + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x31 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3d + .uleb128 0x410a + .byte 0 + .uleb128 0x2 + .uleb128 0x18 + .uleb128 0x2111 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x3e + .uleb128 0x5 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3f + .uleb128 0xb + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .byte 0 + .byte 0 + .uleb128 0x40 + .uleb128 0x4109 + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x41 + .uleb128 0x4109 + .byte 0 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x31 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x42 + .uleb128 0x34 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x43 + .uleb128 0xb + .byte 0x1 + .uleb128 0x55 + .uleb128 0x17 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x44 + .uleb128 0x4109 + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x2113 + .uleb128 0x18 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x45 + .uleb128 0x34 + .byte 0 + .uleb128 0x34 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x46 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x20 + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x47 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x48 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x49 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x4a + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x34 + .uleb128 0x19 + .uleb128 0x1c + .uleb128 0xe + .byte 0 + .byte 0 + .uleb128 0x4b + .uleb128 0xa + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .byte 0 + .byte 0 + .uleb128 0x4c + .uleb128 0xb + .byte 0x1 + .byte 0 + .byte 0 + .uleb128 0x4d + .uleb128 0x21 + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x4e + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x4f + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2116 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x50 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1c + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x51 + .uleb128 0x4109 + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x2113 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x52 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x53 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x54 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x55 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x34 + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x56 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2116 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x57 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x58 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x59 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x5a + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x5b + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x5c + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x5d + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1c + .uleb128 0xb + .byte 0 + .byte 0 + .uleb128 0x5e + .uleb128 0xa + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .uleb128 0x11 + .uleb128 0x1 + .byte 0 + .byte 0 + .uleb128 0x5f + .uleb128 0x4109 + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x60 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x20 + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x61 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x62 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x63 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x64 + .uleb128 0x410a + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x2111 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x65 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x66 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x67 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x68 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x69 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x6a + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x6b + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x20 + .uleb128 0xb + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x6c + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x6d + .uleb128 0x2e + .byte 0x1 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x6 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x6e + .uleb128 0x5 + .byte 0 + .uleb128 0x31 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x6f + .uleb128 0x21 + .byte 0 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2f + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x70 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3c + .uleb128 0x19 + .uleb128 0x6e + .uleb128 0xe + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0x5 + .byte 0 + .byte 0 + .uleb128 0x71 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3c + .uleb128 0x19 + .uleb128 0x6e + .uleb128 0xe + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .byte 0 + .byte 0 + .byte 0 + .section .debug_loc,"",%progbits +.Ldebug_loc0: +.LLST67: + .4byte .LVL137 + .4byte .LVL143 + .2byte 0x1 + .byte 0x50 + .4byte .LVL143 + .4byte .LVL145 + .2byte 0x1 + .byte 0x54 + .4byte .LVL145 + .4byte .LVL146-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL146-1 + .4byte .LFE235 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST68: + .4byte .LVL137 + .4byte .LVL143 + .2byte 0x1 + .byte 0x51 + .4byte .LVL143 + .4byte .LVL145 + .2byte 0x1 + .byte 0x5b + .4byte .LVL145 + .4byte .LVL146-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL146-1 + .4byte .LFE235 + .2byte 0x1 + .byte 0x5b + .4byte 0 + .4byte 0 +.LLST69: + .4byte .LVL137 + .4byte .LVL141 + .2byte 0x1 + .byte 0x52 + .4byte .LVL141 + .4byte .LVL159 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte .LVL159 + .4byte .LVL160 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte .LVL160 + .4byte .LVL221 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte .LVL221 + .4byte .LVL228 + .2byte 0x3 + .byte 0x77 + .sleb128 80 + .4byte .LVL228 + .4byte .LVL230 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte .LVL230 + .4byte .LVL251 + .2byte 0x3 + .byte 0x77 + .sleb128 80 + .4byte .LVL251 + .4byte .LVL265 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte .LVL265 + .4byte .LVL267 + .2byte 0x3 + .byte 0x77 + .sleb128 80 + .4byte .LVL267 + .4byte .LVL268 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte .LVL268 + .4byte .LFE235 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte 0 + .4byte 0 +.LLST70: + .4byte .LVL137 + .4byte .LVL139 + .2byte 0x1 + .byte 0x53 + .4byte .LVL139 + .4byte .LVL143 + .2byte 0x1 + .byte 0x55 + .4byte .LVL143 + .4byte .LVL145 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL145 + .4byte .LVL148 + .2byte 0x1 + .byte 0x55 + .4byte .LVL148 + .4byte .LFE235 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST71: + .4byte .LVL138 + .4byte .LVL140 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte 0 + .4byte 0 +.LLST72: + .4byte .LVL137 + .4byte .LVL159 + .2byte 0x3 + .byte 0x9 + .byte 0xea + .byte 0x9f + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x3 + .byte 0x9 + .byte 0xea + .byte 0x9f + .4byte .LVL268 + .4byte .LVL269 + .2byte 0x3 + .byte 0x9 + .byte 0xea + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST73: + .4byte .LVL146 + .4byte .LVL148 + .2byte 0x1 + .byte 0x55 + .4byte .LVL148 + .4byte .LVL159 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL268 + .4byte .LVL269 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST74: + .4byte .LVL146 + .4byte .LVL159 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte .LVL268 + .4byte .LVL269 + .2byte 0x3 + .byte 0x7d + .sleb128 96 + .4byte 0 + .4byte 0 +.LLST75: + .4byte .LVL146 + .4byte .LVL159 + .2byte 0x1 + .byte 0x5b + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x1 + .byte 0x5b + .4byte .LVL268 + .4byte .LVL269 + .2byte 0x1 + .byte 0x5b + .4byte 0 + .4byte 0 +.LLST76: + .4byte .LVL146 + .4byte .LVL159 + .2byte 0x1 + .byte 0x54 + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x1 + .byte 0x54 + .4byte .LVL268 + .4byte .LVL269 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST77: + .4byte .LVL149 + .4byte .LVL150-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL150-1 + .4byte .LVL156 + .2byte 0x3 + .byte 0x7d + .sleb128 100 + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x3 + .byte 0x7d + .sleb128 100 + .4byte 0 + .4byte 0 +.LLST78: + .4byte .LVL155 + .4byte .LVL157 + .2byte 0x1 + .byte 0x50 + .4byte .LVL157 + .4byte .LVL158-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL158-1 + .4byte .LVL159 + .2byte 0x3 + .byte 0x7d + .sleb128 100 + .4byte .LVL160 + .4byte .LVL161 + .2byte 0x1 + .byte 0x50 + .4byte .LVL163 + .4byte .LVL164 + .2byte 0x1 + .byte 0x50 + .4byte .LVL164 + .4byte .LVL165-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL165-1 + .4byte .LVL166 + .2byte 0x1 + .byte 0x56 + .4byte .LVL166 + .4byte .LVL167 + .2byte 0x1 + .byte 0x50 + .4byte .LVL167 + .4byte .LVL169 + .2byte 0x1 + .byte 0x56 + .4byte .LVL169 + .4byte .LVL170 + .2byte 0x1 + .byte 0x50 + .4byte .LVL175 + .4byte .LVL176 + .2byte 0x1 + .byte 0x50 + .4byte .LVL176 + .4byte .LVL177-1 + .2byte 0x1 + .byte 0x53 + .4byte .LVL177 + .4byte .LVL178 + .2byte 0x1 + .byte 0x50 + .4byte .LVL179 + .4byte .LVL180 + .2byte 0x1 + .byte 0x50 + .4byte .LVL180 + .4byte .LVL181-1 + .2byte 0x1 + .byte 0x52 + .4byte .LVL196 + .4byte .LVL197 + .2byte 0x1 + .byte 0x50 + .4byte .LVL211 + .4byte .LVL214 + .2byte 0x1 + .byte 0x50 + .4byte .LVL214 + .4byte .LVL215-1 + .2byte 0x1 + .byte 0x53 + .4byte 0 + .4byte 0 +.LLST79: + .4byte .LVL146 + .4byte .LVL159 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL160 + .4byte .LVL172 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL172 + .4byte .LVL183 + .2byte 0x1 + .byte 0x56 + .4byte .LVL183 + .4byte .LVL187 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL187 + .4byte .LVL190 + .2byte 0x2 + .byte 0x31 + .byte 0x9f + .4byte .LVL190 + .4byte .LVL209 + .2byte 0x1 + .byte 0x56 + .4byte .LVL209 + .4byte .LVL210 + .2byte 0x2 + .byte 0x31 + .byte 0x9f + .4byte .LVL210 + .4byte .LVL217 + .2byte 0x1 + .byte 0x56 + .4byte .LVL217 + .4byte .LVL218 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL218 + .4byte .LVL219 + .2byte 0x1 + .byte 0x56 + .4byte 0 + .4byte 0 +.LLST80: + .4byte .LVL146 + .4byte .LVL159 + .2byte 0x3 + .byte 0x9 + .byte 0xff + .byte 0x9f + .4byte .LVL160 + .4byte .LVL172 + .2byte 0x3 + .byte 0x9 + .byte 0xff + .byte 0x9f + .4byte .LVL173 + .4byte .LVL174 + .2byte 0x1 + .byte 0x50 + .4byte .LVL174 + .4byte .LVL183 + .2byte 0x1 + .byte 0x58 + .4byte .LVL183 + .4byte .LVL184 + .2byte 0x3 + .byte 0x9 + .byte 0xff + .byte 0x9f + .4byte .LVL184 + .4byte .LVL185 + .2byte 0x1 + .byte 0x50 + .4byte .LVL185 + .4byte .LVL187 + .2byte 0x1 + .byte 0x58 + .4byte .LVL187 + .4byte .LVL188 + .2byte 0x1 + .byte 0x50 + .4byte .LVL188 + .4byte .LVL190 + .2byte 0x1 + .byte 0x58 + .4byte .LVL191 + .4byte .LVL194 + .2byte 0x1 + .byte 0x50 + .4byte .LVL194 + .4byte .LVL195-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL195-1 + .4byte .LVL203 + .2byte 0x1 + .byte 0x5a + .4byte .LVL209 + .4byte .LVL217 + .2byte 0x1 + .byte 0x58 + .4byte .LVL217 + .4byte .LVL219 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST81: + .4byte .LVL147 + .4byte .LVL149-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL149-1 + .4byte .LVL159 + .2byte 0x1 + .byte 0x55 + .4byte .LVL160 + .4byte .LVL219 + .2byte 0x1 + .byte 0x55 + .4byte .LVL268 + .4byte .LVL269 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST82: + .4byte .LVL189 + .4byte .LVL190 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST83: + .4byte .LVL151 + .4byte .LVL152 + .2byte 0x1 + .byte 0x50 + .4byte .LVL152 + .4byte .LVL153 + .2byte 0x1 + .byte 0x51 + .4byte .LVL153 + .4byte .LVL154 + .2byte 0x1 + .byte 0x50 + .4byte .LVL154 + .4byte .LVL155-1 + .2byte 0x1 + .byte 0x51 + .4byte 0 + .4byte 0 +.LLST84: + .4byte .LVL192 + .4byte .LVL193 + .2byte 0x4 + .byte 0x7d + .sleb128 107 + .byte 0x9f + .4byte .LVL193 + .4byte .LVL195-1 + .2byte 0x1 + .byte 0x52 + .4byte .LVL195-1 + .4byte .LVL195 + .2byte 0x4 + .byte 0x7d + .sleb128 107 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST85: + .4byte .LVL192 + .4byte .LVL194 + .2byte 0x1 + .byte 0x50 + .4byte .LVL194 + .4byte .LVL195-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL195-1 + .4byte .LVL195 + .2byte 0x1 + .byte 0x5a + .4byte 0 + .4byte 0 +.LLST86: + .4byte .LVL192 + .4byte .LVL195 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST87: + .4byte .LVL199 + .4byte .LVL207 + .2byte 0x4 + .byte 0x7d + .sleb128 176 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST88: + .4byte .LVL199 + .4byte .LVL207 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST89: + .4byte .LVL199 + .4byte .LVL207 + .2byte 0x1 + .byte 0x56 + .4byte 0 + .4byte 0 +.LLST90: + .4byte .LVL199 + .4byte .LVL207 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST91: + .4byte .LVL199 + .4byte .LVL200 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL200 + .4byte .LVL201 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST92: + .4byte .LVL203 + .4byte .LVL204 + .2byte 0x1 + .byte 0x50 + .4byte .LVL204 + .4byte .LVL205-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL205-1 + .4byte .LVL207 + .2byte 0x1 + .byte 0x5a + .4byte 0 + .4byte 0 +.LLST93: + .4byte .LVL212 + .4byte .LVL213 + .2byte 0x3 + .byte 0x74 + .sleb128 4 + .byte 0x9f + .4byte .LVL213 + .4byte .LVL215-1 + .2byte 0x1 + .byte 0x52 + .4byte .LVL215-1 + .4byte .LVL215 + .2byte 0x3 + .byte 0x74 + .sleb128 4 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST94: + .4byte .LVL212 + .4byte .LVL215 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST95: + .4byte .LVL212 + .4byte .LVL215 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST96: + .4byte .LVL219 + .4byte .LVL229 + .2byte 0x1 + .byte 0x5b + .4byte .LVL230 + .4byte .LVL268 + .2byte 0x1 + .byte 0x5b + .4byte 0 + .4byte 0 +.LLST97: + .4byte .LVL219 + .4byte .LVL229 + .2byte 0x1 + .byte 0x54 + .4byte .LVL230 + .4byte .LVL268 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST99: + .4byte .LVL222 + .4byte .LVL227 + .2byte 0x2 + .byte 0x76 + .sleb128 0 + .4byte .LVL227 + .4byte .LVL229 + .2byte 0x2 + .byte 0x7d + .sleb128 16 + .4byte .LVL230 + .4byte .LVL237 + .2byte 0x2 + .byte 0x76 + .sleb128 0 + .4byte .LVL237 + .4byte .LVL265 + .2byte 0x2 + .byte 0x7d + .sleb128 16 + .4byte .LVL265 + .4byte .LVL266 + .2byte 0x2 + .byte 0x76 + .sleb128 0 + .4byte .LVL266 + .4byte .LVL268 + .2byte 0x2 + .byte 0x7d + .sleb128 16 + .4byte 0 + .4byte 0 +.LLST100: + .4byte .LVL250 + .4byte .LVL252 + .2byte 0x1 + .byte 0x50 + .4byte .LVL267 + .4byte .LVL268 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST101: + .4byte .LVL231 + .4byte .LVL232 + .2byte 0x1 + .byte 0x53 + .4byte .LVL232 + .4byte .LVL244 + .2byte 0x3 + .byte 0x77 + .sleb128 84 + .4byte .LVL247 + .4byte .LVL252 + .2byte 0x3 + .byte 0x77 + .sleb128 84 + .4byte .LVL265 + .4byte .LVL268 + .2byte 0x3 + .byte 0x77 + .sleb128 84 + .4byte 0 + .4byte 0 +.LLST102: + .4byte .LVL253 + .4byte .LVL254 + .2byte 0x1 + .byte 0x50 + .4byte .LVL254 + .4byte .LVL255-1 + .2byte 0x2 + .byte 0x7d + .sleb128 0 + .4byte 0 + .4byte 0 +.LLST103: + .4byte .LVL243 + .4byte .LVL245 + .2byte 0x1 + .byte 0x50 + .4byte .LVL245 + .4byte .LVL246-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL246-1 + .4byte .LVL247 + .2byte 0x3 + .byte 0x77 + .sleb128 84 + .4byte .LVL247 + .4byte .LVL248 + .2byte 0x1 + .byte 0x50 + .4byte .LVL248 + .4byte .LVL252 + .2byte 0x3 + .byte 0x77 + .sleb128 72 + .4byte .LVL255 + .4byte .LVL256 + .2byte 0x1 + .byte 0x50 + .4byte .LVL256 + .4byte .LVL257-1 + .2byte 0x1 + .byte 0x53 + .4byte .LVL267 + .4byte .LVL268 + .2byte 0x3 + .byte 0x77 + .sleb128 72 + .4byte 0 + .4byte 0 +.LLST104: + .4byte .LVL252 + .4byte .LVL262 + .2byte 0x1 + .byte 0x55 + .4byte .LVL263 + .4byte .LVL265 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST105: + .4byte .LVL236 + .4byte .LVL238-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL238-1 + .4byte .LVL262 + .2byte 0x1 + .byte 0x56 + .4byte .LVL263 + .4byte .LVL265 + .2byte 0x1 + .byte 0x56 + .4byte .LVL266 + .4byte .LVL267 + .2byte 0x1 + .byte 0x50 + .4byte .LVL267 + .4byte .LVL268 + .2byte 0x1 + .byte 0x56 + .4byte 0 + .4byte 0 +.LLST106: + .4byte .LVL223 + .4byte .LVL224 + .2byte 0x6 + .byte 0x3 + .4byte .LC15 + .byte 0x9f + .4byte .LVL224 + .4byte .LVL225 + .2byte 0x1 + .byte 0x50 + .4byte .LVL225 + .4byte .LVL226-1 + .2byte 0x1 + .byte 0x51 + .4byte 0 + .4byte 0 +.LLST107: + .4byte .LVL238 + .4byte .LVL239 + .2byte 0x1 + .byte 0x50 + .4byte .LVL239 + .4byte .LVL240-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL241 + .4byte .LVL242 + .2byte 0x1 + .byte 0x50 + .4byte .LVL242 + .4byte .LVL243-1 + .2byte 0x1 + .byte 0x51 + .4byte 0 + .4byte 0 +.LLST98: + .4byte .LVL220 + .4byte .LVL224-1 + .2byte 0x6 + .byte 0x7b + .sleb128 8 + .byte 0x6 + .byte 0x31 + .byte 0x1c + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST66: + .4byte .LVL135 + .4byte .LVL136 + .2byte 0x1 + .byte 0x50 + .4byte .LVL136 + .4byte .LFE232 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST47: + .4byte .LVL105 + .4byte .LVL109 + .2byte 0x1 + .byte 0x50 + .4byte .LVL109 + .4byte .LVL117 + .2byte 0x1 + .byte 0x54 + .4byte .LVL117 + .4byte .LFE231 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST48: + .4byte .LVL105 + .4byte .LVL111 + .2byte 0x1 + .byte 0x51 + .4byte .LVL111 + .4byte .LVL117 + .2byte 0x1 + .byte 0x55 + .4byte .LVL117 + .4byte .LFE231 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x51 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST49: + .4byte .LVL105 + .4byte .LVL106 + .2byte 0x1 + .byte 0x52 + .4byte .LVL106 + .4byte .LFE231 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST50: + .4byte .LVL105 + .4byte .LVL110 + .2byte 0x1 + .byte 0x53 + .4byte .LVL110 + .4byte .LFE231 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST51: + .4byte .LVL115 + .4byte .LVL116 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST52: + .4byte .LVL107 + .4byte .LVL108 + .2byte 0x2d + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x23 + .uleb128 0x4 + .byte 0x6 + .byte 0x38 + .byte 0x24 + .byte 0x8 + .byte 0xff + .byte 0x40 + .byte 0x24 + .byte 0x1a + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x23 + .uleb128 0x4 + .byte 0x6 + .byte 0x38 + .byte 0x25 + .byte 0xa + .2byte 0xff00 + .byte 0x1a + .byte 0x21 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x23 + .uleb128 0x4 + .byte 0x6 + .byte 0x48 + .byte 0x25 + .byte 0x21 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x23 + .uleb128 0x4 + .byte 0x6 + .byte 0x48 + .byte 0x24 + .byte 0x21 + .byte 0x9f + .4byte .LVL108 + .4byte .LVL114-1 + .2byte 0x7 + .byte 0x72 + .sleb128 0 + .byte 0xb + .2byte 0xfe00 + .byte 0x1a + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST53: + .4byte .LVL112 + .4byte .LVL117 + .2byte 0x1 + .byte 0x56 + .4byte 0 + .4byte 0 +.LLST54: + .4byte .LVL112 + .4byte .LVL114 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST55: + .4byte .LVL112 + .4byte .LVL113 + .2byte 0x1 + .byte 0x50 + .4byte .LVL113 + .4byte .LVL114-1 + .2byte 0x7 + .byte 0x72 + .sleb128 0 + .byte 0xb + .2byte 0xfe00 + .byte 0x1a + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST56: + .4byte .LVL112 + .4byte .LVL114 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST65: + .4byte .LVL133 + .4byte .LVL134 + .2byte 0x1 + .byte 0x50 + .4byte .LVL134 + .4byte .LFE230 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST39: + .4byte .LVL94 + .4byte .LVL98 + .2byte 0x1 + .byte 0x50 + .4byte .LVL98 + .4byte .LVL104 + .2byte 0x1 + .byte 0x54 + .4byte .LVL104 + .4byte .LFE227 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST40: + .4byte .LVL94 + .4byte .LVL97 + .2byte 0x1 + .byte 0x51 + .4byte .LVL97 + .4byte .LVL104 + .2byte 0x1 + .byte 0x56 + .4byte .LVL104 + .4byte .LFE227 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x51 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST41: + .4byte .LVL94 + .4byte .LVL96 + .2byte 0x1 + .byte 0x52 + .4byte .LVL96 + .4byte .LVL104 + .2byte 0x1 + .byte 0x57 + .4byte .LVL104 + .4byte .LFE227 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST42: + .4byte .LVL94 + .4byte .LVL95 + .2byte 0x1 + .byte 0x53 + .4byte .LVL95 + .4byte .LVL104 + .2byte 0x1 + .byte 0x55 + .4byte .LVL104 + .4byte .LFE227 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST43: + .4byte .LVL94 + .4byte .LVL104 + .2byte 0x2 + .byte 0x91 + .sleb128 0 + .4byte .LVL104 + .4byte .LFE227 + .2byte 0x2 + .byte 0x7d + .sleb128 0 + .4byte 0 + .4byte 0 +.LLST44: + .4byte .LVL94 + .4byte .LVL104 + .2byte 0x2 + .byte 0x91 + .sleb128 4 + .4byte .LVL104 + .4byte .LFE227 + .2byte 0x2 + .byte 0x7d + .sleb128 4 + .4byte 0 + .4byte 0 +.LLST45: + .4byte .LVL99 + .4byte .LVL100 + .2byte 0x1 + .byte 0x50 + .4byte .LVL100 + .4byte .LVL101-1 + .2byte 0x2 + .byte 0x7d + .sleb128 0 + .4byte 0 + .4byte 0 +.LLST46: + .4byte .LVL101 + .4byte .LVL102 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST15: + .4byte .LVL38 + .4byte .LVL43 + .2byte 0x1 + .byte 0x50 + .4byte .LVL43 + .4byte .LFE226 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST16: + .4byte .LVL38 + .4byte .LVL42 + .2byte 0x1 + .byte 0x51 + .4byte .LVL42 + .4byte .LFE226 + .2byte 0x3 + .byte 0x91 + .sleb128 -68 + .4byte 0 + .4byte 0 +.LLST17: + .4byte .LVL38 + .4byte .LVL39 + .2byte 0x1 + .byte 0x52 + .4byte .LVL39 + .4byte .LVL75 + .2byte 0x1 + .byte 0x54 + .4byte .LVL75 + .4byte .LVL77-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL77-1 + .4byte .LVL85 + .2byte 0x1 + .byte 0x54 + .4byte .LVL85 + .4byte .LVL86-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL86-1 + .4byte .LFE226 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST18: + .4byte .LVL38 + .4byte .LVL40 + .2byte 0x1 + .byte 0x53 + .4byte .LVL40 + .4byte .LVL50 + .2byte 0x1 + .byte 0x57 + .4byte .LVL50 + .4byte .LVL68 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL68 + .4byte .LVL69 + .2byte 0x1 + .byte 0x57 + .4byte .LVL69 + .4byte .LVL73 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL73 + .4byte .LVL74 + .2byte 0x1 + .byte 0x57 + .4byte .LVL74 + .4byte .LVL90 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL90 + .4byte .LVL92 + .2byte 0x1 + .byte 0x57 + .4byte .LVL92 + .4byte .LFE226 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST19: + .4byte .LVL38 + .4byte .LVL68 + .2byte 0x2 + .byte 0x91 + .sleb128 0 + .4byte .LVL68 + .4byte .LFE226 + .2byte 0x2 + .byte 0x91 + .sleb128 0 + .4byte 0 + .4byte 0 +.LLST20: + .4byte .LVL38 + .4byte .LVL68 + .2byte 0x2 + .byte 0x91 + .sleb128 4 + .4byte .LVL68 + .4byte .LFE226 + .2byte 0x2 + .byte 0x91 + .sleb128 4 + .4byte 0 + .4byte 0 +.LLST21: + .4byte .LVL53 + .4byte .LVL54-1 + .2byte 0x1 + .byte 0x53 + .4byte .LVL54-1 + .4byte .LVL65 + .2byte 0x3 + .byte 0x91 + .sleb128 -80 + .4byte .LVL69 + .4byte .LVL73 + .2byte 0x3 + .byte 0x91 + .sleb128 -80 + .4byte .LVL88 + .4byte .LVL89 + .2byte 0x3 + .byte 0x91 + .sleb128 -80 + .4byte 0 + .4byte 0 +.LLST22: + .4byte .LVL57 + .4byte .LVL65 + .2byte 0x1 + .byte 0x5b + .4byte .LVL71 + .4byte .LVL73 + .2byte 0x1 + .byte 0x5b + .4byte .LVL88 + .4byte .LVL89 + .2byte 0x1 + .byte 0x5b + .4byte 0 + .4byte 0 +.LLST23: + .4byte .LVL41 + .4byte .LVL67 + .2byte 0x3 + .byte 0x9 + .byte 0xff + .byte 0x9f + .4byte .LVL68 + .4byte .LVL93 + .2byte 0x3 + .byte 0x9 + .byte 0xff + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST24: + .4byte .LVL41 + .4byte .LVL51 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL51 + .4byte .LVL65 + .2byte 0x2 + .byte 0x31 + .byte 0x9f + .4byte .LVL68 + .4byte .LVL69 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL69 + .4byte .LVL73 + .2byte 0x2 + .byte 0x31 + .byte 0x9f + .4byte .LVL73 + .4byte .LVL74 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL88 + .4byte .LVL89 + .2byte 0x2 + .byte 0x31 + .byte 0x9f + .4byte .LVL90 + .4byte .LVL92 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST25: + .4byte .LVL41 + .4byte .LVL61 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL61 + .4byte .LVL62 + .2byte 0x1 + .byte 0x50 + .4byte .LVL68 + .4byte .LVL71 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL73 + .4byte .LVL74 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte .LVL90 + .4byte .LFE226 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST26: + .4byte .LVL44 + .4byte .LVL45-1 + .2byte 0x1 + .byte 0x53 + .4byte .LVL45-1 + .4byte .LFE226 + .2byte 0x3 + .byte 0x91 + .sleb128 -76 + .4byte 0 + .4byte 0 +.LLST27: + .4byte .LVL56 + .4byte .LVL57 + .2byte 0x1 + .byte 0x50 + .4byte .LVL69 + .4byte .LVL70-1 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST28: + .4byte .LVL56 + .4byte .LVL57 + .2byte 0x1 + .byte 0x58 + .4byte .LVL69 + .4byte .LVL71 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST29: + .4byte .LVL57 + .4byte .LVL60 + .2byte 0x1 + .byte 0x5a + .4byte 0 + .4byte 0 +.LLST30: + .4byte .LVL57 + .4byte .LVL60 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST31: + .4byte .LVL62 + .4byte .LVL63 + .2byte 0x1 + .byte 0x50 + .4byte .LVL71 + .4byte .LVL72-1 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST32: + .4byte .LVL62 + .4byte .LVL63 + .2byte 0x1 + .byte 0x58 + .4byte .LVL71 + .4byte .LVL73 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST33: + .4byte .LVL76 + .4byte .LVL78 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST34: + .4byte .LVL76 + .4byte .LVL77-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL77-1 + .4byte .LVL78 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST35: + .4byte .LVL76 + .4byte .LVL77-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL77-1 + .4byte .LVL78 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST36: + .4byte .LVL85 + .4byte .LVL86 + .2byte 0x2 + .byte 0x30 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST37: + .4byte .LVL85 + .4byte .LVL86-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL86-1 + .4byte .LVL86 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST38: + .4byte .LVL85 + .4byte .LVL86-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL86-1 + .4byte .LVL86 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST9: + .4byte .LVL30 + .4byte .LVL34-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL34-1 + .4byte .LFE222 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST10: + .4byte .LVL30 + .4byte .LVL31 + .2byte 0x1 + .byte 0x51 + .4byte .LVL31 + .4byte .LFE222 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST11: + .4byte .LVL30 + .4byte .LVL32 + .2byte 0x1 + .byte 0x52 + .4byte .LVL32 + .4byte .LVL34-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL34-1 + .4byte .LFE222 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST12: + .4byte .LVL30 + .4byte .LVL33 + .2byte 0x1 + .byte 0x53 + .4byte .LVL33 + .4byte .LVL34-1 + .2byte 0x1 + .byte 0x52 + .4byte .LVL34-1 + .4byte .LFE222 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST13: + .4byte .LVL34 + .4byte .LVL35 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST14: + .4byte .LVL36 + .4byte .LVL37 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST63: + .4byte .LVL130 + .4byte .LVL132 + .2byte 0x1 + .byte 0x50 + .4byte .LVL132 + .4byte .LFE220 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST64: + .4byte .LVL130 + .4byte .LVL131 + .2byte 0x1 + .byte 0x51 + .4byte .LVL131 + .4byte .LFE220 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x51 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST60: + .4byte .LVL124 + .4byte .LVL125 + .2byte 0x1 + .byte 0x50 + .4byte .LVL125 + .4byte .LFE216 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST61: + .4byte .LVL124 + .4byte .LVL126-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL126-1 + .4byte .LFE216 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x51 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST59: + .4byte .LVL122 + .4byte .LVL123 + .2byte 0x1 + .byte 0x50 + .4byte .LVL123 + .4byte .LFE215 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST58: + .4byte .LVL120 + .4byte .LVL121 + .2byte 0x1 + .byte 0x50 + .4byte .LVL121 + .4byte .LFE214 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST57: + .4byte .LVL118 + .4byte .LVL119 + .2byte 0x1 + .byte 0x50 + .4byte .LVL119 + .4byte .LFE213 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST0: + .4byte .LVL0 + .4byte .LVL1-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL1-1 + .4byte .LVL8 + .2byte 0x1 + .byte 0x55 + .4byte .LVL8 + .4byte .LVL9 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte .LVL9 + .4byte .LVL19 + .2byte 0x1 + .byte 0x55 + .4byte .LVL19 + .4byte .LFE236 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 +.LLST1: + .4byte .LVL0 + .4byte .LVL1-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL1-1 + .4byte .LVL4 + .2byte 0x1 + .byte 0x58 + .4byte .LVL4 + .4byte .LVL16 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x51 + .byte 0x9f + .4byte .LVL16 + .4byte .LFE236 + .2byte 0x1 + .byte 0x58 + .4byte 0 + .4byte 0 +.LLST2: + .4byte .LVL0 + .4byte .LVL1-1 + .2byte 0x1 + .byte 0x52 + .4byte .LVL1-1 + .4byte .LVL3 + .2byte 0x1 + .byte 0x57 + .4byte .LVL3 + .4byte .LVL16 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x52 + .byte 0x9f + .4byte .LVL16 + .4byte .LFE236 + .2byte 0x1 + .byte 0x57 + .4byte 0 + .4byte 0 +.LLST3: + .4byte .LVL0 + .4byte .LVL1-1 + .2byte 0x1 + .byte 0x53 + .4byte .LVL1-1 + .4byte .LVL7 + .2byte 0x1 + .byte 0x56 + .4byte .LVL7 + .4byte .LVL16 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x53 + .byte 0x9f + .4byte .LVL16 + .4byte .LFE236 + .2byte 0x1 + .byte 0x56 + .4byte 0 + .4byte 0 +.LLST4: + .4byte .LVL11 + .4byte .LVL12 + .2byte 0x1 + .byte 0x50 + .4byte .LVL12 + .4byte .LVL13-1 + .2byte 0x1 + .byte 0x51 + .4byte .LVL18 + .4byte .LVL20 + .2byte 0x1 + .byte 0x50 + .4byte .LVL20 + .4byte .LVL26 + .2byte 0x1 + .byte 0x55 + .4byte .LVL26 + .4byte .LVL28 + .2byte 0x1 + .byte 0x50 + .4byte .LVL28 + .4byte .LFE236 + .2byte 0x1 + .byte 0x55 + .4byte 0 + .4byte 0 +.LLST5: + .4byte .LVL20 + .4byte .LVL23-1 + .2byte 0x1 + .byte 0x50 + .4byte .LVL23 + .4byte .LVL24 + .2byte 0x3 + .byte 0x70 + .sleb128 1 + .byte 0x9f + .4byte .LVL24 + .4byte .LVL26 + .2byte 0x1 + .byte 0x50 + .4byte .LVL28 + .4byte .LFE236 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST6: + .4byte .LVL7 + .4byte .LVL8 + .2byte 0x1 + .byte 0x50 + .4byte .LVL9 + .4byte .LVL10 + .2byte 0x1 + .byte 0x50 + .4byte .LVL10 + .4byte .LVL15 + .2byte 0x1 + .byte 0x56 + .4byte .LVL15 + .4byte .LVL16 + .2byte 0x1 + .byte 0x50 + .4byte 0 + .4byte 0 +.LLST7: + .4byte .LVL1 + .4byte .LVL2 + .2byte 0x1 + .byte 0x50 + .4byte .LVL2 + .4byte .LVL8 + .2byte 0x1 + .byte 0x54 + .4byte .LVL9 + .4byte .LVL16 + .2byte 0x1 + .byte 0x54 + .4byte .LVL16 + .4byte .LVL17 + .2byte 0x1 + .byte 0x50 + .4byte .LVL17 + .4byte .LVL20 + .2byte 0x1 + .byte 0x54 + .4byte .LVL26 + .4byte .LVL27 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST8: + .4byte .LVL20 + .4byte .LVL21 + .2byte 0x1 + .byte 0x54 + .4byte .LVL22 + .4byte .LVL26 + .2byte 0x1 + .byte 0x54 + .4byte .LVL28 + .4byte .LVL29 + .2byte 0x1 + .byte 0x54 + .4byte 0 + .4byte 0 +.LLST62: + .4byte .LVL127 + .4byte .LVL128 + .2byte 0x1 + .byte 0x50 + .4byte .LVL128 + .4byte .LFE218 + .2byte 0x4 + .byte 0xf3 + .uleb128 0x1 + .byte 0x50 + .byte 0x9f + .4byte 0 + .4byte 0 + .section .debug_aranges,"",%progbits + .4byte 0x8c + .2byte 0x2 + .4byte .Ldebug_info0 + .byte 0x4 + .byte 0 + .2byte 0 + .2byte 0 + .4byte .LFB236 + .4byte .LFE236-.LFB236 + .4byte .LFB222 + .4byte .LFE222-.LFB222 + .4byte .LFB226 + .4byte .LFE226-.LFB226 + .4byte .LFB227 + .4byte .LFE227-.LFB227 + .4byte .LFB231 + .4byte .LFE231-.LFB231 + .4byte .LFB213 + .4byte .LFE213-.LFB213 + .4byte .LFB214 + .4byte .LFE214-.LFB214 + .4byte .LFB215 + .4byte .LFE215-.LFB215 + .4byte .LFB216 + .4byte .LFE216-.LFB216 + .4byte .LFB218 + .4byte .LFE218-.LFB218 + .4byte .LFB219 + .4byte .LFE219-.LFB219 + .4byte .LFB220 + .4byte .LFE220-.LFB220 + .4byte .LFB230 + .4byte .LFE230-.LFB230 + .4byte .LFB232 + .4byte .LFE232-.LFB232 + .4byte .LFB235 + .4byte .LFE235-.LFB235 + .4byte 0 + .4byte 0 + .section .debug_ranges,"",%progbits +.Ldebug_ranges0: + .4byte .LBB36 + .4byte .LBE36 + .4byte .LBB40 + .4byte .LBE40 + .4byte .LBB46 + .4byte .LBE46 + .4byte 0 + .4byte 0 + .4byte .LBB43 + .4byte .LBE43 + .4byte .LBB47 + .4byte .LBE47 + .4byte 0 + .4byte 0 + .4byte .LBB48 + .4byte .LBE48 + .4byte .LBB52 + .4byte .LBE52 + .4byte .LBB53 + .4byte .LBE53 + .4byte 0 + .4byte 0 + .4byte .LBB84 + .4byte .LBE84 + .4byte .LBB97 + .4byte .LBE97 + .4byte .LBB98 + .4byte .LBE98 + .4byte .LBB99 + .4byte .LBE99 + .4byte .LBB106 + .4byte .LBE106 + .4byte 0 + .4byte 0 + .4byte .LBB100 + .4byte .LBE100 + .4byte .LBB105 + .4byte .LBE105 + .4byte 0 + .4byte 0 + .4byte .LBB102 + .4byte .LBE102 + .4byte .LBB103 + .4byte .LBE103 + .4byte 0 + .4byte 0 + .4byte .LFB236 + .4byte .LFE236 + .4byte .LFB222 + .4byte .LFE222 + .4byte .LFB226 + .4byte .LFE226 + .4byte .LFB227 + .4byte .LFE227 + .4byte .LFB231 + .4byte .LFE231 + .4byte .LFB213 + .4byte .LFE213 + .4byte .LFB214 + .4byte .LFE214 + .4byte .LFB215 + .4byte .LFE215 + .4byte .LFB216 + .4byte .LFE216 + .4byte .LFB218 + .4byte .LFE218 + .4byte .LFB219 + .4byte .LFE219 + .4byte .LFB220 + .4byte .LFE220 + .4byte .LFB230 + .4byte .LFE230 + .4byte .LFB232 + .4byte .LFE232 + .4byte .LFB235 + .4byte .LFE235 + .4byte 0 + .4byte 0 + .section .debug_line,"",%progbits +.Ldebug_line0: + .section .debug_str,"MS",%progbits,1 +.LASF45: + .ascii "IF_TYPE_SPINAND\000" +.LASF82: + .ascii "flash_id\000" +.LASF307: + .ascii "mem_malloc_start\000" +.LASF457: + .ascii "fdt_first_subnode\000" +.LASF283: + .ascii "net_hostname\000" +.LASF74: + .ascii "name\000" +.LASF319: + .ascii "spl_load_info\000" +.LASF44: + .ascii "IF_TYPE_RKNAND\000" +.LASF303: + .ascii "NETLOOP_RESTART\000" +.LASF299: + .ascii "net_boot_file_size\000" +.LASF312: + .ascii "spl_image_info\000" +.LASF170: + .ascii "IH_TYPE_SCRIPT\000" +.LASF120: + .ascii "_datarellocal_start_ofs\000" +.LASF123: + .ascii "fdt32_t\000" +.LASF417: + .ascii "slot\000" +.LASF439: + .ascii "fdt_shrink_to_minimum\000" +.LASF382: + .ascii "part_info\000" +.LASF313: + .ascii "entry_point\000" +.LASF108: + .ascii "bi_enetaddr\000" +.LASF385: + .ascii "align_len\000" +.LASF384: + .ascii "spl_kernel_partition\000" +.LASF318: + .ascii "flags\000" +.LASF434: + .ascii "fit_conf_get_node\000" +.LASF407: + .ascii "get_aligned_image_overhead\000" +.LASF238: + .ascii "fit_noffset_rd\000" +.LASF326: + .ascii "baudrate\000" +.LASF359: + .ascii "tos_mem\000" +.LASF24: + .ascii "errno\000" +.LASF167: + .ascii "IH_TYPE_RAMDISK\000" +.LASF361: + .ascii "atf_mem\000" +.LASF8: + .ascii "unsigned int\000" +.LASF275: + .ascii "next\000" +.LASF130: + .ascii "version\000" +.LASF230: + .ascii "legacy_hdr_os_copy\000" +.LASF354: + .ascii "tag_header\000" +.LASF174: + .ascii "IH_TYPE_IMXIMAGE\000" +.LASF365: + .ascii "spl_image\000" +.LASF219: + .ascii "ih_name\000" +.LASF291: + .ascii "net_rx_packet\000" +.LASF403: + .ascii "external_data\000" +.LASF241: + .ascii "fit_noffset_fdt\000" +.LASF50: + .ascii "if_type\000" +.LASF181: + .ascii "IH_TYPE_GPIMAGE\000" +.LASF333: + .ascii "tag_ddr_mem\000" +.LASF25: + .ascii "___strtok\000" +.LASF97: + .ascii "bi_memsize\000" +.LASF35: + .ascii "IF_TYPE_ATAPI\000" +.LASF221: + .ascii "image_info\000" +.LASF387: + .ascii "spl_fit_standalone_release\000" +.LASF255: + .ascii "bootm_headers_t\000" +.LASF204: + .ascii "IH_COMP_LZ4\000" +.LASF430: + .ascii "fdt_record_loadable\000" +.LASF115: + .ascii "bd_t\000" +.LASF460: + .ascii "GNU C11 6.3.1 20170404 -mthumb -mthumb-interwork -m" + .ascii "abi=aapcs-linux -mno-unaligned-access -mfloat-abi=s" + .ascii "oft -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16" + .ascii " -mtls-dialect=gnu -g -Os -fno-builtin -ffreestandi" + .ascii "ng -fshort-wchar -fno-stack-protector -fno-delete-n" + .ascii "ull-pointer-checks -fstack-usage -ffunction-section" + .ascii "s -fdata-sections -fno-common -ffixed-r9\000" +.LASF188: + .ascii "IH_TYPE_RKSD\000" +.LASF261: + .ascii "__dtb_dt_spl_begin\000" +.LASF308: + .ascii "mem_malloc_end\000" +.LASF38: + .ascii "IF_TYPE_MMC\000" +.LASF450: + .ascii "fit_image_verify_with_data\000" +.LASF152: + .ascii "IH_OS_QNX\000" +.LASF102: + .ascii "bi_sramsize\000" +.LASF121: + .ascii "_datarelro_start_ofs\000" +.LASF331: + .ascii "mode\000" +.LASF53: + .ascii "SIG_TYPE_MBR\000" +.LASF298: + .ascii "net_boot_file_name\000" +.LASF55: + .ascii "SIG_TYPE_COUNT\000" +.LASF231: + .ascii "legacy_hdr_valid\000" +.LASF79: + .ascii "bootable\000" +.LASF350: + .ascii "tag_pstore\000" +.LASF262: + .ascii "load_addr\000" +.LASF56: + .ascii "mbr_sig\000" +.LASF279: + .ascii "net_gateway\000" +.LASF245: + .ascii "rd_start\000" +.LASF311: + .ascii "__bss_end\000" +.LASF413: + .ascii "fit_rollback_index_verify\000" +.LASF449: + .ascii "fdt_getprop_u32\000" +.LASF211: + .ascii "ih_size\000" +.LASF43: + .ascii "IF_TYPE_NVME\000" +.LASF300: + .ascii "net_boot_file_expected_size_in_blocks\000" +.LASF169: + .ascii "IH_TYPE_FIRMWARE\000" +.LASF392: + .ascii "image\000" +.LASF191: + .ascii "IH_TYPE_ZYNQMPIMAGE\000" +.LASF40: + .ascii "IF_TYPE_SATA\000" +.LASF271: + .ascii "send\000" +.LASF3: + .ascii "signed char\000" +.LASF129: + .ascii "off_mem_rsvmap\000" +.LASF316: + .ascii "boot_device\000" +.LASF258: + .ascii "sha256_der_prefix\000" +.LASF248: + .ascii "ft_len\000" +.LASF22: + .ascii "uint32_t\000" +.LASF146: + .ascii "IH_OS_SCO\000" +.LASF264: + .ascii "save_size\000" +.LASF163: + .ascii "IH_OS_COUNT\000" +.LASF309: + .ascii "mem_malloc_brk\000" +.LASF323: + .ascii "tag_serial\000" +.LASF242: + .ascii "fit_hdr_setup\000" +.LASF65: + .ascii "blksz\000" +.LASF116: + .ascii "IRQ_STACK_START\000" +.LASF414: + .ascii "rollback_fd\000" +.LASF16: + .ascii "__kernel_size_t\000" +.LASF178: + .ascii "IH_TYPE_KERNEL_NOLOAD\000" +.LASF187: + .ascii "IH_TYPE_RKIMAGE\000" +.LASF446: + .ascii "fit_image_get_data_size\000" +.LASF381: + .ascii "part_name\000" +.LASF456: + .ascii "fit_find_config_node\000" +.LASF90: + .ascii "base\000" +.LASF64: + .ascii "op_flag\000" +.LASF276: + .ascii "index\000" +.LASF360: + .ascii "ram_part\000" +.LASF462: + .ascii "/home/lxh/uboot/u-boot\000" +.LASF285: + .ascii "net_ethaddr\000" +.LASF432: + .ascii "fdt_path_offset\000" +.LASF273: + .ascii "halt\000" +.LASF10: + .ascii "long long unsigned int\000" +.LASF205: + .ascii "IH_COMP_ZIMAGE\000" +.LASF416: + .ascii "otp_index\000" +.LASF346: + .ascii "part\000" +.LASF377: + .ascii "os_type\000" +.LASF67: + .ascii "vendor\000" +.LASF408: + .ascii "get_aligned_image_offset\000" +.LASF31: + .ascii "lbaint_t\000" +.LASF425: + .ascii "fit_hdr\000" +.LASF426: + .ascii "image_get_magic\000" +.LASF217: + .ascii "ih_type\000" +.LASF66: + .ascii "log2blksz\000" +.LASF46: + .ascii "IF_TYPE_SPINOR\000" +.LASF109: + .ascii "bi_ethspeed\000" +.LASF76: + .ascii "disk_partition\000" +.LASF438: + .ascii "part_get_info_by_name\000" +.LASF329: + .ascii "tag_bootdev\000" +.LASF442: + .ascii "fit_image_get_load\000" +.LASF89: + .ascii "lmb_property\000" +.LASF324: + .ascii "enable\000" +.LASF193: + .ascii "IH_TYPE_VYBRIDIMAGE\000" +.LASF141: + .ascii "IH_OS_LINUX\000" +.LASF355: + .ascii "core\000" +.LASF347: + .ascii "tag_soc_info\000" +.LASF201: + .ascii "IH_COMP_BZIP2\000" +.LASF151: + .ascii "IH_OS_PSOS\000" +.LASF155: + .ascii "IH_OS_ARTOS\000" +.LASF132: + .ascii "boot_cpuid_phys\000" +.LASF232: + .ascii "fit_uname_cfg\000" +.LASF427: + .ascii "__fswab32\000" +.LASF218: + .ascii "ih_comp\000" +.LASF111: + .ascii "bi_busfreq\000" +.LASF435: + .ascii "fit_get_desc\000" +.LASF444: + .ascii "fit_image_get_data_position\000" +.LASF266: + .ascii "s_addr\000" +.LASF226: + .ascii "arch\000" +.LASF406: + .ascii "data_size\000" +.LASF60: + .ascii "target\000" +.LASF124: + .ascii "fdt_header\000" +.LASF15: + .ascii "long int\000" +.LASF391: + .ascii "blob\000" +.LASF301: + .ascii "net_loop_state\000" +.LASF441: + .ascii "fit_image_get_comp\000" +.LASF396: + .ascii "offset\000" +.LASF101: + .ascii "bi_sramstart\000" +.LASF176: + .ascii "IH_TYPE_OMAPIMAGE\000" +.LASF27: + .ascii "_Bool\000" +.LASF49: + .ascii "IF_TYPE_COUNT\000" +.LASF310: + .ascii "__bss_start\000" +.LASF12: + .ascii "phys_size_t\000" +.LASF288: + .ascii "net_server_ip\000" +.LASF41: + .ascii "IF_TYPE_HOST\000" +.LASF356: + .ascii "serial\000" +.LASF411: + .ascii "outname\000" +.LASF223: + .ascii "image_len\000" +.LASF162: + .ascii "IH_OS_OP_TEE\000" +.LASF281: + .ascii "net_dns_server\000" +.LASF87: + .ascii "flash_info\000" +.LASF454: + .ascii "fit_image_get_data\000" +.LASF371: + .ascii "base_offset\000" +.LASF208: + .ascii "ih_magic\000" +.LASF399: + .ascii "load_ptr\000" +.LASF58: + .ascii "devnum\000" +.LASF224: + .ascii "load\000" +.LASF30: + .ascii "_binary_u_boot_bin_end\000" +.LASF196: + .ascii "IH_TYPE_PMMC\000" +.LASF463: + .ascii "load_next\000" +.LASF240: + .ascii "fit_uname_fdt\000" +.LASF379: + .ascii "spl_load_kernel_fit\000" +.LASF455: + .ascii "fdt_subnode_offset\000" +.LASF335: + .ascii "bank\000" +.LASF338: + .ascii "tag_tos_mem\000" +.LASF142: + .ascii "IH_OS_SVR4\000" +.LASF72: + .ascii "blk_desc\000" +.LASF177: + .ascii "IH_TYPE_AISIMAGE\000" +.LASF284: + .ascii "net_root_path\000" +.LASF73: + .ascii "block_drvr\000" +.LASF192: + .ascii "IH_TYPE_FPGA\000" +.LASF334: + .ascii "count\000" +.LASF428: + .ascii "fit_image_get_os\000" +.LASF393: + .ascii "spl_fit_load_blob\000" +.LASF59: + .ascii "part_type\000" +.LASF233: + .ascii "fit_hdr_os\000" +.LASF263: + .ascii "save_addr\000" +.LASF277: + .ascii "priv\000" +.LASF465: + .ascii "fdt_bootargs_append\000" +.LASF14: + .ascii "char\000" +.LASF448: + .ascii "fit_image_is_preload\000" +.LASF372: + .ascii "node\000" +.LASF61: + .ascii "hwpart\000" +.LASF182: + .ascii "IH_TYPE_ATMELIMAGE\000" +.LASF71: + .ascii "ide_bus_offset\000" +.LASF419: + .ascii "spl_get_current_slot\000" +.LASF150: + .ascii "IH_OS_VXWORKS\000" +.LASF81: + .ascii "sector_count\000" +.LASF321: + .ascii "filename\000" +.LASF222: + .ascii "image_start\000" +.LASF206: + .ascii "IH_COMP_COUNT\000" +.LASF86: + .ascii "flash_info_t\000" +.LASF69: + .ascii "revision\000" +.LASF368: + .ascii "sector_offs\000" +.LASF214: + .ascii "ih_dcrc\000" +.LASF287: + .ascii "net_ip\000" +.LASF336: + .ascii "data\000" +.LASF154: + .ascii "IH_OS_RTEMS\000" +.LASF9: + .ascii "long long int\000" +.LASF128: + .ascii "off_dt_strings\000" +.LASF367: + .ascii "sector\000" +.LASF48: + .ascii "IF_TYPE_MTD\000" +.LASF306: + .ascii "net_state\000" +.LASF437: + .ascii "strcmp\000" +.LASF234: + .ascii "fit_uname_os\000" +.LASF21: + .ascii "uint8_t\000" +.LASF7: + .ascii "__u32\000" +.LASF305: + .ascii "NETLOOP_FAIL\000" +.LASF183: + .ascii "IH_TYPE_SOCFPGAIMAGE\000" +.LASF400: + .ascii "overhead\000" +.LASF197: + .ascii "IH_TYPE_RKNAND\000" +.LASF185: + .ascii "IH_TYPE_LPC32XXIMAGE\000" +.LASF85: + .ascii "mtd_info\000" +.LASF80: + .ascii "disk_partition_t\000" +.LASF145: + .ascii "IH_OS_IRIX\000" +.LASF166: + .ascii "IH_TYPE_KERNEL\000" +.LASF135: + .ascii "working_fdt\000" +.LASF228: + .ascii "bootm_headers\000" +.LASF398: + .ascii "comp_addr\000" +.LASF195: + .ascii "IH_TYPE_FIRMWARE_IVT\000" +.LASF117: + .ascii "FIQ_STACK_START\000" +.LASF352: + .ascii "pagesize\000" +.LASF161: + .ascii "IH_OS_ARM_TRUSTED_FIRMWARE\000" +.LASF268: + .ascii "enetaddr\000" +.LASF259: + .ascii "monitor_flash_len\000" +.LASF54: + .ascii "SIG_TYPE_GUID\000" +.LASF237: + .ascii "fit_uname_rd\000" +.LASF431: + .ascii "printf\000" +.LASF84: + .ascii "udevice\000" +.LASF383: + .ascii "spl_load_simple_fit\000" +.LASF112: + .ascii "bi_arch_number\000" +.LASF160: + .ascii "IH_OS_OPENRTOS\000" +.LASF436: + .ascii "atags_get_tag\000" +.LASF70: + .ascii "bdev\000" +.LASF404: + .ascii "preload\000" +.LASF445: + .ascii "fit_image_get_data_offset\000" +.LASF126: + .ascii "totalsize\000" +.LASF103: + .ascii "bi_arm_freq\000" +.LASF340: + .ascii "drm_mem\000" +.LASF220: + .ascii "image_header_t\000" +.LASF98: + .ascii "bi_flashstart\000" +.LASF320: + .ascii "bl_len\000" +.LASF297: + .ascii "net_restart_wrap\000" +.LASF57: + .ascii "guid_sig\000" +.LASF137: + .ascii "IH_OS_OPENBSD\000" +.LASF294: + .ascii "net_null_ethaddr\000" +.LASF464: + .ascii "rk_meta_bootargs_append\000" +.LASF139: + .ascii "IH_OS_FREEBSD\000" +.LASF345: + .ascii "tag_ram_partition\000" +.LASF424: + .ascii "fit_get_name\000" +.LASF215: + .ascii "ih_os\000" +.LASF63: + .ascii "removable\000" +.LASF78: + .ascii "size\000" +.LASF143: + .ascii "IH_OS_ESIX\000" +.LASF199: + .ascii "IH_COMP_NONE\000" +.LASF349: + .ascii "param\000" +.LASF314: + .ascii "entry_point_os\000" +.LASF421: + .ascii "partition\000" +.LASF37: + .ascii "IF_TYPE_DOC\000" +.LASF362: + .ascii "pub_key\000" +.LASF458: + .ascii "fdt_next_subnode\000" +.LASF200: + .ascii "IH_COMP_GZIP\000" +.LASF190: + .ascii "IH_TYPE_ZYNQIMAGE\000" +.LASF433: + .ascii "fit_board_verify_required_sigs\000" +.LASF83: + .ascii "protect\000" +.LASF366: + .ascii "info\000" +.LASF1: + .ascii "long unsigned int\000" +.LASF171: + .ascii "IH_TYPE_FILESYSTEM\000" +.LASF207: + .ascii "image_header\000" +.LASF131: + .ascii "last_comp_version\000" +.LASF357: + .ascii "bootdev\000" +.LASF260: + .ascii "__dtb_dt_begin\000" +.LASF375: + .ascii "this_index\000" +.LASF351: + .ascii "tag_core\000" +.LASF180: + .ascii "IH_TYPE_MXSIMAGE\000" +.LASF203: + .ascii "IH_COMP_LZO\000" +.LASF252: + .ascii "cmdline_end\000" +.LASF278: + .ascii "eth_current\000" +.LASF47: + .ascii "IF_TYPE_RAMDISK\000" +.LASF127: + .ascii "off_dt_struct\000" +.LASF148: + .ascii "IH_OS_NCR\000" +.LASF173: + .ascii "IH_TYPE_KWBIMAGE\000" +.LASF280: + .ascii "net_netmask\000" +.LASF147: + .ascii "IH_OS_DELL\000" +.LASF95: + .ascii "bd_info\000" +.LASF251: + .ascii "cmdline_start\000" +.LASF256: + .ascii "images\000" +.LASF394: + .ascii "spl_fit_append_fdt\000" +.LASF88: + .ascii "long double\000" +.LASF229: + .ascii "legacy_hdr_os\000" +.LASF452: + .ascii "puts\000" +.LASF389: + .ascii "noffset\000" +.LASF18: + .ascii "size_t\000" +.LASF107: + .ascii "bi_ip_addr\000" +.LASF420: + .ascii "dev_desc\000" +.LASF110: + .ascii "bi_intfreq\000" +.LASF158: + .ascii "IH_OS_OSE\000" +.LASF461: + .ascii "common/spl/spl_fit_tb.c\000" +.LASF11: + .ascii "phys_addr_t\000" +.LASF332: + .ascii "sdupdate\000" +.LASF153: + .ascii "IH_OS_U_BOOT\000" +.LASF289: + .ascii "net_tx_packet\000" +.LASF249: + .ascii "initrd_start\000" +.LASF459: + .ascii "strchr\000" +.LASF330: + .ascii "devtype\000" +.LASF6: + .ascii "short int\000" +.LASF184: + .ascii "IH_TYPE_X86_SETUP\000" +.LASF213: + .ascii "ih_ep\000" +.LASF216: + .ascii "ih_arch\000" +.LASF32: + .ascii "IF_TYPE_UNKNOWN\000" +.LASF395: + .ascii "spl_load_fit_image\000" +.LASF328: + .ascii "hash\000" +.LASF29: + .ascii "_binary_u_boot_bin_start\000" +.LASF369: + .ascii "fit_header\000" +.LASF397: + .ascii "length\000" +.LASF36: + .ascii "IF_TYPE_USB\000" +.LASF140: + .ascii "IH_OS_4_4BSD\000" +.LASF282: + .ascii "net_nis_domain\000" +.LASF212: + .ascii "ih_load\000" +.LASF423: + .ascii "fit_config_verify\000" +.LASF304: + .ascii "NETLOOP_SUCCESS\000" +.LASF315: + .ascii "fdt_addr\000" +.LASF202: + .ascii "IH_COMP_LZMA\000" +.LASF409: + .ascii "spl_fit_get_image_node\000" +.LASF344: + .ascii "flag\000" +.LASF374: + .ascii "conf_noffset\000" +.LASF20: + .ascii "ulong\000" +.LASF210: + .ascii "ih_time\000" +.LASF100: + .ascii "bi_flashoffset\000" +.LASF165: + .ascii "IH_TYPE_STANDALONE\000" +.LASF269: + .ascii "iobase\000" +.LASF302: + .ascii "NETLOOP_CONTINUE\000" +.LASF198: + .ascii "IH_TYPE_COUNT\000" +.LASF342: + .ascii "tag_atf_mem\000" +.LASF290: + .ascii "net_rx_packets\000" +.LASF341: + .ascii "reserved1\000" +.LASF92: + .ascii "region\000" +.LASF247: + .ascii "ft_addr\000" +.LASF410: + .ascii "spl_fit_get_image_name\000" +.LASF418: + .ascii "spl_load_meta\000" +.LASF440: + .ascii "fdt_get_name\000" +.LASF322: + .ascii "read\000" +.LASF77: + .ascii "start\000" +.LASF243: + .ascii "fit_uname_setup\000" +.LASF28: + .ascii "image_base\000" +.LASF26: + .ascii "efi_guid_t\000" +.LASF364: + .ascii "pstore\000" +.LASF125: + .ascii "magic\000" +.LASF236: + .ascii "fit_hdr_rd\000" +.LASF239: + .ascii "fit_hdr_fdt\000" +.LASF17: + .ascii "uintptr_t\000" +.LASF386: + .ascii "sectors\000" +.LASF274: + .ascii "write_hwaddr\000" +.LASF390: + .ascii "spl_fit_record_loadable\000" +.LASF270: + .ascii "init\000" +.LASF113: + .ascii "bi_boot_params\000" +.LASF358: + .ascii "ddr_mem\000" +.LASF13: + .ascii "sizetype\000" +.LASF168: + .ascii "IH_TYPE_MULTI\000" +.LASF172: + .ascii "IH_TYPE_FLATDT\000" +.LASF189: + .ascii "IH_TYPE_RKSPI\000" +.LASF5: + .ascii "__u8\000" +.LASF118: + .ascii "_datarel_start_ofs\000" +.LASF96: + .ascii "bi_memstart\000" +.LASF209: + .ascii "ih_hcrc\000" +.LASF133: + .ascii "size_dt_strings\000" +.LASF179: + .ascii "IH_TYPE_PBLIMAGE\000" +.LASF227: + .ascii "image_info_t\000" +.LASF93: + .ascii "memory\000" +.LASF134: + .ascii "size_dt_struct\000" +.LASF246: + .ascii "rd_end\000" +.LASF265: + .ascii "in_addr\000" +.LASF250: + .ascii "initrd_end\000" +.LASF23: + .ascii "__be32\000" +.LASF122: + .ascii "IRQ_STACK_START_IN\000" +.LASF412: + .ascii "conf_node\000" +.LASF62: + .ascii "type\000" +.LASF380: + .ascii "images_noffset\000" +.LASF292: + .ascii "net_rx_packet_len\000" +.LASF0: + .ascii "unsigned char\000" +.LASF19: + .ascii "ushort\000" +.LASF39: + .ascii "IF_TYPE_SD\000" +.LASF194: + .ascii "IH_TYPE_TEE\000" +.LASF401: + .ascii "nr_sectors\000" +.LASF105: + .ascii "bi_ddr_freq\000" +.LASF402: + .ascii "image_comp\000" +.LASF244: + .ascii "fit_noffset_setup\000" +.LASF149: + .ascii "IH_OS_LYNXOS\000" +.LASF52: + .ascii "SIG_TYPE_NONE\000" +.LASF257: + .ascii "sha1_der_prefix\000" +.LASF325: + .ascii "addr\000" +.LASF136: + .ascii "IH_OS_INVALID\000" +.LASF254: + .ascii "state\000" +.LASF447: + .ascii "memalign_simple\000" +.LASF339: + .ascii "tee_mem\000" +.LASF293: + .ascii "net_bcast_ethaddr\000" +.LASF235: + .ascii "fit_noffset_os\000" +.LASF353: + .ascii "rootdev\000" +.LASF286: + .ascii "net_server_ethaddr\000" +.LASF451: + .ascii "board_fit_image_post_process\000" +.LASF343: + .ascii "tag_pub_key\000" +.LASF157: + .ascii "IH_OS_INTEGRITY\000" +.LASF175: + .ascii "IH_TYPE_UBLIMAGE\000" +.LASF267: + .ascii "eth_device\000" +.LASF415: + .ascii "fit_index\000" +.LASF272: + .ascii "recv\000" +.LASF75: + .ascii "select_hwpart\000" +.LASF466: + .ascii "fdt_bootargs_append_ab\000" +.LASF4: + .ascii "uchar\000" +.LASF99: + .ascii "bi_flashsize\000" +.LASF295: + .ascii "net_our_vlan\000" +.LASF2: + .ascii "short unsigned int\000" +.LASF34: + .ascii "IF_TYPE_SCSI\000" +.LASF104: + .ascii "bi_dsp_freq\000" +.LASF363: + .ascii "boot1p\000" +.LASF453: + .ascii "memcpy\000" +.LASF317: + .ascii "next_stage\000" +.LASF144: + .ascii "IH_OS_SOLARIS\000" +.LASF42: + .ascii "IF_TYPE_SYSTEMACE\000" +.LASF373: + .ascii "__func__\000" +.LASF94: + .ascii "reserved\000" +.LASF186: + .ascii "IH_TYPE_LOADABLE\000" +.LASF51: + .ascii "sig_type\000" +.LASF68: + .ascii "product\000" +.LASF119: + .ascii "_datarelrolocal_start_ofs\000" +.LASF33: + .ascii "IF_TYPE_IDE\000" +.LASF405: + .ascii "get_aligned_image_size\000" +.LASF253: + .ascii "verify\000" +.LASF370: + .ascii "desc\000" +.LASF388: + .ascii "spl_fit_image_get_os\000" +.LASF106: + .ascii "bi_bootflags\000" +.LASF327: + .ascii "m_mode\000" +.LASF114: + .ascii "bi_dram\000" +.LASF225: + .ascii "comp\000" +.LASF296: + .ascii "net_native_vlan\000" +.LASF159: + .ascii "IH_OS_PLAN9\000" +.LASF138: + .ascii "IH_OS_NETBSD\000" +.LASF376: + .ascii "min_index\000" +.LASF443: + .ascii "fit_image_get_comp_addr\000" +.LASF378: + .ascii "spl_internal_load_simple_fit\000" +.LASF348: + .ascii "tag_boot1p\000" +.LASF156: + .ascii "IH_OS_UNITY\000" +.LASF164: + .ascii "IH_TYPE_INVALID\000" +.LASF337: + .ascii "phy_addr\000" +.LASF422: + .ascii "mtd_part_parse\000" +.LASF429: + .ascii "fdt_getprop\000" +.LASF91: + .ascii "lmb_region\000" + .ident "GCC: (Linaro GCC 6.3-2017.05) 6.3.1 20170404" + .section .note.GNU-stack,"",%progbits diff --git a/u-boot/common/spl/spl_fit_tb_arm32.S b/u-boot/common/spl/spl_fit_tb_rv1126.S similarity index 100% rename from u-boot/common/spl/spl_fit_tb_arm32.S rename to u-boot/common/spl/spl_fit_tb_rv1126.S diff --git a/u-boot/common/stdio.c b/u-boot/common/stdio.c index fbf06e29f0..a61a05a147 100644 --- a/u-boot/common/stdio.c +++ b/u-boot/common/stdio.c @@ -368,16 +368,11 @@ int stdio_add_devices(void) */ #ifndef CONFIG_SYS_CONSOLE_IS_IN_ENV struct udevice *vdev; -# ifndef CONFIG_DM_KEYBOARD - int ret; -# endif - for (ret = uclass_first_device(UCLASS_VIDEO, &vdev); + for (uclass_first_device(UCLASS_VIDEO, &vdev); vdev; - ret = uclass_next_device(&vdev)) + uclass_next_device(&vdev)) ; - if (ret) - printf("%s: Video device failed (ret=%d)\n", __func__, ret); #endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */ #else # if defined(CONFIG_LCD) diff --git a/u-boot/common/write_keybox.c b/u-boot/common/write_keybox.c old mode 100755 new mode 100644 index 15f370fe09..bbb3775293 --- a/u-boot/common/write_keybox.c +++ b/u-boot/common/write_keybox.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #define BOOT_FROM_EMMC (1 << 1) #define WIDEVINE_TAG "KBOX" #define ATTESTATION_TAG "ATTE" +#define ID_ATTESTATION_TAG "IDAT" #define PLAYREADY30_TAG "SL30" TEEC_Result write_to_security_storage(uint8_t is_use_rpmb, @@ -224,6 +226,7 @@ uint32_t write_keybox_to_secure_storage(uint8_t *received_data, uint32_t len) { uint8_t *widevine_data; uint8_t *attestation_data; + uint8_t *id_attestation_data; uint8_t *playready_sl30_data; uint32_t key_size; uint32_t data_size; @@ -255,6 +258,8 @@ uint32_t write_keybox_to_secure_storage(uint8_t *received_data, uint32_t len) WIDEVINE_TAG, len); attestation_data = (uint8_t *)new_strstr((char *)received_data, ATTESTATION_TAG, len); + id_attestation_data = (uint8_t *)new_strstr((char *)received_data, + ID_ATTESTATION_TAG, len); playready_sl30_data = (uint8_t *)new_strstr((char *)received_data, PLAYREADY30_TAG, len); if (widevine_data) { @@ -293,6 +298,16 @@ uint32_t write_keybox_to_secure_storage(uint8_t *received_data, uint32_t len) rc = -EIO; printf("write attestation key to secure storage fail\n"); } + } else if (id_attestation_data) { + /* id attestation */ + ret = write_id_attestation_to_secure_storage(id_attestation_data, len); + if (ret == ATAP_RESULT_OK) { + rc = 0; + printf("write id attestation success!\n"); + } else { + rc = -EIO; + printf("write id attestation failed\n"); + } } else if (playready_sl30_data) { /* PlayReady SL3000 root key */ uint32_t ret; diff --git a/u-boot/configs/gki.config b/u-boot/configs/gki.config new file mode 100644 index 0000000000..03a7dfea4c --- /dev/null +++ b/u-boot/configs/gki.config @@ -0,0 +1 @@ +CONFIG_ANDROID_AB=y diff --git a/u-boot/configs/rk-amp.config b/u-boot/configs/rk-amp.config index b76e182dbc..ab248f8ad5 100644 --- a/u-boot/configs/rk-amp.config +++ b/u-boot/configs/rk-amp.config @@ -1,3 +1,2 @@ -# CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_AMP=y CONFIG_ROCKCHIP_AMP=y diff --git a/u-boot/configs/rk322x_defconfig b/u-boot/configs/rk322x_defconfig index 22621cde4a..82ea3feff6 100644 --- a/u-boot/configs/rk322x_defconfig +++ b/u-boot/configs/rk322x_defconfig @@ -86,6 +86,8 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PINCTRL=y +CONFIG_IO_DOMAIN=y +CONFIG_ROCKCHIP_IO_DOMAIN=y CONFIG_DM_PMIC=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y diff --git a/u-boot/configs/rk3308-ia.config b/u-boot/configs/rk3308-ia.config new file mode 100644 index 0000000000..a0a498c33b --- /dev/null +++ b/u-boot/configs/rk3308-ia.config @@ -0,0 +1,14 @@ +# CONFIG_CMD_ATAGS is not set +# CONFIG_CMD_DHCP is not set +# CONFIG_CMD_MMC is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_PING is not set +# CONFIG_DM_ETH is not set +# CONFIG_DM_MMC is not set +# CONFIG_FIT is not set +# CONFIG_LED is not set +# CONFIG_MMC is not set +# CONFIG_NET is not set +# CONFIG_PHYLIB is not set +# CONFIG_REGEX is not set +# CONFIG_RKNANDC_NAND is not set diff --git a/u-boot/configs/rk3308_defconfig b/u-boot/configs/rk3308_defconfig index 6150026c66..db34dd5bc1 100644 --- a/u-boot/configs/rk3308_defconfig +++ b/u-boot/configs/rk3308_defconfig @@ -81,6 +81,8 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PINCTRL=y CONFIG_DM_FUEL_GAUGE=y CONFIG_POWER_FG_RK816=y +CONFIG_IO_DOMAIN=y +CONFIG_ROCKCHIP_IO_DOMAIN=y CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set CONFIG_PMIC_RK8XX=y diff --git a/u-boot/configs/rk3328_defconfig b/u-boot/configs/rk3328_defconfig index 03de227eb2..45383565fe 100644 --- a/u-boot/configs/rk3328_defconfig +++ b/u-boot/configs/rk3328_defconfig @@ -5,7 +5,6 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.py" CONFIG_ROCKCHIP_RK3328=y -CONFIG_RKIMG_BOOTLOADER=y CONFIG_ROCKCHIP_VENDOR_PARTITION=y CONFIG_TPL_LIBCOMMON_SUPPORT=y CONFIG_TPL_LIBGENERIC_SUPPORT=y @@ -89,6 +88,8 @@ CONFIG_SF_DEFAULT_SPEED=20000000 CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_INNO_USB3=y CONFIG_PINCTRL=y +CONFIG_IO_DOMAIN=y +CONFIG_ROCKCHIP_IO_DOMAIN=y CONFIG_DM_PMIC=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y @@ -118,11 +119,11 @@ CONFIG_USB_DWC3=y CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y -CONFIG_USB_GADGET_DWC2_OTG=y -CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_GADGET_MANUFACTURER="Rockchip" CONFIG_USB_GADGET_VENDOR_NUM=0x2207 CONFIG_USB_GADGET_PRODUCT_NUM=0x330a +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_DM_VIDEO=y CONFIG_DISPLAY=y CONFIG_DRM_ROCKCHIP=y @@ -133,7 +134,6 @@ CONFIG_DRM_ROCKCHIP_TVE=y CONFIG_LCD=y # CONFIG_IRQ is not set CONFIG_USE_TINY_PRINTF=y -CONFIG_PANIC_HANG=y CONFIG_SPL_TINY_MEMSET=y CONFIG_TPL_TINY_MEMSET=y CONFIG_ERRNO_STR=y diff --git a/u-boot/configs/rk3528-usbplug.config b/u-boot/configs/rk3528-usbplug.config new file mode 100644 index 0000000000..758a68fc1c --- /dev/null +++ b/u-boot/configs/rk3528-usbplug.config @@ -0,0 +1,25 @@ +CONFIG_BASE_DEFCONFIG="rockchip-usbplug_defconfig" +# CONFIG_TARGET_EVB_RV1126 is not set +# CONFIG_ROCKCHIP_RV1126 is not set +CONFIG_DEBUG_UART_BASE=0xff9f0000 +CONFIG_DEFAULT_DEVICE_TREE="rk3528-evb" +CONFIG_ROCKCHIP_RK3528=y +CONFIG_TARGET_EVB_RK3528=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_ROCKCHIP_NEW_IDB=y +# CONFIG_CLK_SCMI is not set +# CONFIG_SCMI_FIRMWARE is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_ROCKCHIP is not set +CONFIG_ROCKCHIP_BOOT_MODE_REG=0xff370200 +CONFIG_ROCKCHIP_STIMER_BASE=0xff620000 +CONFIG_ROCKCHIP_IRAM_START_ADDR=0xfe480000 +# CONFIG_ROCKCHIP_SFC is not set +# CONFIG_MTD is not set +# CONFIG_MTD_BLK is not set +# CONFIG_MTD_DEVICE is not set +# CONFIG_SPI_FLASH is not set +CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y +CONFIG_DM_RESET=y diff --git a/u-boot/configs/rk3562-usbplug.config b/u-boot/configs/rk3562-usbplug.config new file mode 100644 index 0000000000..f019ef4117 --- /dev/null +++ b/u-boot/configs/rk3562-usbplug.config @@ -0,0 +1,25 @@ +CONFIG_BASE_DEFCONFIG="rockchip-usbplug_defconfig" +# CONFIG_TARGET_EVB_RV1126 is not set +# CONFIG_ROCKCHIP_RV1126 is not set +CONFIG_DEBUG_UART_BASE=0xff210000 +CONFIG_DEFAULT_DEVICE_TREE="rk3562-evb" +CONFIG_ROCKCHIP_RK3562=y +CONFIG_TARGET_EVB_RK3562=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_ROCKCHIP_NEW_IDB=y +# CONFIG_CLK_SCMI is not set +# CONFIG_SCMI_FIRMWARE is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_ROCKCHIP is not set +CONFIG_ROCKCHIP_BOOT_MODE_REG=0xff010220 +CONFIG_ROCKCHIP_STIMER_BASE=0xffa90020 +CONFIG_ROCKCHIP_IRAM_START_ADDR=0xfe480000 +# CONFIG_ROCKCHIP_SFC is not set +# CONFIG_MTD is not set +# CONFIG_MTD_BLK is not set +# CONFIG_MTD_DEVICE is not set +# CONFIG_SPI_FLASH is not set +CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y +CONFIG_DM_RESET=y diff --git a/u-boot/configs/rk3562_defconfig b/u-boot/configs/rk3562_defconfig index 229e37b634..cf6fb9ad9a 100644 --- a/u-boot/configs/rk3562_defconfig +++ b/u-boot/configs/rk3562_defconfig @@ -32,6 +32,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_ANDROID_BOOTLOADER=y CONFIG_ANDROID_AVB=y CONFIG_ANDROID_BOOT_IMAGE_HASH=y +CONFIG_BOARD_RNG_SEED=y CONFIG_SPL_BOARD_INIT=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set # CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set diff --git a/u-boot/configs/rk3568-pcie-ep_defconfig b/u-boot/configs/rk3568-pcie-ep_defconfig new file mode 100644 index 0000000000..fc22f81d67 --- /dev/null +++ b/u-boot/configs/rk3568-pcie-ep_defconfig @@ -0,0 +1,226 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_atf.sh" +CONFIG_ROCKCHIP_RK3568=y +CONFIG_ROCKCHIP_FIT_IMAGE=y +CONFIG_ROCKCHIP_VENDOR_PARTITION=y +CONFIG_ROCKCHIP_FIT_IMAGE_PACK=y +CONFIG_ROCKCHIP_NEW_IDB=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_EVB_RK3568=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="rk3568-evb" +CONFIG_DEBUG_UART=y +CONFIG_FIT=y +CONFIG_FIT_IMAGE_POST_PROCESS=y +CONFIG_FIT_HW_CRYPTO=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_FIT_HW_CRYPTO=y +# CONFIG_SPL_SYS_DCACHE_OFF is not set +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_ANDROID_BOOTLOADER=y +CONFIG_ANDROID_AVB=y +CONFIG_ANDROID_BOOT_IMAGE_HASH=y +CONFIG_BOARD_RNG_SEED=y +CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y +CONFIG_SPL_SHA256_SUPPORT=y +CONFIG_SPL_CRYPTO_SUPPORT=y +CONFIG_SPL_HASH_SUPPORT=y +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_PCIE_EP_SUPPORT=y +CONFIG_SPL_ATF=y +CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y +CONFIG_SPL_AB=y +CONFIG_FASTBOOT_BUF_ADDR=0xc00800 +CONFIG_FASTBOOT_BUF_SIZE=0x04000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_CMD_BOOTZ=y +CONFIG_CMD_DTIMG=y +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_LZMADEC is not set +# CONFIG_CMD_UNZIP is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_BOOT_ANDROID=y +CONFIG_CMD_BOOT_ROCKCHIP=y +CONFIG_CMD_MMC=y +CONFIG_CMD_MTD=y +CONFIG_CMD_NAND=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_TFTP_BOOTM=y +CONFIG_CMD_TFTP_FLASH=y +# CONFIG_CMD_MISC is not set +# CONFIG_CMD_CHARGE_DISPLAY is not set +CONFIG_CMD_MTD_BLK=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_SPL_DTB_MINIMUM=y +CONFIG_OF_LIVE=y +CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +# CONFIG_NET_TFTP_VARS is not set +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_CLK_SCMI=y +CONFIG_DM_CRYPTO=y +CONFIG_SPL_DM_CRYPTO=y +CONFIG_ROCKCHIP_CRYPTO_V2=y +CONFIG_SPL_ROCKCHIP_CRYPTO_V2=y +CONFIG_DM_RNG=y +CONFIG_RNG_ROCKCHIP=y +CONFIG_SCMI_FIRMWARE=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_ROCKCHIP_GPIO_V2=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_DM_KEY=y +CONFIG_RK8XX_PWRKEY=y +CONFIG_ADC_KEY=y +CONFIG_MISC=y +CONFIG_SPL_MISC=y +CONFIG_ROCKCHIP_OTP=y +CONFIG_SPL_ROCKCHIP_SECURE_OTP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_MTD=y +CONFIG_MTD_BLK=y +CONFIG_MTD_DEVICE=y +CONFIG_MTD_SPI_NAND=y +# CONFIG_SPI_NAND_TOSHIBA is not set +# CONFIG_SPI_NAND_BIWIN is not set +# CONFIG_SPI_NAND_ETRON is not set +# CONFIG_SPI_NAND_JSC is not set +# CONFIG_SPI_NAND_SILICONGO is not set +# CONFIG_SPI_NAND_UNIM is not set +# CONFIG_SPI_NAND_SKYHIGH is not set +# CONFIG_SPI_NAND_GSTO is not set +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_SPEED=20000000 +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_XMC=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_DM_ETH=y +CONFIG_DM_ETH_PHY=y +CONFIG_DWC_ETH_QOS=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y +CONFIG_PHY_ROCKCHIP_NANENG_EDP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_DM_FUEL_GAUGE=y +CONFIG_POWER_FG_RK817=y +CONFIG_IO_DOMAIN=y +CONFIG_ROCKCHIP_IO_DOMAIN=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_DM_CHARGE_DISPLAY=y +CONFIG_CHARGE_ANIMATION=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +CONFIG_DM_RAMDISK=y +CONFIG_RAMDISK_RO=y +CONFIG_DM_DMC=y +CONFIG_ROCKCHIP_DMC_FSP=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE=0 +CONFIG_DM_RESET=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_RESET_ROCKCHIP=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xFE660000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_ROCKCHIP_SFC=y +CONFIG_SYSRESET=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_GENERIC=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_GENERIC=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Rockchip" +CONFIG_USB_GADGET_VENDOR_NUM=0x2207 +CONFIG_USB_GADGET_PRODUCT_NUM=0x350a +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y +CONFIG_DRM_ROCKCHIP=y +CONFIG_DRM_ROCKCHIP_DW_HDMI=y +CONFIG_DRM_ROCKCHIP_INNO_MIPI_PHY=y +CONFIG_DRM_ROCKCHIP_INNO_VIDEO_COMBO_PHY=y +CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI=y +CONFIG_DRM_ROCKCHIP_ANALOGIX_DP=y +CONFIG_DRM_ROCKCHIP_LVDS=y +CONFIG_DRM_ROCKCHIP_RGB=y +CONFIG_ROCKCHIP_CUBIC_LUT_SIZE=9 +CONFIG_LCD=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_RSA=y +CONFIG_SPL_RSA=y +CONFIG_RSA_N_SIZE=0x200 +CONFIG_RSA_E_SIZE=0x10 +CONFIG_RSA_C_SIZE=0x20 +CONFIG_XBC=y +CONFIG_SHA512=y +CONFIG_LZ4=y +CONFIG_LZMA=y +CONFIG_SPL_GZIP=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set +CONFIG_AVB_LIBAVB=y +CONFIG_AVB_LIBAVB_AB=y +CONFIG_AVB_LIBAVB_ATX=y +CONFIG_AVB_LIBAVB_USER=y +CONFIG_RK_AVB_LIBAVB_USER=y +CONFIG_OPTEE_CLIENT=y +CONFIG_OPTEE_V2=y +CONFIG_OPTEE_ALWAYS_USE_SECURITY_PARTITION=y diff --git a/u-boot/configs/rk3568-usbplug.config b/u-boot/configs/rk3568-usbplug.config index 3700d08844..01542bf95f 100644 --- a/u-boot/configs/rk3568-usbplug.config +++ b/u-boot/configs/rk3568-usbplug.config @@ -9,3 +9,17 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_ROCKCHIP=y CONFIG_ROCKCHIP_NEW_IDB=y +# CONFIG_CLK_SCMI is not set +# CONFIG_SCMI_FIRMWARE is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_ROCKCHIP is not set +CONFIG_ROCKCHIP_BOOT_MODE_REG=0xfdc20200 +CONFIG_ROCKCHIP_STIMER_BASE=0xfdd1c020 +CONFIG_ROCKCHIP_IRAM_START_ADDR=0xfdcc0000 +# CONFIG_ROCKCHIP_SFC is not set +# CONFIG_MTD is not set +# CONFIG_MTD_BLK is not set +# CONFIG_MTD_DEVICE is not set +# CONFIG_SPI_FLASH is not set +CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y +CONFIG_DM_RESET=y diff --git a/u-boot/configs/rk3568_defconfig b/u-boot/configs/rk3568_defconfig index 10e39385a5..acd1fb1816 100644 --- a/u-boot/configs/rk3568_defconfig +++ b/u-boot/configs/rk3568_defconfig @@ -20,6 +20,7 @@ CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="rk3568-evb" CONFIG_DEBUG_UART=y +CONFIG_IMAGE_GZIP=y CONFIG_FIT=y CONFIG_FIT_IMAGE_POST_PROCESS=y CONFIG_FIT_HW_CRYPTO=y @@ -33,6 +34,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_ANDROID_BOOTLOADER=y CONFIG_ANDROID_AVB=y CONFIG_ANDROID_BOOT_IMAGE_HASH=y +CONFIG_BOARD_RNG_SEED=y CONFIG_SPL_BOARD_INIT=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set # CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set @@ -166,7 +168,7 @@ CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE=0 CONFIG_DM_RESET=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_RESET_ROCKCHIP=y -CONFIG_BAUDRATE=115200 +CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_BASE=0xFE660000 CONFIG_DEBUG_UART_CLOCK=24000000 CONFIG_DEBUG_UART_SHIFT=2 diff --git a/u-boot/configs/rk3583.config b/u-boot/configs/rk3583.config new file mode 100644 index 0000000000..9a9b6cfa13 --- /dev/null +++ b/u-boot/configs/rk3583.config @@ -0,0 +1,2 @@ +CONFIG_BASE_DEFCONFIG="rk3588_defconfig" +CONFIG_LOADER_INI="RK3583MINIALL.ini" diff --git a/u-boot/configs/rk3588-ab-car.config b/u-boot/configs/rk3588-ab-car.config new file mode 100644 index 0000000000..815d6eec69 --- /dev/null +++ b/u-boot/configs/rk3588-ab-car.config @@ -0,0 +1,18 @@ +CONFIG_ANDROID_AB=y +CONFIG_BASE_DEFCONFIG="rk3588_defconfig" +# CONFIG_CMD_ANDROID_AB_SELECT is not set +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789=y +CONFIG_SERDES_DISPLAY_CHIP_MAXIM=y +CONFIG_SERDES_DISPLAY_CHIP_NOVO_NCA9539=y +CONFIG_SERDES_DISPLAY_CHIP_NOVO=y +CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111=y +CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121=y +CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP=y +CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82=y +CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82=y +CONFIG_SERDES_DISPLAY_CHIP_ROHM=y +CONFIG_SERDES_DISPLAY=y diff --git a/u-boot/configs/rk3588-qnx_defconfig b/u-boot/configs/rk3588-qnx_defconfig index 0c42ff1de6..26300813a4 100644 --- a/u-boot/configs/rk3588-qnx_defconfig +++ b/u-boot/configs/rk3588-qnx_defconfig @@ -139,7 +139,7 @@ CONFIG_REGULATOR_PWM=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_REGULATOR_RK860X=y -CONFIG_REGULATOR_RK806=y +CONFIG_REGULATOR_RK8XX=y CONFIG_CHARGER_BQ25700=y CONFIG_CHARGER_BQ25890=y CONFIG_CHARGER_SC8551=y diff --git a/u-boot/configs/rk3588-usbplug.config b/u-boot/configs/rk3588-usbplug.config new file mode 100644 index 0000000000..ad5bfa97d6 --- /dev/null +++ b/u-boot/configs/rk3588-usbplug.config @@ -0,0 +1,26 @@ +CONFIG_BASE_DEFCONFIG="rockchip-usbplug_defconfig" +# CONFIG_TARGET_EVB_RV1126 is not set +# CONFIG_ROCKCHIP_RV1126 is not set +CONFIG_DEBUG_UART_BASE=0xFEB50000 +CONFIG_DEFAULT_DEVICE_TREE="rk3588-evb" +CONFIG_ROCKCHIP_RK3588=y +CONFIG_TARGET_EVB_RK3588=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_ROCKCHIP=y +CONFIG_ROCKCHIP_NEW_IDB=y +# CONFIG_CLK_SCMI is not set +# CONFIG_SCMI_FIRMWARE is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_DW_ROCKCHIP is not set +CONFIG_ROCKCHIP_BOOT_MODE_REG=0xfd588080 +CONFIG_ROCKCHIP_STIMER_BASE=0xfd8c8000 +CONFIG_ROCKCHIP_IRAM_START_ADDR=0xff000000 +# CONFIG_ROCKCHIP_SFC is not set +# CONFIG_MTD is not set +# CONFIG_MTD_BLK is not set +# CONFIG_MTD_DEVICE is not set +# CONFIG_SPI_FLASH is not set +CONFIG_PHY_ROCKCHIP_USBDP=y +CONFIG_DM_RESET=y +CONFIG_OF_LIVE=y diff --git a/u-boot/configs/rk3588_defconfig b/u-boot/configs/rk3588_defconfig index a1425da15e..b5a8234a71 100644 --- a/u-boot/configs/rk3588_defconfig +++ b/u-boot/configs/rk3588_defconfig @@ -13,6 +13,7 @@ CONFIG_USING_KERNEL_DTB_V2=y CONFIG_ROCKCHIP_FIT_IMAGE_PACK=y CONFIG_ROCKCHIP_NEW_IDB=y CONFIG_PSTORE=y +CONFIG_ROCKCHIP_MINIDUMP=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_DRIVERS_MISC_SUPPORT=y CONFIG_TARGET_EVB_RK3588=y @@ -21,6 +22,7 @@ CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y CONFIG_DEFAULT_DEVICE_TREE="rk3588-evb" CONFIG_DEBUG_UART=y +CONFIG_IMAGE_GZIP=y CONFIG_FIT=y CONFIG_FIT_IMAGE_POST_PROCESS=y CONFIG_FIT_HW_CRYPTO=y @@ -34,13 +36,14 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_ANDROID_BOOTLOADER=y CONFIG_ANDROID_AVB=y CONFIG_ANDROID_BOOT_IMAGE_HASH=y +CONFIG_BOARD_RNG_SEED=y CONFIG_SPL_BOARD_INIT=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set # CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set CONFIG_SPL_SEPARATE_BSS=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x1 -CONFIG_SPL_MMC_WRITE=y +CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_ATF=y CONFIG_SPL_AB=y @@ -58,6 +61,7 @@ CONFIG_CMD_DTIMG=y # CONFIG_CMD_UNZIP is not set # CONFIG_CMD_FLASH is not set # CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y # CONFIG_CMD_LOADB is not set # CONFIG_CMD_LOADS is not set @@ -104,6 +108,7 @@ CONFIG_SPL_SCMI_FIRMWARE=y CONFIG_GPIO_HOG=y CONFIG_ROCKCHIP_GPIO=y CONFIG_ROCKCHIP_GPIO_V2=y +CONFIG_NCA9539_GPIO=y CONFIG_SYS_I2C_ROCKCHIP=y CONFIG_I2C_MUX=y CONFIG_DM_KEY=y @@ -160,7 +165,7 @@ CONFIG_REGULATOR_PWM=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_REGULATOR_RK860X=y -CONFIG_REGULATOR_RK806=y +CONFIG_REGULATOR_RK8XX=y CONFIG_CHARGER_BQ25700=y CONFIG_CHARGER_BQ25890=y CONFIG_CHARGER_SC8551=y @@ -176,7 +181,7 @@ CONFIG_RAMDISK_RO=y CONFIG_DM_RESET=y CONFIG_SPL_DM_RESET=y CONFIG_SPL_RESET_ROCKCHIP=y -CONFIG_BAUDRATE=115200 +CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_BASE=0xFEB50000 CONFIG_DEBUG_UART_CLOCK=24000000 CONFIG_DEBUG_UART_SHIFT=2 @@ -202,11 +207,6 @@ CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_DM_VIDEO=y CONFIG_DISPLAY=y CONFIG_DRM_ROCKCHIP=y -CONFIG_DRM_MAXIM_MAX96745=y -CONFIG_DRM_MAXIM_MAX96755F=y -CONFIG_DRM_PANEL_ROHM_BU18RL82=y -CONFIG_DRM_PANEL_MAXIM_MAX96752F=y -CONFIG_DRM_ROHM_BU18XL82=y CONFIG_DRM_ROCKCHIP_DW_HDMI_QP=y CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI2=y CONFIG_DRM_ROCKCHIP_DW_DP=y diff --git a/u-boot/configs/rv1106-spi-nand-tb-nofastae_defconfig b/u-boot/configs/rv1106-spi-nand-tb-nofastae_defconfig new file mode 100644 index 0000000000..c70801249b --- /dev/null +++ b/u-boot/configs/rv1106-spi-nand-tb-nofastae_defconfig @@ -0,0 +1,121 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_optee.sh" +CONFIG_ROCKCHIP_RV1106=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_ROCKCHIP_FIT_IMAGE=y +CONFIG_USING_KERNEL_DTB_V2=y +CONFIG_ROCKCHIP_FIT_IMAGE_PACK=y +# CONFIG_ROCKCHIP_SET_SN is not set +# CONFIG_ROCKCHIP_SET_ETHADDR is not set +CONFIG_LOADER_INI="RV1106MINIALL_SPI_NOR_TB_NOMCU.ini" +CONFIG_TRUST_INI="RV1106TOS_TB.ini" +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_EVB_RV1106=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="rv1106-evb" +CONFIG_DEBUG_UART=y +# CONFIG_DISTRO_DEFAULTS is not set +CONFIG_FIT=y +CONFIG_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_FIT_HW_CRYPTO=y +# CONFIG_SPL_SYS_DCACHE_OFF is not set +CONFIG_SPL_FIT_IMAGE_KB=512 +CONFIG_SPL_FIT_IMAGE_MULTIPLE=1 +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_SKIP_RELOCATE_UBOOT is not set +CONFIG_SPL_ADC_SUPPORT=y +CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_KERNEL_BOOT=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SOURCE is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +# CONFIG_CMD_MISC is not set +CONFIG_CMD_MTD_BLK=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_SPL_DTB_MINIMUM=y +CONFIG_OF_LIVE=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_OF_U_BOOT_REMOVE_PROPS="interrupt-parent" +CONFIG_ENVF=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +# CONFIG_SARADC_ROCKCHIP is not set +CONFIG_SARADC_ROCKCHIP_V2=y +CONFIG_SPL_BLK_READ_PREPARE=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_SPL_DM_CRYPTO=y +CONFIG_SPL_ROCKCHIP_CRYPTO_V2=y +CONFIG_ROCKCHIP_GPIO=y +# CONFIG_DM_I2C is not set +CONFIG_SPL_INPUT=y +CONFIG_DM_KEY=y +CONFIG_ADC_KEY=y +CONFIG_SPL_ADC_KEY=y +CONFIG_SPL_MISC=y +CONFIG_SPL_MISC_DECOMPRESS=y +CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS=y +# CONFIG_MMC is not set +# CONFIG_DM_MMC is not set +CONFIG_MTD=y +CONFIG_MTD_BLK=y +CONFIG_MTD_DEVICE=y +CONFIG_MTD_SPI_NAND=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x1 +CONFIG_SF_DEFAULT_SPEED=50000000 +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_XMC=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PINCTRL=y +# CONFIG_DM_REGULATOR is not set +# CONFIG_DM_PWM is not set +CONFIG_RAM=y +CONFIG_TPL_RAM=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_DM_RESET=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_RESET_ROCKCHIP=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xff4c0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_ROCKCHIP_SFC=y +CONFIG_SYSRESET=y +# CONFIG_SYSRESET_SYSCON_REBOOT is not set +CONFIG_USE_TINY_PRINTF=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set diff --git a/u-boot/configs/rv1106-spi-nand-tb_defconfig b/u-boot/configs/rv1106-spi-nand-tb_defconfig new file mode 100644 index 0000000000..066a58f450 --- /dev/null +++ b/u-boot/configs/rv1106-spi-nand-tb_defconfig @@ -0,0 +1,122 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_optee.sh" +CONFIG_ROCKCHIP_RV1106=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_ROCKCHIP_FIT_IMAGE=y +CONFIG_USING_KERNEL_DTB_V2=y +CONFIG_ROCKCHIP_META=y +CONFIG_ROCKCHIP_FIT_IMAGE_PACK=y +# CONFIG_ROCKCHIP_SET_SN is not set +# CONFIG_ROCKCHIP_SET_ETHADDR is not set +CONFIG_LOADER_INI="RV1106MINIALL_SPI_NAND_TB.ini" +CONFIG_TRUST_INI="RV1106TOS_TB.ini" +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_EVB_RV1106=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="rv1106-evb" +CONFIG_DEBUG_UART=y +# CONFIG_DISTRO_DEFAULTS is not set +CONFIG_FIT=y +CONFIG_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_FIT_HW_CRYPTO=y +# CONFIG_SPL_SYS_DCACHE_OFF is not set +CONFIG_SPL_FIT_IMAGE_KB=512 +CONFIG_SPL_FIT_IMAGE_MULTIPLE=1 +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_SKIP_RELOCATE_UBOOT is not set +CONFIG_SPL_ADC_SUPPORT=y +CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_KERNEL_BOOT=y +CONFIG_HUSH_PARSER=y +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SOURCE is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +# CONFIG_CMD_MISC is not set +CONFIG_CMD_MTD_BLK=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_SPL_DTB_MINIMUM=y +CONFIG_OF_LIVE=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_OF_U_BOOT_REMOVE_PROPS="interrupt-parent" +CONFIG_ENVF=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +# CONFIG_SARADC_ROCKCHIP is not set +CONFIG_SARADC_ROCKCHIP_V2=y +CONFIG_SPL_BLK_READ_PREPARE=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_SPL_DM_CRYPTO=y +CONFIG_SPL_ROCKCHIP_CRYPTO_V2=y +CONFIG_ROCKCHIP_GPIO=y +# CONFIG_DM_I2C is not set +CONFIG_SPL_INPUT=y +CONFIG_DM_KEY=y +CONFIG_ADC_KEY=y +CONFIG_SPL_ADC_KEY=y +CONFIG_SPL_MISC=y +CONFIG_SPL_MISC_DECOMPRESS=y +CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS=y +# CONFIG_MMC is not set +# CONFIG_DM_MMC is not set +CONFIG_MTD=y +CONFIG_MTD_BLK=y +CONFIG_MTD_DEVICE=y +CONFIG_MTD_SPI_NAND=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_MODE=0x1 +CONFIG_SF_DEFAULT_SPEED=50000000 +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_XMC=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PINCTRL=y +# CONFIG_DM_REGULATOR is not set +# CONFIG_DM_PWM is not set +CONFIG_RAM=y +CONFIG_TPL_RAM=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_DM_RESET=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_RESET_ROCKCHIP=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xff4c0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_ROCKCHIP_SFC=y +CONFIG_SYSRESET=y +# CONFIG_SYSRESET_SYSCON_REBOOT is not set +CONFIG_USE_TINY_PRINTF=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set diff --git a/u-boot/configs/rv1106-usbplug.config b/u-boot/configs/rv1106-usbplug.config new file mode 100755 index 0000000000..3831814216 --- /dev/null +++ b/u-boot/configs/rv1106-usbplug.config @@ -0,0 +1,48 @@ +CONFIG_BASE_DEFCONFIG="rockchip-usbplug_defconfig" +CONFIG_BAUDRATE=115200 +CONFIG_CMD_PINMUX=y +# CONFIG_CMD_REGULATOR is not set +CONFIG_CMD_USB=y +CONFIG_DEBUG_UART_BASE=0xff4c0000 +CONFIG_DEFAULT_DEVICE_TREE="rv1106-evb" +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_REGULATOR=y +# CONFIG_NOP_PHY is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY=y +# CONFIG_PINCONF is not set +CONFIG_PINCONF_RECURSIVE=y +# CONFIG_PINCTRL_AT91 is not set +# CONFIG_PINCTRL_AT91PIO4 is not set +CONFIG_PINCTRL_FULL=y +CONFIG_PINCTRL_GENERIC=y +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PINCTRL_STM32 is not set +CONFIG_PINCTRL=y +CONFIG_PINMUX=y +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_RK860X is not set +CONFIG_ROCKCHIP_BOOT_MODE_REG=0xff020200 +CONFIG_ROCKCHIP_GPIO_V2=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_ROCKCHIP_IRAM_START_ADDR=0xff6c0000 +CONFIG_ROCKCHIP_NEW_IDB=y +CONFIG_ROCKCHIP_RV1106=y +# CONFIG_ROCKCHIP_RV1126 is not set +CONFIG_ROCKCHIP_STIMER_BASE=0xff590020 +CONFIG_ROCKCHIP_VENDOR_PARTITION=y +# CONFIG_SPL_DM_REGULATOR_FIXED is not set +# CONFIG_SPL_DM_REGULATOR is not set +CONFIG_SYS_BOARD="evb_rv1106" +CONFIG_SYS_CONFIG_NAME="evb_rv1106" +CONFIG_TARGET_EVB_RV1106=y +CONFIG_USB_GADGET_PRODUCT_NUM=0x110c +CONFIG_USB_HOST=y +CONFIG_USB_STORAGE=y +# CONFIG_USB_XHCI_DWC3 is not set +# CONFIG_USB_XHCI_DWC3_OF_SIMPLE is not set +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_PCI is not set diff --git a/u-boot/configs/rv1106_defconfig b/u-boot/configs/rv1106_defconfig index 5dd1bb39e9..f56f5bc565 100644 --- a/u-boot/configs/rv1106_defconfig +++ b/u-boot/configs/rv1106_defconfig @@ -42,6 +42,7 @@ CONFIG_SPL_BOARD_INIT=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_AB=y CONFIG_HUSH_PARSER=y # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set @@ -108,14 +109,6 @@ CONFIG_MTD=y CONFIG_MTD_BLK=y CONFIG_MTD_DEVICE=y CONFIG_MTD_SPI_NAND=y -CONFIG_SPI_FLASH=y -CONFIG_SF_DEFAULT_MODE=0x3 -CONFIG_SPI_FLASH_GIGADEVICE=y -CONFIG_SPI_FLASH_MACRONIX=y -CONFIG_SPI_FLASH_WINBOND=y -CONFIG_SPI_FLASH_XMC=y -CONFIG_SPI_FLASH_XTX=y -CONFIG_SPI_FLASH_MTD=y CONFIG_PHY_RK630=y CONFIG_DM_ETH=y CONFIG_DM_ETH_PHY=y diff --git a/u-boot/configs/rv1126-emmc-tb-nofastae.config b/u-boot/configs/rv1126-emmc-tb-nofastae.config new file mode 100644 index 0000000000..20a6a3900f --- /dev/null +++ b/u-boot/configs/rv1126-emmc-tb-nofastae.config @@ -0,0 +1,35 @@ +CONFIG_BASE_DEFCONFIG="rv1126_defconfig" +# CONFIG_CMD_MTD_BLK is not set +# CONFIG_CMD_NAND is not set +# CONFIG_CMD_SF is not set +# CONFIG_CMD_SPI is not set +CONFIG_LOADER_INI="RV1126MINIALL_EMMC_TB.ini" +CONFIG_MMC_USE_PRE_CONFIG=y +# CONFIG_MTD_DEVICE is not set +# CONFIG_MTD is not set +# CONFIG_MTD_NAND_BBT_USING_FLASH is not set +# CONFIG_NAND is not set +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +# CONFIG_ROCKCHIP_SFC is not set +# CONFIG_SPI_FLASH is not set +# CONFIG_SPI_MEM is not set +# CONFIG_SPL_AB is not set +CONFIG_SPL_ADC_KEY=y +CONFIG_SPL_ADC_SUPPORT=y +CONFIG_SPL_BLK_READ_PREPARE=y +# CONFIG_SPL_CROS_EC_KEYB is not set +CONFIG_SPL_DM_FUEL_GAUGE=y +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_INPUT=y +CONFIG_SPL_KERNEL_BOOT=y +# CONFIG_SPL_MTD_SUPPORT is not set +# CONFIG_SPL_NAND_SUPPORT is not set +# CONFIG_SPL_PINCTRL is not set +# CONFIG_SPL_POWER_FG_CW201X is not set +CONFIG_SPL_POWER_FG_RK817=y +# CONFIG_SPL_POWER_FG_RK818 is not set +CONFIG_SPL_POWER_LOW_VOLTAGE_THRESHOLD=3400 +# CONFIG_SPL_SPI_FLASH_SUPPORT is not set +# CONFIG_SPL_SPI_SUPPORT is not set +CONFIG_SPL_SYS_MALLOC_F_LEN=0x100000 +CONFIG_TRUST_INI="RV1126TOS_TB_NOMCU.ini" diff --git a/u-boot/configs/rv1126-spl-slc-nand_defconfig b/u-boot/configs/rv1126-spl-slc-nand_defconfig new file mode 100644 index 0000000000..802cba3b86 --- /dev/null +++ b/u-boot/configs/rv1126-spl-slc-nand_defconfig @@ -0,0 +1,184 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x80000 +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-rockchip/make_fit_optee.sh" +CONFIG_ROCKCHIP_RV1126=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +# CONFIG_SPL_MMC_SUPPORT is not set +CONFIG_ROCKCHIP_FIT_IMAGE=y +CONFIG_ROCKCHIP_UIMAGE=y +CONFIG_ROCKCHIP_FIT_IMAGE_PACK=y +CONFIG_ROCKCHIP_UART_MUX_SEL_M=2 +CONFIG_ROCKCHIP_SFC_IOMUX=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_EVB_RV1126=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_SPL_NAND_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DEFAULT_DEVICE_TREE="rv1126-evb" +CONFIG_DEBUG_UART=y +CONFIG_FIT=y +CONFIG_FIT_IMAGE_POST_PROCESS=y +CONFIG_FIT_HW_CRYPTO=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y +CONFIG_SPL_FIT_HW_CRYPTO=y +# CONFIG_SPL_SYS_DCACHE_OFF is not set +CONFIG_BOOTDELAY=0 +# CONFIG_CONSOLE_MUX is not set +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_ANDROID_BOOTLOADER=y +# CONFIG_ANDROID_WRITE_KEYBOX is not set +# CONFIG_ANDROID_KEYMASTER_CA is not set +CONFIG_ANDROID_BOOT_IMAGE_HASH=y +CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set +# CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set +CONFIG_SPL_SHA256_SUPPORT=y +CONFIG_SPL_CRYPTO_SUPPORT=y +CONFIG_SPL_HASH_SUPPORT=y +CONFIG_SPL_MTD_SUPPORT=y +CONFIG_SPL_MTD_WRITE=y +CONFIG_SPL_OPTEE=y +CONFIG_FASTBOOT_BUF_ADDR=0x800800 +CONFIG_FASTBOOT_BUF_SIZE=0x04000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_BOOT_ANDROID=y +CONFIG_CMD_BOOT_ROCKCHIP=y +CONFIG_CMD_MMC=y +CONFIG_CMD_MTD=y +CONFIG_CMD_NAND=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_TFTP_BOOTM=y +CONFIG_CMD_TFTP_FLASH=y +# CONFIG_CMD_NFS is not set +# CONFIG_CMD_MISC is not set +# CONFIG_CMD_CHARGE_DISPLAY is not set +CONFIG_CMD_MTD_BLK=y +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_SPL_DTB_MINIMUM=y +CONFIG_OF_LIVE=y +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_OF_U_BOOT_REMOVE_PROPS="interrupt-parent" +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_DM_CRYPTO=y +CONFIG_SPL_DM_CRYPTO=y +CONFIG_ROCKCHIP_CRYPTO_V2=y +CONFIG_SPL_ROCKCHIP_CRYPTO_V2=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_DM_KEY=y +CONFIG_RK8XX_PWRKEY=y +CONFIG_ADC_KEY=y +CONFIG_MISC=y +CONFIG_SPL_MISC=y +CONFIG_MISC_DECOMPRESS=y +CONFIG_SPL_MISC_DECOMPRESS=y +CONFIG_ROCKCHIP_OTP=y +CONFIG_ROCKCHIP_HW_DECOMPRESS=y +CONFIG_SPL_ROCKCHIP_HW_DECOMPRESS=y +CONFIG_SPL_ROCKCHIP_SECURE_OTP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MTD=y +CONFIG_MTD_BLK=y +CONFIG_MTD_DEVICE=y +CONFIG_MTD_NAND_BBT_USING_FLASH=y +CONFIG_NAND=y +CONFIG_NAND_ROCKCHIP=y +CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y +CONFIG_SYS_NAND_U_BOOT_OFFS=0x4000 +CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND=0x10000 +CONFIG_SF_DEFAULT_MODE=0x1 +CONFIG_SF_DEFAULT_SPEED=50000000 +CONFIG_DM_ETH=y +CONFIG_DM_ETH_PHY=y +CONFIG_DWC_ETH_QOS=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PHY_ROCKCHIP_NANENG_USB2=y +CONFIG_PINCTRL=y +CONFIG_DM_FUEL_GAUGE=y +CONFIG_POWER_FG_RK817=y +CONFIG_IO_DOMAIN=y +CONFIG_ROCKCHIP_IO_DOMAIN=y +CONFIG_DM_PMIC=y +# CONFIG_SPL_PMIC_CHILDREN is not set +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_DM_CHARGE_DISPLAY=y +CONFIG_CHARGE_ANIMATION=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_DM_RESET=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_RESET_ROCKCHIP=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_BASE=0xff570000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SPI_MEM=y +CONFIG_ROCKCHIP_SFC=y +CONFIG_SYSRESET=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_STORAGE=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Rockchip" +CONFIG_USB_GADGET_VENDOR_NUM=0x2207 +CONFIG_USB_GADGET_PRODUCT_NUM=0x110b +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y +CONFIG_DRM_ROCKCHIP=y +CONFIG_DRM_ROCKCHIP_INNO_MIPI_PHY=y +CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI=y +CONFIG_DRM_ROCKCHIP_RGB=y +CONFIG_USE_TINY_PRINTF=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_RSA=y +CONFIG_SPL_RSA=y +CONFIG_RSA_N_SIZE=0x100 +CONFIG_RSA_E_SIZE=0x100 +CONFIG_RSA_C_SIZE=0x14 +CONFIG_SHA512=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set +CONFIG_OPTEE_CLIENT=y +CONFIG_OPTEE_V2=y diff --git a/u-boot/disk/part_env.c b/u-boot/disk/part_env.c index 53c8b39191..8570ce7323 100644 --- a/u-boot/disk/part_env.c +++ b/u-boot/disk/part_env.c @@ -157,7 +157,7 @@ static int part_get_info_env(struct blk_desc *dev_desc, int idx, { struct env_part *p = NULL; struct list_head *node; - int part_num = 1; + int part_num = 0; int ret = 0; if (idx < 1) { @@ -175,9 +175,9 @@ static int part_get_info_env(struct blk_desc *dev_desc, int idx, list_for_each(node, &parts_head) { p = list_entry(node, struct env_part, node); + part_num++; if (idx == part_num) break; - part_num++; } if (part_num < idx) { diff --git a/u-boot/disk/part_rkparm.c b/u-boot/disk/part_rkparm.c index 0d0890a125..302e7faa26 100644 --- a/u-boot/disk/part_rkparm.c +++ b/u-boot/disk/part_rkparm.c @@ -176,7 +176,7 @@ static int part_get_info_rkparm(struct blk_desc *dev_desc, int idx, { struct list_head *node; struct rkparm_part *p = NULL; - int part_num = 1; + int part_num = 0; int ret = 0; if (idx < 1) { @@ -195,9 +195,9 @@ static int part_get_info_rkparm(struct blk_desc *dev_desc, int idx, list_for_each(node, &parts_head) { p = list_entry(node, struct rkparm_part, node); + part_num ++; if (idx == part_num) break; - part_num ++; } if (part_num < idx) { diff --git a/u-boot/disk/part_rkram.c b/u-boot/disk/part_rkram.c index 7398b5e64f..c553b425e0 100644 --- a/u-boot/disk/part_rkram.c +++ b/u-boot/disk/part_rkram.c @@ -99,7 +99,7 @@ static int part_get_info_rkram_part(struct blk_desc *dev_desc, int idx, { struct rkram_part *p = NULL; struct list_head *node; - int part_num = 1; + int part_num = 0; if (idx < 1) { printf("Invalid partition no.%d\n", idx); @@ -111,9 +111,9 @@ static int part_get_info_rkram_part(struct blk_desc *dev_desc, int idx, list_for_each(node, &parts_head) { p = list_entry(node, struct rkram_part, node); + part_num++; if (idx == part_num) break; - part_num++; } if (part_num < idx) { diff --git a/u-boot/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt b/u-boot/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt index b73c96d24f..603796f169 100644 --- a/u-boot/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt +++ b/u-boot/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt @@ -119,7 +119,8 @@ For example: The contents of each of those pin configuration child nodes is defined entirely by the binding for the individual pin controller device. There -exists no common standard for this content. +exists no common standard for this content. The pinctrl framework only +provides generic helper bindings that the pin controller driver can use. The pin configuration nodes need not be direct children of the pin controller device; they may be grandchildren, for example. Whether this is legal, and @@ -156,6 +157,29 @@ state_2_node_a { pins = "mfio29", "mfio30"; }; +For hardware where pin multiplexing configurations have to be specified for +each single pin the number of required sub-nodes containing "pin" and +"function" properties can quickly escalate and become hard to write and +maintain. + +For cases like this, the pin controller driver may use the pinmux helper +property, where the pin identifier is provided with mux configuration settings +in a pinmux group. A pinmux group consists of the pin identifier and mux +settings represented as a single integer or an array of integers. + +The pinmux property accepts an array of pinmux groups, each of them describing +a single pin multiplexing configuration. + +pincontroller { + state_0_node_a { + pinmux = , , ...; + }; +}; + +Each individual pin controller driver bindings documentation shall specify +how pin IDs and pin multiplexing configuration are defined and assembled +together in a pinmux group. + == Generic pin configuration node content == Many data items that are represented in a pin configuration node are common @@ -168,12 +192,15 @@ structure of the DT nodes that contain these properties. Supported generic properties are: pins - the list of pins that properties in the node - apply to (either this or "group" has to be + apply to (either this, "group" or "pinmux" has to be specified) group - the group to apply the properties to, if the driver supports configuration of whole groups rather than - individual pins (either this or "pins" has to be - specified) + individual pins (either this, "pins" or "pinmux" has + to be specified) +pinmux - the list of numeric pin ids and their mux settings + that properties in the node apply to (either this, + "pins" or "groups" have to be specified) bias-disable - disable any pin bias bias-high-impedance - high impedance mode ("third-state", "floating") bias-bus-hold - latch weakly @@ -184,17 +211,30 @@ drive-push-pull - drive actively high and low drive-open-drain - drive with open drain drive-open-source - drive with open source drive-strength - sink or source at most X mA -input-enable - enable input on pin (no effect on output) -input-disable - disable input on pin (no effect on output) +drive-strength-microamp - sink or source at most X uA +input-enable - enable input on pin (no effect on output, such as + enabling an input buffer) +input-disable - disable input on pin (no effect on output, such as + disabling an input buffer) input-schmitt-enable - enable schmitt-trigger mode input-schmitt-disable - disable schmitt-trigger mode input-debounce - debounce mode with debound time X power-source - select between different power supplies low-power-enable - enable low power mode low-power-disable - disable low power mode +output-disable - disable output on a pin (such as disable an output + buffer) +output-enable - enable output on a pin without actively driving it + (such as enabling an output buffer) output-low - set the pin to output mode with low level output-high - set the pin to output mode with high level +sleep-hardware-state - indicate this is sleep related state which will be programmed + into the registers for the sleep state. slew-rate - set the slew rate +skew-delay - this affects the expected clock skew on input pins + and the delay before latching a value to an output + pin. Typically indicates how many double-inverters are + used to delay the signal. For example: @@ -216,6 +256,12 @@ state_2_node_a { bias-pull-up; }; }; +state_3_node_a { + mux { + pinmux = , ; + input-enable; + }; +}; Some of the generic properties take arguments. For those that do, the arguments are described below. @@ -224,11 +270,18 @@ arguments are described below. binding for the hardware defines: - Whether the entries are integers or strings, and their meaning. +- pinmux takes a list of pin IDs and mux settings as required argument. The + specific bindings for the hardware defines: + - How pin IDs and mux settings are defined and assembled together in a single + integer or an array of integers. + - bias-pull-up, -down and -pin-default take as optional argument on hardware supporting it the pull strength in Ohm. bias-disable will disable the pull. - drive-strength takes as argument the target strength in mA. +- drive-strength-microamp takes as argument the target strength in uA. + - input-debounce takes the debounce time in usec as argument or 0 to disable debouncing diff --git a/u-boot/drivers/ata/ahci.c b/u-boot/drivers/ata/ahci.c index ad952f8ddf..c1327931c6 100644 --- a/u-boot/drivers/ata/ahci.c +++ b/u-boot/drivers/ata/ahci.c @@ -115,6 +115,22 @@ int __weak ahci_link_up(struct ahci_uc_priv *uc_priv, u8 port) int j = 0; void __iomem *port_mmio = uc_priv->port[port].port_mmio; + /* + * Add port reset before link up to fix some device link up + * fail. + */ + writel(0x4, port_mmio + PORT_SCR_CTL); + udelay(10000); + writel(0x1, port_mmio + PORT_SCR_CTL); + udelay(10000); + writel(0x0, port_mmio + PORT_SCR_CTL); + udelay(10000); + + writel(0x301, port_mmio + PORT_SCR_CTL); + udelay(10000); + writel(0x300, port_mmio + PORT_SCR_CTL); + udelay(1000); + /* * Bring up SATA link. * SATA link bringup time is usually less than 1 ms; only very diff --git a/u-boot/drivers/clk/rockchip/clk_pll.c b/u-boot/drivers/clk/rockchip/clk_pll.c index 49ddcc81a4..9566299c11 100644 --- a/u-boot/drivers/clk/rockchip/clk_pll.c +++ b/u-boot/drivers/clk/rockchip/clk_pll.c @@ -155,8 +155,8 @@ rockchip_pll_clk_set_by_auto(ulong fin_hz, f_frac = (foutvco % MHZ); fin_64 = fin_hz; - fin_64 = fin_64 / rate_table->refdiv; - frac_64 = f_frac << 24; + fin_64 = fin_64 / (ulong)rate_table->refdiv; + frac_64 = (ulong)f_frac << 24; frac_64 = frac_64 / fin_64; rate_table->frac = frac_64; if (rate_table->frac > 0) @@ -330,10 +330,10 @@ static int rk3036_pll_set_rate(struct rockchip_pll_clock *pll, RK3036_PLLCON1_REFDIV_MASK), (rate->postdiv2 << RK3036_PLLCON1_POSTDIV2_SHIFT | rate->refdiv << RK3036_PLLCON1_REFDIV_SHIFT)); - if (!rate->dsmpd) { - rk_clrsetreg(base + pll->con_offset + 0x4, + rk_clrsetreg(base + pll->con_offset + 0x4, RK3036_PLLCON1_DSMPD_MASK, rate->dsmpd << RK3036_PLLCON1_DSMPD_SHIFT); + if (!rate->dsmpd) { writel((readl(base + pll->con_offset + 0x8) & (~RK3036_PLLCON2_FRAC_MASK)) | (rate->frac << RK3036_PLLCON2_FRAC_SHIFT), @@ -372,7 +372,7 @@ static ulong rk3036_pll_get_rate(struct rockchip_pll_clock *pll, { u32 refdiv, fbdiv, postdiv1, postdiv2, dsmpd, frac; u32 con = 0, shift, mask; - ulong rate; + ulong rate, p_rate = OSC_HZ / KHZ; int mode; con = readl(base + pll->mode_offset); @@ -404,14 +404,14 @@ static ulong rk3036_pll_get_rate(struct rockchip_pll_clock *pll, con = readl(base + pll->con_offset + 0x8); frac = (con & RK3036_PLLCON2_FRAC_MASK) >> RK3036_PLLCON2_FRAC_SHIFT; - rate = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000; + rate = (p_rate * fbdiv / (refdiv * postdiv1 * postdiv2)) * KHZ; if (dsmpd == 0) { - u64 frac_rate = OSC_HZ * (u64)frac; + u64 frac_rate = p_rate * (u64)frac * KHZ; - do_div(frac_rate, refdiv); + do_div(frac_rate, (u64)refdiv); frac_rate >>= 24; - do_div(frac_rate, postdiv1); - do_div(frac_rate, postdiv1); + do_div(frac_rate, (u64)postdiv1); + do_div(frac_rate, (u64)postdiv2); rate += frac_rate; } return rate; @@ -491,11 +491,10 @@ static int rk3588_pll_set_rate(struct rockchip_pll_clock *pll, RK3588_PLLCON1_S_MASK), (rate->p << RK3588_PLLCON1_P_SHIFT | rate->s << RK3588_PLLCON1_S_SHIFT)); - if (rate->k) { - rk_clrsetreg(base + pll->con_offset + RK3588_PLLCON(2), - RK3588_PLLCON2_K_MASK, - rate->k << RK3588_PLLCON2_K_SHIFT); - } + + rk_clrsetreg(base + pll->con_offset + RK3588_PLLCON(2), + RK3588_PLLCON2_K_MASK, + rate->k << RK3588_PLLCON2_K_SHIFT); /* Power up */ rk_clrreg(base + pll->con_offset + RK3588_PLLCON(1), RK3588_PLLCON1_PWRDOWN); diff --git a/u-boot/drivers/clk/rockchip/clk_rk3036.c b/u-boot/drivers/clk/rockchip/clk_rk3036.c index a78c4db2b1..2ab8218a65 100644 --- a/u-boot/drivers/clk/rockchip/clk_rk3036.c +++ b/u-boot/drivers/clk/rockchip/clk_rk3036.c @@ -255,8 +255,16 @@ static ulong rockchip_mmc_get_clk(struct rk3036_cru *cru, uint clk_general_rate, break; case HCLK_SDIO: case SCLK_SDIO: + con = readl(&cru->cru_clksel_con[12]); + mux = (con & SDIO_PLL_MASK) >> SDIO_PLL_SHIFT; + con = readl(&cru->cru_clksel_con[11]); + div = (con & SDIO_DIV_MASK) >> SDIO_DIV_SHIFT; + break; + case HCLK_SDMMC: + case SCLK_SDMMC: con = readl(&cru->cru_clksel_con[12]); mux = (con & MMC0_PLL_MASK) >> MMC0_PLL_SHIFT; + con = readl(&cru->cru_clksel_con[11]); div = (con & MMC0_DIV_MASK) >> MMC0_DIV_SHIFT; break; default: @@ -296,10 +304,27 @@ static ulong rockchip_mmc_set_clk(struct rk3036_cru *cru, uint clk_general_rate, break; case HCLK_SDIO: case SCLK_SDIO: + rk_clrsetreg(&cru->cru_clksel_con[12], + SDIO_PLL_MASK, + SDIO_SEL_24M << SDIO_PLL_SHIFT); rk_clrsetreg(&cru->cru_clksel_con[11], - MMC0_PLL_MASK | MMC0_DIV_MASK, - mux << MMC0_PLL_SHIFT | + SDIO_DIV_MASK, + (src_clk_div - 1) << SDIO_DIV_SHIFT); + rk_clrsetreg(&cru->cru_clksel_con[12], + SDIO_PLL_MASK, + mux << SDIO_PLL_SHIFT); + break; + case HCLK_SDMMC: + case SCLK_SDMMC: + rk_clrsetreg(&cru->cru_clksel_con[12], + MMC0_PLL_MASK, + MMC0_SEL_24M << MMC0_PLL_SHIFT); + rk_clrsetreg(&cru->cru_clksel_con[11], + MMC0_DIV_MASK, (src_clk_div - 1) << MMC0_DIV_SHIFT); + rk_clrsetreg(&cru->cru_clksel_con[12], + MMC0_PLL_MASK, + mux << MMC0_PLL_SHIFT); break; default: return -EINVAL; @@ -464,6 +489,14 @@ static ulong rk3036_clk_get_rate(struct clk *clk) switch (clk->id) { case 0 ... 63: return rkclk_pll_get_rate(priv->cru, clk->id); + case SCLK_EMMC: + case SCLK_SDMMC: + case SCLK_SDIO: + case HCLK_EMMC: + case HCLK_SDMMC: + case HCLK_SDIO: + return rockchip_mmc_get_clk(priv->cru, gclk_rate, + clk->id); case SCLK_LCDC: return rockchip_dclk_lcdc_get_clk(priv->cru, gclk_rate); case ACLK_LCDC: @@ -487,7 +520,11 @@ static ulong rk3036_clk_set_rate(struct clk *clk, ulong rate) case 0 ... 63: return 0; case HCLK_EMMC: + case HCLK_SDMMC: + case HCLK_SDIO: case SCLK_EMMC: + case SCLK_SDMMC: + case SCLK_SDIO: new_rate = rockchip_mmc_set_clk(priv->cru, gclk_rate, clk->id, rate); break; diff --git a/u-boot/drivers/clk/rockchip/clk_rk3308.c b/u-boot/drivers/clk/rockchip/clk_rk3308.c index 725a5e2e05..82a2ac50ed 100644 --- a/u-boot/drivers/clk/rockchip/clk_rk3308.c +++ b/u-boot/drivers/clk/rockchip/clk_rk3308.c @@ -974,7 +974,9 @@ static ulong rk3308_clk_get_rate(struct clk *clk) case SCLK_SPI1: rate = rk3308_spi_get_clk(clk); break; - case SCLK_PWM: + case SCLK_PWM0: + case SCLK_PWM1: + case SCLK_PWM2: rate = rk3308_pwm_get_clk(clk); break; case DCLK_VOP: @@ -1059,7 +1061,9 @@ static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) case SCLK_SPI1: ret = rk3308_spi_set_clk(clk, rate); break; - case SCLK_PWM: + case SCLK_PWM0: + case SCLK_PWM1: + case SCLK_PWM2: ret = rk3308_pwm_set_clk(clk, rate); break; case DCLK_VOP: diff --git a/u-boot/drivers/clk/rockchip/clk_rk3528.c b/u-boot/drivers/clk/rockchip/clk_rk3528.c index ada7dd424f..dded6777e6 100644 --- a/u-boot/drivers/clk/rockchip/clk_rk3528.c +++ b/u-boot/drivers/clk/rockchip/clk_rk3528.c @@ -1832,6 +1832,52 @@ U_BOOT_DRIVER(rockchip_rk3528_grf_cru) = { .probe = rk3528_grfclk_probe, }; +#ifdef CONFIG_SPL_BUILD + +#define COREGRF_BASE 0xff300000 +#define PVTPLL_CON0_L 0x0 +#define PVTPLL_CON0_H 0x4 + +static int rk3528_cpu_pvtpll_set_rate(struct rk3528_clk_priv *priv, ulong rate) +{ + struct rk3528_cru *cru = priv->cru; + u32 length; + + if (rate >= 1200000000) + length = 8; + else if (rate >= 1008000000) + length = 11; + else + length = 17; + + /* set pclk dbg div to 9 */ + rk_clrsetreg(&cru->clksel_con[40], RK3528_DIV_PCLK_DBG_MASK, + 9 << RK3528_DIV_PCLK_DBG_SHIFT); + /* set aclk_m_core div to 1 */ + rk_clrsetreg(&cru->clksel_con[39], RK3528_DIV_ACLK_M_CORE_MASK, + 1 << RK3528_DIV_ACLK_M_CORE_SHIFT); + + /* set ring sel = 1 */ + writel(0x07000000 | (1 << 8), COREGRF_BASE + PVTPLL_CON0_L); + /* set length */ + writel(0x007f0000 | length, COREGRF_BASE + PVTPLL_CON0_H); + /* enable pvtpll */ + writel(0x00020002, COREGRF_BASE + PVTPLL_CON0_L); + /* start monitor */ + writel(0x00010001, COREGRF_BASE + PVTPLL_CON0_L); + + /* set core mux pvtpll */ + writel(0x00010001, &cru->clksel_con[40]); + writel(0x00100010, &cru->clksel_con[39]); + + /* set pclk dbg div to 8 */ + rk_clrsetreg(&cru->clksel_con[40], RK3528_DIV_PCLK_DBG_MASK, + 8 << RK3528_DIV_PCLK_DBG_SHIFT); + + return 0; +} +#endif + static int rk3528_clk_init(struct rk3528_clk_priv *priv) { int ret; @@ -1866,7 +1912,13 @@ static int rk3528_clk_init(struct rk3528_clk_priv *priv) if (!ret) priv->armclk_init_hz = APLL_HZ; } -#else + + if (!rk3528_cpu_pvtpll_set_rate(priv, CPU_PVTPLL_HZ)) { + printf("cpu pvtpll %d KHz\n", CPU_PVTPLL_HZ / 1000); + priv->armclk_init_hz = CPU_PVTPLL_HZ; + } + +#elif CONFIG_IS_ENABLED(CLK_SCMI) if (!priv->armclk_enter_hz) { struct clk clk; @@ -1882,9 +1934,7 @@ static int rk3528_clk_init(struct rk3528_clk_priv *priv) printf("Failed to set scmi cpu %dhz\n", CPU_PVTPLL_HZ); return ret; } else { - priv->armclk_enter_hz = - rockchip_pll_get_rate(&rk3528_pll_clks[APLL], - priv->cru, APLL); + priv->armclk_enter_hz = CPU_PVTPLL_HZ; priv->armclk_init_hz = CPU_PVTPLL_HZ; } } diff --git a/u-boot/drivers/clk/rockchip/clk_rk3562.c b/u-boot/drivers/clk/rockchip/clk_rk3562.c index 36d8c447a1..ee22b7fa9f 100644 --- a/u-boot/drivers/clk/rockchip/clk_rk3562.c +++ b/u-boot/drivers/clk/rockchip/clk_rk3562.c @@ -31,6 +31,8 @@ static struct rockchip_pll_rate_table rk3562_pll_rates[] = { RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0), RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0), RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE(705600000, 2, 235, 4, 1, 0, 3355443), + RK3036_PLL_RATE(611520000, 4, 611, 6, 1, 0, 8724152), RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0), RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0), RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), @@ -1166,7 +1168,7 @@ static ulong rk3562_vop_get_rate(struct rk3562_clk_priv *priv, ulong clk_id) return DIV_TO_RATE(prate, div); } -#define RK3562_VOP_PLL_LIMIT_FREQ 600000000 +#define RK3562_VOP_PLL_LIMIT_FREQ 594000000 static ulong rk3562_vop_set_rate(struct rk3562_clk_priv *priv, ulong clk_id, ulong rate) @@ -1198,6 +1200,8 @@ static ulong rk3562_vop_set_rate(struct rk3562_clk_priv *priv, ulong clk_id, return rk3562_vop_get_rate(priv, clk_id); case DCLK_VOP: div = DIV_ROUND_UP(RK3562_VOP_PLL_LIMIT_FREQ, rate); + if (div % 2) + div = div + 1; rk_clrsetreg(&cru->clksel_con[30], DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK, DCLK_VOP_SEL_VPLL << DCLK_VOP_SEL_SHIFT | @@ -1792,7 +1796,7 @@ static void rk3562_clk_init(struct rk3562_clk_priv *priv) priv->cru, APLL); if (!priv->armclk_init_hz) { -#ifdef CONFIG_SPL_BUILD +#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_SUPPORT_USBPLUG) ret = rk3562_armclk_set_rate(priv, APLL_HZ); if (!ret) priv->armclk_init_hz = APLL_HZ; diff --git a/u-boot/drivers/clk/rockchip/clk_rk3568.c b/u-boot/drivers/clk/rockchip/clk_rk3568.c index f917357558..ae33fa2bd2 100644 --- a/u-boot/drivers/clk/rockchip/clk_rk3568.c +++ b/u-boot/drivers/clk/rockchip/clk_rk3568.c @@ -1815,7 +1815,7 @@ static ulong rk3568_dclk_vop_get_clk(struct rk3568_clk_priv *priv, ulong clk_id) return DIV_TO_RATE(parent, div); } -#define RK3568_VOP_PLL_LIMIT_FREQ 600000000 +#define RK3568_VOP_PLL_LIMIT_FREQ 594000000 static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv, ulong clk_id, ulong rate) @@ -1850,6 +1850,8 @@ static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv, rk3568_pmu_pll_set_rate(priv, HPLL, div * rate); } else if (sel == DCLK_VOP_SEL_VPLL) { div = DIV_ROUND_UP(RK3568_VOP_PLL_LIMIT_FREQ, rate); + if (div % 2) + div = div + 1; rk_clrsetreg(&cru->clksel_con[conid], DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK, (DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT) | @@ -1865,6 +1867,9 @@ static ulong rk3568_dclk_vop_set_clk(struct rk3568_clk_priv *priv, case DCLK_VOP_SEL_CPLL: pll_rate = priv->cpll_hz; break; + case DCLK_VOP_SEL_HPLL: + case DCLK_VOP_SEL_VPLL: + continue; default: printf("do not support this vop pll sel\n"); return -EINVAL; diff --git a/u-boot/drivers/clk/rockchip/clk_rk3588.c b/u-boot/drivers/clk/rockchip/clk_rk3588.c index 715ea04b93..a2aa6e1f26 100644 --- a/u-boot/drivers/clk/rockchip/clk_rk3588.c +++ b/u-boot/drivers/clk/rockchip/clk_rk3588.c @@ -1103,7 +1103,7 @@ static ulong rk3588_dclk_vop_get_clk(struct rk3588_clk_priv *priv, ulong clk_id) return DIV_TO_RATE(parent, div); } -#define RK3588_VOP_PLL_LIMIT_FREQ 600000000 +#define RK3588_VOP_PLL_LIMIT_FREQ 594000000 static ulong rk3588_dclk_vop_set_clk(struct rk3588_clk_priv *priv, ulong clk_id, ulong rate) @@ -1164,6 +1164,8 @@ static ulong rk3588_dclk_vop_set_clk(struct rk3588_clk_priv *priv, ((div - 1) << div_shift)); } else { div = DIV_ROUND_UP(RK3588_VOP_PLL_LIMIT_FREQ, rate); + if (div % 2) + div = div + 1; rk_clrsetreg(&cru->clksel_con[conid], mask, DCLK_VOP_SRC_SEL_V0PLL << sel_shift | @@ -2061,7 +2063,10 @@ static int rk3588_clk_probe(struct udevice *dev) { struct rk3588_clk_priv *priv = dev_get_priv(dev); int ret; + +#if CONFIG_IS_ENABLED(CLK_SCMI) struct clk clk; +#endif priv->sync_kernel = false; @@ -2080,6 +2085,7 @@ static int rk3588_clk_probe(struct udevice *dev) } #endif +#if CONFIG_IS_ENABLED(CLK_SCMI) ret = rockchip_get_scmi_clk(&clk.dev); if (ret) { printf("Failed to get scmi clk dev\n"); @@ -2110,6 +2116,7 @@ static int rk3588_clk_probe(struct udevice *dev) ret = clk_set_rate(&clk, CPU_PVTPLL_HZ); if (ret < 0) printf("Failed to set cpub23\n"); +#endif #endif priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); diff --git a/u-boot/drivers/clk/rockchip/clk_rv1106.c b/u-boot/drivers/clk/rockchip/clk_rv1106.c index dcf02e7170..a99846f4e1 100644 --- a/u-boot/drivers/clk/rockchip/clk_rv1106.c +++ b/u-boot/drivers/clk/rockchip/clk_rv1106.c @@ -1131,6 +1131,9 @@ static ulong rv1106_clk_get_rate(struct clk *clk) rate = rv1106_decom_get_clk(priv); break; #endif + case TCLK_WDT_NS: + rate = OSC_HZ; + break; default: return -ENOENT; } diff --git a/u-boot/drivers/core/device.c b/u-boot/drivers/core/device.c index a8803ee42c..b2df97f1c1 100644 --- a/u-boot/drivers/core/device.c +++ b/u-boot/drivers/core/device.c @@ -510,8 +510,10 @@ int device_probe(struct udevice *dev) if (ret) goto fail_uclass; - if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL) + if (dev->parent && device_get_uclass_id(dev) == UCLASS_PINCTRL) { + pinctrl_select_state(dev, "init"); pinctrl_select_state(dev, "default"); + } return 0; fail_uclass: diff --git a/u-boot/drivers/core/uclass.c b/u-boot/drivers/core/uclass.c index 02f1bebd80..cfcfdebe05 100644 --- a/u-boot/drivers/core/uclass.c +++ b/u-boot/drivers/core/uclass.c @@ -503,23 +503,40 @@ int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent, } #endif -int uclass_first_device(enum uclass_id id, struct udevice **devp) +/* + * Starting from the given device @dev, return pointer to the first device in + * the uclass that probes successfully in @devp. + */ +static void _uclass_next_device(struct udevice *dev, struct udevice **devp) +{ + for (; dev; uclass_find_next_device(&dev)) { + if (!device_probe(dev)) + break; + } + *devp = dev; +} + +void uclass_first_device(enum uclass_id id, struct udevice **devp) { struct udevice *dev; - int ret; - *devp = NULL; - ret = uclass_find_first_device(id, &dev); - if (!dev) - return 0; - return uclass_get_device_tail(dev, ret, devp); + uclass_find_first_device(id, &dev); + _uclass_next_device(dev, devp); +} + +void uclass_next_device(struct udevice **devp) +{ + struct udevice *dev = *devp; + + uclass_find_next_device(&dev); + _uclass_next_device(dev, devp); } int uclass_first_device_err(enum uclass_id id, struct udevice **devp) { int ret; - ret = uclass_first_device(id, devp); + ret = uclass_first_device_check(id, devp); if (ret) return ret; else if (!*devp) @@ -528,16 +545,17 @@ int uclass_first_device_err(enum uclass_id id, struct udevice **devp) return 0; } -int uclass_next_device(struct udevice **devp) +int uclass_next_device_err(struct udevice **devp) { - struct udevice *dev = *devp; int ret; - *devp = NULL; - ret = uclass_find_next_device(&dev); - if (!dev) - return 0; - return uclass_get_device_tail(dev, ret, devp); + ret = uclass_next_device_check(devp); + if (ret) + return ret; + else if (!*devp) + return -ENODEV; + + return 0; } int uclass_first_device_check(enum uclass_id id, struct udevice **devp) @@ -567,6 +585,23 @@ int uclass_next_device_check(struct udevice **devp) return device_probe(*devp); } +int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data, + struct udevice **devp) +{ + struct udevice *dev; + struct uclass *uc; + + uclass_id_foreach_dev(id, dev, uc) { + if (dev_get_driver_data(dev) == driver_data) { + *devp = dev; + + return device_probe(dev); + } + } + + return -ENODEV; +} + int uclass_bind_device(struct udevice *dev, bool after_u_boot_dev) { struct uclass *uc; diff --git a/u-boot/drivers/cpu/amp.its b/u-boot/drivers/cpu/amp.its index e1d3ed01ed..44db734fca 100644 --- a/u-boot/drivers/cpu/amp.its +++ b/u-boot/drivers/cpu/amp.its @@ -99,6 +99,8 @@ thumb = <0>; hyp = <0>; udelay = <1000000>; + load = <0x2000000>; // optional + load_c = <0x4000000>; // optional }; }; }; diff --git a/u-boot/drivers/cpu/rockchip_amp.c b/u-boot/drivers/cpu/rockchip_amp.c index 41439305a0..5c7f1592e5 100644 --- a/u-boot/drivers/cpu/rockchip_amp.c +++ b/u-boot/drivers/cpu/rockchip_amp.c @@ -248,7 +248,7 @@ static int brought_up_amp(void *fit, int noffset, const char *desc; boot_args_t args; u32 cpu, aarch64, hyp; - u32 load, thumb, us; + u32 load, load_c, thumb, us; u32 pe_state, entry; int boot_on; int data_size; @@ -261,6 +261,7 @@ static int brought_up_amp(void *fit, int noffset, hyp = fit_get_u32_default(fit, noffset, "hyp", 0); thumb = fit_get_u32_default(fit, noffset, "thumb", 0); entry = load = fit_get_u32_default(fit, noffset, "load", -ENODATA); + load_c = fit_get_u32_default(fit, noffset, "load_c", -ENODATA); us = fit_get_u32_default(fit, noffset, "udelay", 0); boot_on = fit_get_u32_default(fit, noffset, "boot-on", 1); fit_image_get_arch(fit, noffset, &arch); @@ -283,6 +284,14 @@ static int brought_up_amp(void *fit, int noffset, AMP_E("Property missing!\n"); return -EINVAL; } + + if (is_linux) { + if (load != -ENODATA) + env_set_hex("kernel_addr_r", load); + if (load_c != -ENODATA) + env_set_hex("kernel_addr_c", load_c); + } + aarch64 = (arch == IH_ARCH_ARM) ? 0 : 1; pe_state = PE_STATE(aarch64, hyp, thumb, 0); @@ -293,6 +302,7 @@ static int brought_up_amp(void *fit, int noffset, AMP_I(" hyp: %d\n", hyp); AMP_I(" thumb: %d\n", thumb); AMP_I(" load: 0x%08x\n", load); + AMP_I(" load_c: 0x%08x\n", load_c); AMP_I(" pe_state: 0x%08x\n", pe_state); AMP_I(" linux-os: %d\n\n", is_linux); #endif diff --git a/u-boot/drivers/crypto/rockchip/crypto_v2.c b/u-boot/drivers/crypto/rockchip/crypto_v2.c index e2135a7b40..78d3952681 100644 --- a/u-boot/drivers/crypto/rockchip/crypto_v2.c +++ b/u-boot/drivers/crypto/rockchip/crypto_v2.c @@ -1252,16 +1252,20 @@ int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx, case CRYPTO_DES: ret = rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len, ctx->iv, in, out, len, enc); + break; case CRYPTO_AES: ret = rk_crypto_aes(dev, ctx->mode, ctx->key, ctx->twk_key, ctx->key_len, ctx->iv, ctx->iv_len, in, out, len, enc); + break; case CRYPTO_SM4: ret = rk_crypto_sm4(dev, ctx->mode, ctx->key, ctx->twk_key, ctx->key_len, ctx->iv, ctx->iv_len, in, out, len, enc); + break; default: ret = -EINVAL; + break; } rk_crypto_disable_clk(dev); diff --git a/u-boot/drivers/dma/dma-uclass.c b/u-boot/drivers/dma/dma-uclass.c index 3d0ce22fbc..5d1bf8a437 100644 --- a/u-boot/drivers/dma/dma-uclass.c +++ b/u-boot/drivers/dma/dma-uclass.c @@ -21,10 +21,9 @@ DECLARE_GLOBAL_DATA_PTR; int dma_get_device(u32 transfer_type, struct udevice **devp) { struct udevice *dev; - int ret; - for (ret = uclass_first_device(UCLASS_DMA, &dev); dev && !ret; - ret = uclass_next_device(&dev)) { + for (uclass_first_device(UCLASS_DMA, &dev); dev; + uclass_next_device(&dev)) { struct dma_dev_priv *uc_priv; uc_priv = dev_get_uclass_priv(dev); @@ -40,7 +39,7 @@ int dma_get_device(u32 transfer_type, struct udevice **devp) *devp = dev; - return ret; + return 0; } int dma_memcpy(void *dst, void *src, size_t len) diff --git a/u-boot/drivers/gpio/Kconfig b/u-boot/drivers/gpio/Kconfig index 412df722e0..e50ea11aec 100644 --- a/u-boot/drivers/gpio/Kconfig +++ b/u-boot/drivers/gpio/Kconfig @@ -320,4 +320,13 @@ config MPC85XX_GPIO The driver has been tested on MPC85XX, but it is likely that other PowerQUICC III devices will work as well. + +config NCA9539_GPIO + bool "NCA9539 GPIO port expander driver" + depends on DM_GPIO + default n + help + Device model driver support for NCA9539 GPIO expander. It should be + usable on many NCA9539 families like NCA9539 & NCA9535. + Tested on NCA9539. endmenu diff --git a/u-boot/drivers/gpio/Makefile b/u-boot/drivers/gpio/Makefile index 1396467ab6..6dbbb9e67b 100644 --- a/u-boot/drivers/gpio/Makefile +++ b/u-boot/drivers/gpio/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(SPL_)PCF8575_GPIO) += pcf8575_gpio.o obj-$(CONFIG_PM8916_GPIO) += pm8916_gpio.o +obj-$(CONFIG_NCA9539_GPIO) += nca9539_gpio.o diff --git a/u-boot/drivers/gpio/gpio-uclass.c b/u-boot/drivers/gpio/gpio-uclass.c index a8479b061e..8599ef367e 100644 --- a/u-boot/drivers/gpio/gpio-uclass.c +++ b/u-boot/drivers/gpio/gpio-uclass.c @@ -34,11 +34,10 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) { struct gpio_dev_priv *uc_priv; struct udevice *dev; - int ret; - for (ret = uclass_first_device(UCLASS_GPIO, &dev); + for (uclass_first_device(UCLASS_GPIO, &dev); dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { uc_priv = dev_get_uclass_priv(dev); if (gpio >= uc_priv->gpio_base && gpio < uc_priv->gpio_base + uc_priv->gpio_count) { @@ -50,7 +49,7 @@ static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc) } /* No such GPIO */ - return ret ? ret : -ENOENT; + return -ENOENT; } int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) @@ -59,12 +58,11 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) struct udevice *dev; ulong offset; int numeric; - int ret; numeric = isdigit(*name) ? simple_strtoul(name, NULL, 10) : -1; - for (ret = uclass_first_device(UCLASS_GPIO, &dev); + for (uclass_first_device(UCLASS_GPIO, &dev); dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { int len; uc_priv = dev_get_uclass_priv(dev); @@ -84,7 +82,7 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) } if (!dev) - return ret ? ret : -EINVAL; + return -EINVAL; desc->dev = dev; desc->offset = offset; diff --git a/u-boot/drivers/gpio/nca9539_gpio.c b/u-boot/drivers/gpio/nca9539_gpio.c new file mode 100644 index 0000000000..2eba9f7e4b --- /dev/null +++ b/u-boot/drivers/gpio/nca9539_gpio.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * NCA9539 I2C Port Expander I/O + * + * Copyright (C) 2023 Cody Xie + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NCA9539_REG_INPUT_PORT_BASE 0x00 +#define NCA9539_REG_INPUT_PORT0 (NCA9539_REG_INPUT_PORT_BASE + 0x0) +#define NCA9539_REG_INPUT_PORT1 (NCA9539_REG_INPUT_PORT_BASE + 0x1) +#define NCA9539_REG_OUTPUT_PORT_BASE 0x02 +#define NCA9539_REG_OUTPUT_PORT0 (NCA9539_REG_OUTPUT_PORT_BASE + 0x0) +#define NCA9539_REG_OUTPUT_PORT1 (NCA9539_REG_OUTPUT_PORT_BASE + 0x1) +#define NCA9539_REG_POLARITY_BASE 0x04 +#define NCA9539_REG_POLARITY_PORT0 (NCA9539_REG_POLARITY_BASE + 0x0) +#define NCA9539_REG_POLARITY_PORT1 (NCA9539_REG_POLARITY_BASE + 0x1) +#define NCA9539_REG_CONFIG_BASE 0x06 +#define NCA9539_REG_CONFIG_PORT0 (NCA9539_REG_CONFIG_BASE + 0x0) +#define NCA9539_REG_CONFIG_PORT1 (NCA9539_REG_CONFIG_BASE + 0x1) + +#define NCA9539_BANK_SZ 8 +#define NCA9539_MAX_BANK 2 + +#define NCA9539_CHIP_ADDR 0x74 + +#ifndef BIT +#define BIT(nr) (1UL << (nr)) +#endif + +struct nca9539_info { + struct udevice *dev; + int addr; + unsigned int ngpio; +}; + +static int nca9539_write_reg(struct udevice *dev, int reg, u8 val) +{ + int ret = 0; + + ret = dm_i2c_write(dev, reg, &val, 1); + if (ret) { + dev_err(dev, "%s error\n", __func__); + return ret; + } + + return 0; +} + +static int nca9539_read_reg(struct udevice *dev, int reg, u8 *val) +{ + int ret; + u8 byte; + + ret = dm_i2c_read(dev, reg, &byte, 1); + if (ret) { + dev_err(dev, "%s error\n", __func__); + return ret; + } + + *val = byte; + + return 0; +} + +static int nca9539_gpio_get_direction(struct udevice *dev, unsigned int offset) +{ + unsigned int port = offset / NCA9539_BANK_SZ; + unsigned int pin = offset % NCA9539_BANK_SZ; + u8 value; + int ret; + + dev_dbg(dev, "%s offset(%d)\n", __func__, offset); + ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); + if (ret < 0) { + dev_err(dev, "%s offset(%d) read config failed\n", __func__, + offset); + return ret; + } + + if (value & BIT(pin)) + return GPIOF_INPUT; + + return GPIOF_OUTPUT; +} + +static int nca9539_gpio_direction_input(struct udevice *dev, + unsigned int offset) +{ + unsigned int port = offset / NCA9539_BANK_SZ; + unsigned int pin = offset % NCA9539_BANK_SZ; + u8 val; + int ret = 0; + + dev_dbg(dev, "%s offset(%d)\n", __func__, offset); + + ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &val); + if (!ret) { + val &= ~BIT(pin); + val |= BIT(pin); + ret = nca9539_write_reg(dev, NCA9539_REG_CONFIG_BASE + port, + val); + } + + if (ret < 0) { + dev_err(dev, "%s offset(%d) read config failed\n", __func__, + offset); + } + + return ret; +} + +static int nca9539_gpio_direction_output(struct udevice *dev, + unsigned int offset, int val) +{ + unsigned int port = offset / NCA9539_BANK_SZ; + unsigned int pin = offset % NCA9539_BANK_SZ; + u8 value; + int ret; + + dev_dbg(dev, "%s offset(%d) val(%d)\n", __func__, offset, val); + + ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); + if (!ret) { + value &= ~BIT(pin); + ret = nca9539_write_reg(dev, NCA9539_REG_CONFIG_BASE + port, + value); + } + if (ret < 0) { + dev_warn(dev, "%s offset(%d) read config failed\n", __func__, + offset); + } + + ret = nca9539_read_reg(dev, NCA9539_REG_OUTPUT_PORT_BASE + port, + &value); + if (!ret) { + value &= ~BIT(pin); + value |= val ? BIT(pin) : 0; + ret = nca9539_write_reg( + dev, NCA9539_REG_OUTPUT_PORT_BASE + port, value); + } + if (ret < 0) { + dev_err(dev, "%s offset(%d) val(%d) update output failed\n", + __func__, offset, val); + } + + return ret; +} + +static int nca9539_gpio_get(struct udevice *dev, unsigned int offset) +{ + unsigned int port = offset / NCA9539_BANK_SZ; + unsigned int pin = offset % NCA9539_BANK_SZ; + int reg; + u8 value; + int ret; + + dev_dbg(dev, "%s offset(%d)\n", __func__, offset); + ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); + if (ret < 0) { + dev_err(dev, "%s offset(%d) check config failed\n", __func__, + offset); + return ret; + } + if (!(BIT(pin) & value)) + reg = NCA9539_REG_OUTPUT_PORT_BASE + port; + else + reg = NCA9539_REG_INPUT_PORT_BASE + port; + ret = nca9539_read_reg(dev, reg, &value); + if (ret < 0) { + dev_err(dev, "%s offset(%d) read value failed\n", __func__, + offset); + return -EIO; + } + + return !!(BIT(pin) & value); +} + +static int nca9539_gpio_set(struct udevice *dev, unsigned int offset, int val) +{ + unsigned int port = offset / NCA9539_BANK_SZ; + unsigned int pin = offset % NCA9539_BANK_SZ; + u8 value; + int ret; + + dev_dbg(dev, "%s offset(%d) val(%d)\n", __func__, offset, val); + ret = nca9539_read_reg(dev, NCA9539_REG_CONFIG_BASE + port, &value); + if (ret < 0 || !!(BIT(pin) & value)) { + dev_warn(dev, "%s offset(%d) val(%d) check config failed\n", + __func__, offset, val); + } + + ret = nca9539_read_reg(dev, NCA9539_REG_OUTPUT_PORT_BASE + port, + &value); + if (!ret) { + value &= ~BIT(pin); + value |= val ? BIT(pin) : 0; + ret = nca9539_write_reg( + dev, NCA9539_REG_OUTPUT_PORT_BASE + port, value); + } + if (ret < 0) { + dev_err(dev, "%s offset(%d) val(%d) read input failed\n", + __func__, offset, val); + } + + return ret; +} + +static int nca9539_get_function(struct udevice *dev, unsigned offset) +{ + return nca9539_gpio_get_direction(dev, offset); +} + +static int nca9539_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; + + return 0; +} + +static const struct dm_gpio_ops nca9539_ops = { + .direction_input = nca9539_gpio_direction_input, + .direction_output = nca9539_gpio_direction_output, + .get_value = nca9539_gpio_get, + .set_value = nca9539_gpio_set, + .get_function = nca9539_get_function, + .xlate = nca9539_xlate, +}; + +static int nca9539_probe(struct udevice *dev) +{ + struct nca9539_info *info = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + char name[32], *str; + ulong driver_data; + + if (!info) { + dev_err(dev, "platdata not ready\n"); + return -ENOMEM; + } + + if (!chip) { + dev_err(dev, "i2c not ready\n"); + return -ENODEV; + } + +#if CONFIG_IS_ENABLED(OF_CONTROL) + info->addr = chip->chip_addr; +#else + info->addr = NCA9539_CHIP_ADDR; +#endif + + driver_data = dev_get_driver_data(dev); + info->ngpio = driver_data; + if (info->ngpio > NCA9539_MAX_BANK * NCA9539_BANK_SZ) { + dev_err(dev, "Max support %d pins now\n", + NCA9539_MAX_BANK * NCA9539_BANK_SZ); + return -EINVAL; + } + + snprintf(name, sizeof(name), "gpio@%x_", info->addr); + str = strdup(name); + if (!str) + return -ENOMEM; + uc_priv->bank_name = str; + uc_priv->gpio_count = info->ngpio; + + dev_dbg(dev, "%s is ready\n", str); + + return 0; +} + +static const struct udevice_id nca9539_ids[] = { + { + .compatible = "novo,nca9539-gpio", + .data = (ulong)16, + }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(nca9539) = { + .name = "nca9539", + .id = UCLASS_GPIO, + .ops = &nca9539_ops, + .probe = nca9539_probe, + .platdata_auto_alloc_size = sizeof(struct nca9539_info), + .of_match = nca9539_ids, +}; diff --git a/u-boot/drivers/irq/irq-gpio-switch.c b/u-boot/drivers/irq/irq-gpio-switch.c index 3c5b92f36e..10acd9f331 100644 --- a/u-boot/drivers/irq/irq-gpio-switch.c +++ b/u-boot/drivers/irq/irq-gpio-switch.c @@ -42,7 +42,8 @@ static struct gpio_bank gpio_banks[GPIO_BANK_NUM] = { #endif }; -static const char *gpio_alias[GPIO_BANK_NUM]; +static const char *aliases_gpios[GPIO_BANK_NUM]; +static const char *order_gpios[GPIO_BANK_NUM]; static int gpio_is_valid(u32 gpio) { @@ -80,14 +81,92 @@ static int __hard_gpio_to_irq(u32 gpio) return -EINVAL; } +static int init_order_gpios(void) +{ + const void *fdt = gd->fdt_blob; + static int initialized; + int node, offset; + int i = 0; + + if (initialized) + return 0; + + node = fdt_path_offset(fdt, "/pinctrl"); + if (node < 0) + return -EINVAL; + + for (offset = fdt_first_subnode(fdt, node); + offset >= 0 && i < GPIO_BANK_NUM; + offset = fdt_next_subnode(fdt, offset)) { + if (i >= GPIO_BANK_NUM) + break; + + order_gpios[i++] = fdt_get_name(fdt, offset, NULL); + IRQ_D("order gpio: %s\n", order_gpios[i - 1]); + } + + initialized = 1; + + return 0; +} + +static int init_aliases_gpios(void) +{ + static int initialized; + char alias_name[6]; + int i; + + if (initialized) + return 0; + + for (i = 0; i < GPIO_BANK_NUM; i++) { + snprintf(alias_name, 6, "gpio%d", i); + aliases_gpios[i] = fdt_get_alias(gd->fdt_blob, alias_name); + if (!aliases_gpios[i]) + return -EINVAL; + + IRQ_D("aliases gpio: %s\n", aliases_gpios[i]); + } + + initialized = 1; + + return 0; +} + +static int lookup_gpio_bank(const char *name) +{ + int bank, ret; + + for (bank = 0; bank < GPIO_BANK_NUM; bank++) { + if (strstr(name, gpio_banks[bank].name)) + return bank; + } + + ret = init_aliases_gpios(); + for (bank = 0; !ret && bank < GPIO_BANK_NUM; bank++) { + /* + * @name pattern can be: + * /pinctrl/gpio@fd8a0000 or gpio@fd8a0000 + */ + if (strstr(aliases_gpios[bank], name)) + return bank; + } + + ret = init_order_gpios(); + for (bank = 0; !ret && bank < GPIO_BANK_NUM; bank++) { + if (!strcmp(name, order_gpios[bank])) + return bank; + } + + return -ENOENT; +} + static int __phandle_gpio_to_irq(u32 gpio_phandle, u32 offset) { const void *blob = gd->fdt_blob; const char *gpio_name; - char alias_name[6]; int irq, node; - int i, bank; - bool found = false; + int bank; node = fdt_node_offset_by_phandle(blob, gpio_phandle); if (node < 0) { @@ -99,36 +178,8 @@ static int __phandle_gpio_to_irq(u32 gpio_phandle, u32 offset) if (!gpio_name) return EINVAL_GPIO; - for (bank = 0; bank < GPIO_BANK_NUM; bank++) { - if (strstr(gpio_name, gpio_banks[bank].name)) { - found = true; - break; - } - } - - if (!found) { - /* initial getting all gpio alias */ - if (!gpio_alias[0]) { - for (i = 0; i < GPIO_BANK_NUM; i++) { - snprintf(alias_name, 6, "gpio%d", i); - gpio_alias[i] = fdt_get_alias(blob, alias_name); - if (!gpio_alias[i]) { - IRQ_D("No gpio alias %s\n", alias_name); - return EINVAL_GPIO; - } - } - } - - /* match alias ? */ - for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) { - if (strstr(gpio_alias[bank], gpio_name)) { - found = true; - break; - } - } - } - - if (!found) { + bank = lookup_gpio_bank(gpio_name); + if (bank < 0) { IRQ_E("IRQ Framework can't find: %s\n", gpio_name); return EINVAL_GPIO; } diff --git a/u-boot/drivers/irq/irq-gpio-v2.c b/u-boot/drivers/irq/irq-gpio-v2.c index 9ad58d611a..ba19074adb 100644 --- a/u-boot/drivers/irq/irq-gpio-v2.c +++ b/u-boot/drivers/irq/irq-gpio-v2.c @@ -117,7 +117,7 @@ static void generic_gpio_handle_irq(int irq, void *data __always_unused) h_pin = pin - 16; if (ilr_h & (1 << h_pin)) { unmasked = 1; - gpio_irq_unmask(bank->regbase, offset_to_bit(h_pin)); + gpio_irq_unmask(bank->regbase, offset_to_bit(pin)); } } __generic_gpio_handle_irq(gpio_irq + pin); diff --git a/u-boot/drivers/misc/Kconfig b/u-boot/drivers/misc/Kconfig index 9b238e077f..fe288ad6bd 100644 --- a/u-boot/drivers/misc/Kconfig +++ b/u-boot/drivers/misc/Kconfig @@ -85,6 +85,12 @@ config ROCKCHIP_HW_DECOMPRESS This driver support Decompress IP built-in Rockchip SoC, support LZ4, GZIP, PNG, ZLIB. +config ROCKCHIP_PM_CONFIG + bool "Rockchip PM Config Support" + depends on ARM_CPU_SUSPEND + help + This driver supports to configure parameters of system sleep. + config SPL_ROCKCHIP_HW_DECOMPRESS bool "Rockchip HardWare Decompress Support" depends on SPL_MISC_DECOMPRESS diff --git a/u-boot/drivers/misc/Makefile b/u-boot/drivers/misc/Makefile index df1fee87f1..4d6b1f7188 100644 --- a/u-boot/drivers/misc/Makefile +++ b/u-boot/drivers/misc/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o obj-$(CONFIG_CROS_EC_SANDBOX) += cros_ec_sandbox.o obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o +obj-$(CONFIG_ROCKCHIP_PM_CONFIG) += rockchip_pm_config.o endif obj-$(CONFIG_FSL_IIM) += fsl_iim.o obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o diff --git a/u-boot/drivers/misc/rockchip_decompress.c b/u-boot/drivers/misc/rockchip_decompress.c index 85edf6e9f2..bbd74a2063 100644 --- a/u-boot/drivers/misc/rockchip_decompress.c +++ b/u-boot/drivers/misc/rockchip_decompress.c @@ -98,6 +98,7 @@ static int rockchip_decom_start(struct udevice *dev, void *buf) struct decom_param *param = (struct decom_param *)buf; unsigned int limit_lo = param->size_dst & 0xffffffff; unsigned int limit_hi = param->size_dst >> 32; + u32 irq_status; #if CONFIG_IS_ENABLED(DM_RESET) reset_assert(&priv->rst); @@ -118,6 +119,11 @@ static int rockchip_decom_start(struct udevice *dev, void *buf) priv->done = false; + irq_status = readl(priv->base + DECOM_ISR); + /* clear interrupts */ + if (irq_status) + writel(irq_status, priv->base + DECOM_ISR); + if (param->mode == DECOM_LZ4) writel(LZ4_CONT_CSUM_CHECK_EN | LZ4_HEAD_CSUM_CHECK_EN | @@ -137,6 +143,8 @@ static int rockchip_decom_start(struct udevice *dev, void *buf) writel(limit_lo, priv->base + DECOM_LMTSL); writel(limit_hi, priv->base + DECOM_LMTSH); + if (param->flags && DCOMP_FLG_IRQ_ONESHOT) + writel(DECOM_INT_MASK, priv->base + DECOM_IEN); writel(DECOM_ENABLE, priv->base + DECOM_ENR); priv->idle_check_once = true; diff --git a/u-boot/drivers/misc/rockchip_pm_config.c b/u-boot/drivers/misc/rockchip_pm_config.c new file mode 100644 index 0000000000..e586336c15 --- /dev/null +++ b/u-boot/drivers/misc/rockchip_pm_config.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define RK_ATAG_MCU_SLP_CORE 0x526b0001 +#define RK_ATAG_MCU_SLP_MAX 0x526b00ff +#define RK_ATAG_NONE 0x00000000 + +/* rk_tag related defines */ +#define sleep_tag_next(t) \ + ((struct rk_sleep_tag *)((__u32 *)(t) + (t)->hdr.size)) + +struct rk_tag_header { + u32 size; + u32 tag; +}; + +struct rk_sleep_tag { + struct rk_tag_header hdr; + u32 params[]; +}; + +struct rk_mcu_sleep_core_tag { + struct rk_tag_header hdr; + u32 total_size; + u32 reserve[13]; +}; + +struct rk_mcu_sleep_tags { + struct rk_mcu_sleep_core_tag core; + struct rk_sleep_tag slp_tags; +}; + +static int rockchip_pm_config_ioctl(struct udevice *dev, + unsigned long request, + void *buf) +{ + int ret = -EINVAL; + + switch (request) { + case IOCTL_REQ_START: + break; + default: + printf("Unsupported ioctl: %ld\n", (ulong)request); + break; + } + + return ret; +} + +static const struct misc_ops rockchip_pm_config_ops = { + .ioctl = rockchip_pm_config_ioctl, +}; + +static int parse_mcu_sleep_config(ofnode node) +{ + int ret, len; + ofnode mcu_sleep_node; + ofnode child; + struct arm_smccc_res res; + struct rk_mcu_sleep_tags *config; + struct rk_sleep_tag *slp_tag; + char *end; + + mcu_sleep_node = ofnode_find_subnode(node, "rockchip-mcu-sleep-cfg"); + if (ofnode_valid(mcu_sleep_node) == 0) { + ret = -ENODEV; + goto out; + } + + child = ofnode_first_subnode(mcu_sleep_node); + if (ofnode_valid(child) == 0) { + pr_err("%s: no valid child node in rockchip-mcu-sleep-cfg\n", + __func__); + ret = -ENODEV; + goto out; + } + + /* + * 4kb for sleep parameters + */ + res = sip_smc_request_share_mem(1, SHARE_PAGE_TYPE_SLEEP); + if (res.a0 != 0) { + pr_err("%s: no trust memory for mcu_sleep\n", __func__); + ret = -ENOMEM; + goto out; + } + + /* Initialize core tag */ + memset((void *)res.a1, 0, sizeof(struct rk_mcu_sleep_tags)); + config = (struct rk_mcu_sleep_tags *)res.a1; + config->core.hdr.tag = RK_ATAG_MCU_SLP_CORE; + config->core.hdr.size = sizeof(struct rk_mcu_sleep_core_tag) / sizeof(u32); + config->core.total_size = sizeof(struct rk_mcu_sleep_tags) - + sizeof(struct rk_sleep_tag); + + slp_tag = &config->slp_tags; + + /* End point of sleep data */ + end = (char *)config + PAGE_SIZE - sizeof(struct rk_sleep_tag); + + ofnode_for_each_subnode(child, mcu_sleep_node) { + /* Is overflow? */ + if ((char *)slp_tag->params >= end) + break; + + ret = ofnode_read_u32_array(child, "rockchip,tag", + &slp_tag->hdr.tag, 1); + if (ret || + slp_tag->hdr.tag <= RK_ATAG_MCU_SLP_CORE || + slp_tag->hdr.tag >= RK_ATAG_MCU_SLP_MAX) { + pr_err("%s: no or invalid rockchip,tag in %s\n", + __func__, ofnode_get_name(child)); + + continue; + } + + len = ofnode_read_size(child, "rockchip,params"); + if (len > 0) { + /* Is overflow? */ + if ((char *)(slp_tag->params + len) >= end) { + pr_warn("%s: no more space for rockchip,tag in %s\n", + __func__, ofnode_get_name(child)); + break; + } + + ret = ofnode_read_u32_array(child, "rockchip,params", + slp_tag->params, + len / sizeof(u32)); + if (ret) { + pr_err("%s: read rockchip,params error in %s\n", + __func__, ofnode_get_name(child)); + break; + } + + slp_tag->hdr.size = + (len + sizeof(struct rk_tag_header)) / sizeof(u32); + } else if (len == 0) { + slp_tag->hdr.size = 0; + } else { + continue; + } + + config->core.total_size += slp_tag->hdr.size * sizeof(u32); + + slp_tag = sleep_tag_next(slp_tag); + } + + /* Add none tag. + * Compiler will combine the follow code as "str xzr, [x28]", but + * "slp->hdr" may not be 8-byte alignment. So we use memset_io instead: + * slp_tag->hdr.size = 0; + * slp_tag->hdr.tag = RK_ATAG_NONE; + */ + memset_io(&slp_tag->hdr, 0, sizeof(slp_tag->hdr)); + + config->core.total_size += sizeof(struct rk_sleep_tag); + + ret = 0; + +out: + return ret; +} + +static int rockchip_pm_config_probe(struct udevice *dev) +{ + parse_mcu_sleep_config(dev_ofnode(dev)); + + return 0; +} + +static const struct udevice_id rockchip_pm_config_ids[] = { + { .compatible = "rockchip,pm-rk3588" }, + {} +}; + +U_BOOT_DRIVER(rockchip_pm_config) = { + .name = "rockchip_pm_config", + .id = UCLASS_MISC, + .of_match = rockchip_pm_config_ids, + .probe = rockchip_pm_config_probe, + .ops = &rockchip_pm_config_ops, +}; diff --git a/u-boot/drivers/mmc/dw_mmc.c b/u-boot/drivers/mmc/dw_mmc.c index 8126ac0e48..3286105526 100644 --- a/u-boot/drivers/mmc/dw_mmc.c +++ b/u-boot/drivers/mmc/dw_mmc.c @@ -241,6 +241,10 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) buf = (unsigned int *)data->src; timeout = dwmci_get_drto(host, size); + /* The tuning data is 128bytes, a timeout of 1ms is sufficient.*/ + if ((dwmci_readl(host, DWMCI_CMD) & 0x1F) == MMC_SEND_TUNING_BLOCK_HS200) + timeout = 1; + size /= 4; for (;;) { @@ -248,6 +252,11 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) /* Error during data transfer. */ if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { debug("%s: DATA ERROR!\n", __func__); + /* + * It is necessary to wait for several cycles before + * resetting the controller while data timeout or error. + */ + udelay(1); dwmci_wait_reset(host, DWMCI_RESET_ALL); dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); diff --git a/u-boot/drivers/mmc/mmc-uclass.c b/u-boot/drivers/mmc/mmc-uclass.c index eb44c3891f..2f99198aa0 100644 --- a/u-boot/drivers/mmc/mmc-uclass.c +++ b/u-boot/drivers/mmc/mmc-uclass.c @@ -35,7 +35,8 @@ retry: cmd->cmdidx != MMC_CMD_SEND_OP_COND && cmd->cmdidx != MMC_SEND_TUNING_BLOCK_HS200 && cmd->cmdidx != MMC_CMD_READ_MULTIPLE_BLOCK && - cmd->cmdidx != MMC_CMD_WRITE_MULTIPLE_BLOCK) { + cmd->cmdidx != MMC_CMD_WRITE_MULTIPLE_BLOCK && + cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION ) { /* execute tuning at last retry. */ if (retry_time == 1 && mmc->timing == MMC_TIMING_MMC_HS200 && diff --git a/u-boot/drivers/mmc/mmc.c b/u-boot/drivers/mmc/mmc.c index 590e4ba6c8..59805d33aa 100644 --- a/u-boot/drivers/mmc/mmc.c +++ b/u-boot/drivers/mmc/mmc.c @@ -902,9 +902,13 @@ int mmc_send_tuning(struct mmc *mmc, u32 opcode) data.flags = MMC_DATA_READ; err = mmc_send_cmd(mmc, &cmd, &data); - if (err) + if (err) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + mmc_send_cmd(mmc, &cmd, NULL); goto out; - + } if (memcmp(data_buf, tuning_block_pattern, size)) err = -EIO; out: diff --git a/u-boot/drivers/mmc/rockchip_dw_mmc.c b/u-boot/drivers/mmc/rockchip_dw_mmc.c index a78cb39c7f..9df956f346 100644 --- a/u-boot/drivers/mmc/rockchip_dw_mmc.c +++ b/u-boot/drivers/mmc/rockchip_dw_mmc.c @@ -123,49 +123,115 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev) } #ifndef CONFIG_MMC_SIMPLE +#define NUM_PHASES 32 +#define TUNING_ITERATION_TO_PHASE(i, num_phases) (DIV_ROUND_UP((i) * 360, num_phases)) + static int rockchip_dwmmc_execute_tuning(struct dwmci_host *host, u32 opcode) { - int i = 0; - int ret = -1; struct mmc *mmc = host->mmc; struct udevice *dev = host->priv; struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); + int ret = 0; + int i, num_phases = NUM_PHASES; + bool v, prev_v = 0, first_v; + struct range_t { + short start; + short end; /* inclusive */ + }; + struct range_t ranges[NUM_PHASES / 2 + 1]; + unsigned int range_count = 0; + int longest_range_len = -1; + int longest_range = -1; + int middle_phase, real_middle_phase; + ulong ts; if (IS_ERR(&priv->sample_clk)) return -EIO; + ts = get_timer(0); - if (mmc->default_phase > 0 && mmc->default_phase < 360) { - ret = clk_set_phase(&priv->sample_clk, mmc->default_phase); - if (ret) - printf("set clk phase fail\n"); - else - ret = mmc_send_tuning(mmc, opcode); - mmc->default_phase = 0; - } - /* - * If use default_phase to tune successfully, return. - * Otherwise, use the othe phase to tune. - */ - if (!ret) - return ret; - - for (i = 0; i < 5; i++) { - /* mmc->init_retry must be 0, 1, 2, 3 */ - if (mmc->init_retry == 4) - mmc->init_retry = 0; - - ret = clk_set_phase(&priv->sample_clk, 90 * mmc->init_retry); - if (ret) { - printf("set clk phase fail\n"); + /* Try each phase and extract good ranges */ + for (i = 0; i < num_phases; ) { + /* Cannot guarantee any phases larger than 270 would work well */ + if (TUNING_ITERATION_TO_PHASE(i, num_phases) > 270) break; + clk_set_phase(&priv->sample_clk, TUNING_ITERATION_TO_PHASE(i, num_phases)); + + v = !mmc_send_tuning(mmc, opcode); + debug("3 Tuning phase is %d v = %x\n", TUNING_ITERATION_TO_PHASE(i, num_phases), v); + if (i == 0) + first_v = v; + + if ((!prev_v) && v) { + range_count++; + ranges[range_count - 1].start = i; } - ret = mmc_send_tuning(mmc, opcode); - debug("Tuning phase is %d, ret is %d\n", mmc->init_retry * 90, ret); - mmc->init_retry++; - if (!ret) - break; + + if (v) + ranges[range_count - 1].end = i; + i++; + prev_v = v; } + if (range_count == 0) { + dev_warn(host->dev, "All phases bad!"); + return -EIO; + } + + /* wrap around case, merge the end points */ + if ((range_count > 1) && first_v && v) { + ranges[0].start = ranges[range_count - 1].start; + range_count--; + } + + /* Find the longest range */ + for (i = 0; i < range_count; i++) { + int len = (ranges[i].end - ranges[i].start + 1); + + if (len < 0) + len += num_phases; + + if (longest_range_len < len) { + longest_range_len = len; + longest_range = i; + } + + debug("Good phase range %d-%d (%d len)\n", + TUNING_ITERATION_TO_PHASE(ranges[i].start, num_phases), + TUNING_ITERATION_TO_PHASE(ranges[i].end, num_phases), + len); + } + + printf("Best phase range %d-%d (%d len)\n", + TUNING_ITERATION_TO_PHASE(ranges[longest_range].start, num_phases), + TUNING_ITERATION_TO_PHASE(ranges[longest_range].end, num_phases), + longest_range_len); + + middle_phase = ranges[longest_range].start + longest_range_len / 2; + middle_phase %= num_phases; + real_middle_phase = TUNING_ITERATION_TO_PHASE(middle_phase, num_phases); + + /* + * Since we cut out 270 ~ 360, the original algorithm + * still rolling ranges before and after 270 together + * in some corner cases, we should adjust it to avoid + * using any middle phase located between 270 and 360. + * By calculatiion, it happends due to the bad phases + * lay between 90 ~ 180. So others are all fine to chose. + * Pick 270 is a better choice in those cases. In case of + * bad phases exceed 180, the middle phase of rollback + * would be bigger than 315, so we chose 360. + */ + if (real_middle_phase > 270) { + if (real_middle_phase < 315) + real_middle_phase = 270; + else + real_middle_phase = 0; + } + + printf("Successfully tuned phase to %d, used %ldms\n", real_middle_phase, get_timer(0) - ts); + + clk_set_phase(&priv->sample_clk, real_middle_phase); + return ret; } #else diff --git a/u-boot/drivers/mtd/mtd_blk.c b/u-boot/drivers/mtd/mtd_blk.c index 6472c01d1d..bbaf077f89 100644 --- a/u-boot/drivers/mtd/mtd_blk.c +++ b/u-boot/drivers/mtd/mtd_blk.c @@ -21,6 +21,8 @@ #include #endif +// #define MTD_BLK_VERBOSE + #define MTD_PART_NAND_HEAD "mtdparts=" #define MTD_PART_INFO_MAX_SIZE 512 #define MTD_SINGLE_PART_INFO_MAX_SIZE 40 @@ -458,6 +460,9 @@ ulong mtd_dread(struct udevice *udev, lbaint_t start, #endif struct mtd_info *mtd; int ret = 0; +#ifdef MTD_BLK_VERBOSE + ulong us = 1; +#endif if (!desc) return ret; @@ -469,24 +474,21 @@ ulong mtd_dread(struct udevice *udev, lbaint_t start, if (blkcnt == 0) return 0; - pr_debug("mtd dread %s %lx %lx\n", mtd->name, start, blkcnt); - +#ifdef MTD_BLK_VERBOSE + us = get_ticks(); +#endif if (desc->devnum == BLK_MTD_NAND) { ret = mtd_map_read(mtd, off, &rwsize, NULL, mtd->size, (u_char *)(dst)); if (!ret) - return blkcnt; - else - return 0; + ret = blkcnt; } else if (desc->devnum == BLK_MTD_SPI_NAND) { ret = mtd_map_read(mtd, off, &rwsize, NULL, mtd->size, (u_char *)(dst)); if (!ret) - return blkcnt; - else - return 0; + ret = blkcnt; } else if (desc->devnum == BLK_MTD_SPI_NOR) { #if defined(CONFIG_SPI_FLASH_MTD) || defined(CONFIG_SPL_BUILD) struct spi_nor *nor = (struct spi_nor *)mtd->priv; @@ -495,18 +497,22 @@ ulong mtd_dread(struct udevice *udev, lbaint_t start, if (desc->op_flag == BLK_PRE_RW) spi->mode |= SPI_DMA_PREPARE; - mtd_read(mtd, off, rwsize, &retlen_nor, dst); + ret = mtd_read(mtd, off, rwsize, &retlen_nor, dst); if (desc->op_flag == BLK_PRE_RW) spi->mode &= ~SPI_DMA_PREPARE; if (retlen_nor == rwsize) - return blkcnt; - else + ret = blkcnt; #endif - return 0; - } else { - return 0; } +#ifdef MTD_BLK_VERBOSE + us = (get_ticks() - us) / 24UL; + pr_err("mtd dread %s %lx %lx cost %ldus: %ldMB/s\n\n", mtd->name, start, blkcnt, us, (blkcnt / 2) / ((us + 999) / 1000)); +#else + pr_debug("mtd dread %s %lx %lx\n\n", mtd->name, start, blkcnt); +#endif + + return ret; } #if CONFIG_IS_ENABLED(MTD_WRITE) diff --git a/u-boot/drivers/mtd/nand/bbt.c b/u-boot/drivers/mtd/nand/bbt.c index 9738ef73c8..2c9ffde09f 100644 --- a/u-boot/drivers/mtd/nand/bbt.c +++ b/u-boot/drivers/mtd/nand/bbt.c @@ -17,18 +17,81 @@ #ifdef CONFIG_MTD_NAND_BBT_USING_FLASH #ifdef BBT_DEBUG -#define BBT_DBG pr_err +#define bbt_dbg pr_err #else -#define BBT_DBG(args...) +#define bbt_dbg(args...) #endif +#define BBT_VERSION_INVALID (0xFFFFFFFFU) +#define BBT_VERSION_BLOCK_ABNORMAL (BBT_VERSION_INVALID - 1) +#define BBT_VERSION_MAX (BBT_VERSION_INVALID - 8) + struct nanddev_bbt_info { u8 pattern[4]; unsigned int version; + u32 hash; }; static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; +#if defined(BBT_DEBUG) && defined(BBT_DEBUG_DUMP) +static void bbt_dbg_hex(char *s, void *buf, u32 len) +{ + u32 i, j = 0; + u32 *p32 = (u32 *)buf; + + for (i = 0; i < len / 4; i++) { + if (j == 0) + printf("%s %p + 0x%04x: ", s, buf, i * 4); + + printf("0x%08x,", p32[i]); + + if (++j >= (4)) { + j = 0; + printf("\n"); + } + } + printf("\n"); +} +#endif + +static u32 js_hash(u8 *buf, u32 len) +{ + u32 hash = 0x47C6A7E6; + u32 i; + + for (i = 0; i < len; i++) + hash ^= ((hash << 5) + buf[i] + (hash >> 2)); + + return hash; +} + +static bool bbt_check_hash(u8 *buf, u32 len, u32 hash_cmp) +{ + u32 hash; + + /* compatible with no-hash version */ + if (hash_cmp == 0 || hash_cmp == 0xFFFFFFFF) + return 1; + + hash = js_hash(buf, len); + if (hash != hash_cmp) + return 0; + + return 1; +} + +static u32 bbt_nand_isbad_bypass(struct nand_device *nand, u32 block) +{ + struct mtd_info *mtd = nanddev_to_mtd(nand); + struct nand_pos pos; + + nanddev_bbt_set_block_status(nand, block, NAND_BBT_BLOCK_STATUS_UNKNOWN); + nanddev_offs_to_pos(nand, block * mtd->erasesize, &pos); + + return nanddev_isbad(nand, &pos); +} + /** * nanddev_read_bbt() - Read the BBT (Bad Block Table) * @nand: NAND device @@ -50,7 +113,7 @@ static int nanddev_read_bbt(struct nand_device *nand, u32 block, bool update) u8 *data_buf, *oob_buf; struct nanddev_bbt_info *bbt_info; struct mtd_oob_ops ops; - int bbt_page_num; + u32 bbt_page_num; int ret = 0; unsigned int version = 0; @@ -87,27 +150,69 @@ static int nanddev_read_bbt(struct nand_device *nand, u32 block, bool update) /* Store one entry for each block */ ret = mtd_read_oob(mtd, block * mtd->erasesize, &ops); if (ret && ret != -EUCLEAN) { - pr_err("%s fail %d\n", __func__, ret); - ret = -EIO; + pr_err("read_bbt blk=%d fail=%d update=%d\n", block, ret, update); + ret = 0; + version = BBT_VERSION_BLOCK_ABNORMAL; goto out; } else { ret = 0; } - if (oob_buf[0] != 0xff && !memcmp(bbt_pattern, bbt_info->pattern, 4)) - version = bbt_info->version; + /* bad block or good block without bbt */ + if (memcmp(bbt_pattern, bbt_info->pattern, 4)) { + ret = 0; + goto out; + } - BBT_DBG("read_bbt from blk=%d tag=%d ver=%d\n", block, update, version); + /* good block with abnornal bbt */ + if (oob_buf[0] == 0xff || + !bbt_check_hash(data_buf, nbytes + sizeof(struct nanddev_bbt_info) - 4, bbt_info->hash)) { + pr_err("read_bbt check fail blk=%d ret=%d update=%d\n", block, ret, update); + ret = 0; + version = BBT_VERSION_BLOCK_ABNORMAL; + goto out; + } + + /* good block with good bbt */ + version = bbt_info->version; + bbt_dbg("read_bbt from blk=%d ver=%d update=%d\n", block, version, update); if (update && version > nand->bbt.version) { memcpy(nand->bbt.cache, data_buf, nbytes); nand->bbt.version = version; } +#if defined(BBT_DEBUG) && defined(BBT_DEBUG_DUMP) + bbt_dbg_hex("bbt", data_buf, nbytes + sizeof(struct nanddev_bbt_info)); + if (version) { + u8 *temp_buf = kzalloc(bbt_page_num * mtd->writesize, GFP_KERNEL); + bool in_scan = nand->bbt.option & NANDDEV_BBT_SCANNED; + + if (!temp_buf) + goto out; + + memcpy(temp_buf, nand->bbt.cache, nbytes); + memcpy(nand->bbt.cache, data_buf, nbytes); + + if (!in_scan) + nand->bbt.option |= NANDDEV_BBT_SCANNED; + for (block = 0; block < nblocks; block++) { + ret = nanddev_bbt_get_block_status(nand, block); + if (ret != NAND_BBT_BLOCK_GOOD) + bbt_dbg("bad block[0x%x], ret=%d\n", block, ret); + } + if (!in_scan) + nand->bbt.option &= ~NANDDEV_BBT_SCANNED; + memcpy(nand->bbt.cache, temp_buf, nbytes); + kfree(temp_buf); + ret = 0; + } +#endif + out: kfree(data_buf); kfree(oob_buf); - return ret < 0 ? -EIO : version; + return ret < 0 ? -EIO : (int)version; } static int nanddev_write_bbt(struct nand_device *nand, u32 block) @@ -120,11 +225,11 @@ static int nanddev_write_bbt(struct nand_device *nand, u32 block) u8 *data_buf, *oob_buf; struct nanddev_bbt_info *bbt_info; struct mtd_oob_ops ops; - int bbt_page_num; - int ret = 0; + u32 bbt_page_num; + int ret = 0, version; struct nand_pos pos; - BBT_DBG("write_bbt to blk=%d ver=%d\n", block, nand->bbt.version); + bbt_dbg("write_bbt to blk=%d ver=%d\n", block, nand->bbt.version); if (!nand->bbt.cache) return -ENOMEM; @@ -151,6 +256,7 @@ static int nanddev_write_bbt(struct nand_device *nand, u32 block) memcpy(data_buf, nand->bbt.cache, nbytes); memcpy(bbt_info, bbt_pattern, 4); bbt_info->version = nand->bbt.version; + bbt_info->hash = js_hash(data_buf, nbytes + sizeof(struct nanddev_bbt_info) - 4); /* Store one entry for each block */ nanddev_offs_to_pos(nand, block * mtd->erasesize, &pos); @@ -166,7 +272,20 @@ static int nanddev_write_bbt(struct nand_device *nand, u32 block) ops.ooblen = bbt_page_num * mtd->oobsize; ops.ooboffs = 0; ret = mtd_write_oob(mtd, block * mtd->erasesize, &ops); + if (ret) { + nand->ops->erase(nand, &pos); + goto out; + } + version = nanddev_read_bbt(nand, block, false); + if (version != bbt_info->version) { + pr_err("bbt_write fail, blk=%d recheck fail %d-%d\n", + block, version, bbt_info->version); + nand->ops->erase(nand, &pos); + ret = -EIO; + } else { + ret = 0; + } out: kfree(data_buf); kfree(oob_buf); @@ -180,14 +299,30 @@ static __maybe_unused int nanddev_bbt_format(struct nand_device *nand) struct mtd_info *mtd = nanddev_to_mtd(nand); struct nand_pos pos; u32 start_block, block; + unsigned int bits_per_block = fls(NAND_BBT_BLOCK_NUM_STATUS); + unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block, + BITS_PER_LONG); start_block = nblocks - NANDDEV_BBT_SCAN_MAXBLOCKS; for (block = 0; block < nblocks; block++) { nanddev_offs_to_pos(nand, block * mtd->erasesize, &pos); - if (nanddev_isbad(nand, &pos)) + if (nanddev_isbad(nand, &pos)) { + if (bbt_nand_isbad_bypass(nand, 0)) { + memset(nand->bbt.cache, 0, nwords * sizeof(*nand->bbt.cache)); + pr_err("bbt_format fail, test good block %d fail\n", 0); + return -EIO; + } + + if (!bbt_nand_isbad_bypass(nand, block)) { + memset(nand->bbt.cache, 0, nwords * sizeof(*nand->bbt.cache)); + pr_err("bbt_format fail, test bad block %d fail\n", block); + return -EIO; + } + nanddev_bbt_set_block_status(nand, block, NAND_BBT_BLOCK_FACTORY_BAD); + } } for (block = 0; block < NANDDEV_BBT_SCAN_MAXBLOCKS; block++) { @@ -214,11 +349,31 @@ static int nanddev_scan_bbt(struct nand_device *nand) nand->bbt.option |= NANDDEV_BBT_SCANNED; #ifndef CONFIG_SPL_BUILD if (nand->bbt.version == 0) { - nanddev_bbt_format(nand); + ret = nanddev_bbt_format(nand); + if (ret) { + nand->bbt.option = 0; + pr_err("%s format fail\n", __func__); + + return ret; + } + ret = nanddev_bbt_update(nand); if (ret) { nand->bbt.option = 0; - pr_err("%s fail\n", __func__); + pr_err("%s update fail\n", __func__); + + return ret; + } + } +#endif + +#if defined(BBT_DEBUG) + pr_err("scan_bbt success\n"); + if (nand->bbt.version) { + for (block = 0; block < nblocks; block++) { + ret = nanddev_bbt_get_block_status(nand, block); + if (ret != NAND_BBT_BLOCK_GOOD) + bbt_dbg("bad block[0x%x], ret=%d\n", block, ret); } } #endif @@ -275,32 +430,32 @@ EXPORT_SYMBOL_GPL(nanddev_bbt_cleanup); int nanddev_bbt_update(struct nand_device *nand) { #ifdef CONFIG_MTD_NAND_BBT_USING_FLASH + struct nand_pos pos; + struct mtd_info *mtd = nanddev_to_mtd(nand); + if (nand->bbt.cache && nand->bbt.option & NANDDEV_BBT_USE_FLASH) { unsigned int nblocks = nanddev_neraseblocks(nand); u32 bbt_version[NANDDEV_BBT_SCAN_MAXBLOCKS]; int start_block, block; u32 min_version, block_des; - int ret, count = 0; + int ret, count = 0, status; start_block = nblocks - NANDDEV_BBT_SCAN_MAXBLOCKS; for (block = 0; block < NANDDEV_BBT_SCAN_MAXBLOCKS; block++) { - ret = nanddev_bbt_get_block_status(nand, start_block + block); - if (ret == NAND_BBT_BLOCK_FACTORY_BAD) { - bbt_version[block] = 0xFFFFFFFF; - continue; - } - ret = nanddev_read_bbt(nand, start_block + block, - false); - if (ret < 0) - bbt_version[block] = 0xFFFFFFFF; - else if (ret == 0) - bbt_version[block] = 0; + status = nanddev_bbt_get_block_status(nand, start_block + block); + ret = nanddev_read_bbt(nand, start_block + block, false); + if (ret == 0 && status == NAND_BBT_BLOCK_FACTORY_BAD) + bbt_version[block] = BBT_VERSION_INVALID; + else if (ret == -EIO) + bbt_version[block] = BBT_VERSION_INVALID; + else if (ret == BBT_VERSION_BLOCK_ABNORMAL) + bbt_version[block] = ret; else bbt_version[block] = ret; } get_min_ver: - min_version = 0xFFFFFFFF; + min_version = BBT_VERSION_MAX; block_des = 0; for (block = 0; block < NANDDEV_BBT_SCAN_MAXBLOCKS; block++) { if (bbt_version[block] < min_version) { @@ -309,25 +464,38 @@ get_min_ver: } } + /* Overwrite the BBT_VERSION_BLOCK_ABNORMAL block */ + if (nand->bbt.version < min_version) + nand->bbt.version = min_version + 4; + if (block_des > 0) { nand->bbt.version++; ret = nanddev_write_bbt(nand, block_des); - bbt_version[block_des - start_block] = 0xFFFFFFFF; if (ret) { - pr_err("%s blk= %d ret= %d\n", __func__, - block_des, ret); - goto get_min_ver; - } else { - count++; - if (count < 2) - goto get_min_ver; - BBT_DBG("%s success\n", __func__); - } - } else { - pr_err("%s failed\n", __func__); + pr_err("bbt_update fail, blk=%d ret= %d\n", block_des, ret); - return -1; + return -1; + } + + bbt_version[block_des - start_block] = BBT_VERSION_INVALID; + count++; + if (count < 2) + goto get_min_ver; + bbt_dbg("bbt_update success\n"); + } else { + pr_err("bbt_update failed\n"); + ret = -1; } + + for (block = 0; block < NANDDEV_BBT_SCAN_MAXBLOCKS; block++) { + if (bbt_version[block] == BBT_VERSION_BLOCK_ABNORMAL) { + block_des = start_block + block; + nanddev_offs_to_pos(nand, block_des * mtd->erasesize, &pos); + nand->ops->erase(nand, &pos); + } + } + + return ret; } #endif return 0; diff --git a/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl.c b/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl.c index 20731d1806..1a900331ad 100644 --- a/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl.c +++ b/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl.c @@ -351,11 +351,11 @@ static int rockchip_nandc_probe(struct udevice *dev) id[1] == 0xDA || id[1] == 0xAC || id[1] == 0xDC || id[1] == 0xA3 || id[1] == 0xD3 || id[1] == 0x95 || - id[1] == 0x48) { + id[1] == 0x48 || id[1] == 0x63) { nand_page_size = 2048; nand_page_num = 64; nand_block_num = 1024; - if (id[1] == 0xDC) { + if (id[1] == 0xDC || id[1] == 0xAC) { if ((id[0] == 0x2C && id[3] == 0xA6) || (id[0] == 0xC2 && id[3] == 0xA2)) { nand_page_size = 4096; @@ -380,8 +380,11 @@ static int rockchip_nandc_probe(struct udevice *dev) nand_page_size = 4096; nand_block_num = 4096; } + } else if (id[1] == 0x63 && id[3] == 0x19) { /* IS34ML08G088 */ + nand_page_size = 4096; + nand_page_num = 64; + nand_block_num = 4096; } - g_rk_nand->chipnr = 1; g_rk_nand->databuf = kzalloc(nand_page_size, GFP_KERNEL); if (!g_rk_nand) diff --git a/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl_v9.c b/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl_v9.c index 0b225be338..1943a58fe5 100644 --- a/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl_v9.c +++ b/u-boot/drivers/mtd/nand/raw/rockchip_nand_spl_v9.c @@ -346,11 +346,12 @@ static int rockchip_nandc_probe(struct udevice *dev) id[1] == 0xDA || id[1] == 0xAC || id[1] == 0xDC || id[1] == 0xA3 || id[1] == 0xD3 || id[1] == 0x95 || - id[1] == 0x48 || id[1] == 0xD7) { + id[1] == 0x48 || id[1] == 0xD7 || + id[1] == 0x63) { nand_page_size = 2048; nand_page_num = 64; nand_block_num = 1024; - if (id[1] == 0xDC) { + if (id[1] == 0xDC || id[1] == 0xAC) { if ((id[0] == 0x2C && id[3] == 0xA6) || (id[0] == 0xC2 && id[3] == 0xA2)) { nand_page_size = 4096; @@ -379,6 +380,10 @@ static int rockchip_nandc_probe(struct udevice *dev) nand_page_size = 8192; nand_page_num = 128; nand_block_num = 4096; + } else if (id[1] == 0x63 && id[3] == 0x19) { /* IS34ML08G088 */ + nand_page_size = 4096; + nand_page_num = 64; + nand_block_num = 4096; } g_rk_nand->chipnr = 1; g_rk_nand->databuf = kzalloc(nand_page_size, GFP_KERNEL); diff --git a/u-boot/drivers/mtd/nand/spi/core.c b/u-boot/drivers/mtd/nand/spi/core.c index 2ddd2f362d..88b49bc453 100644 --- a/u-boot/drivers/mtd/nand/spi/core.c +++ b/u-boot/drivers/mtd/nand/spi/core.c @@ -872,6 +872,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = { #endif #ifdef CONFIG_SPI_NAND_UNIM &unim_spinand_manufacturer, + &unim_zl_spinand_manufacturer, #endif #ifdef CONFIG_SPI_NAND_SKYHIGH &skyhigh_spinand_manufacturer, diff --git a/u-boot/drivers/mtd/nand/spi/skyhigh.c b/u-boot/drivers/mtd/nand/spi/skyhigh.c index 7cf58c6ba5..c01fd747ce 100644 --- a/u-boot/drivers/mtd/nand/spi/skyhigh.c +++ b/u-boot/drivers/mtd/nand/spi/skyhigh.c @@ -19,7 +19,7 @@ #define SKYHIGH_STATUS_ECC_UNCOR_ERROR (3 << 4) static SPINAND_OP_VARIANTS(read_cache_variants, - SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 8, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), @@ -88,7 +88,7 @@ static const struct spinand_info skyhigh_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, + 0, SPINAND_ECCINFO(&s35ml04g3_ooblayout, s35ml0xg3_ecc_get_status)), SPINAND_INFO("S35ML02G3", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), @@ -97,7 +97,7 @@ static const struct spinand_info skyhigh_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, + 0, SPINAND_ECCINFO(&s35ml04g3_ooblayout, s35ml0xg3_ecc_get_status)), SPINAND_INFO("S35ML04G3", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), @@ -106,7 +106,7 @@ static const struct spinand_info skyhigh_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - SPINAND_HAS_QE_BIT, + 0, SPINAND_ECCINFO(&s35ml04g3_ooblayout, s35ml0xg3_ecc_get_status)), }; diff --git a/u-boot/drivers/mtd/nand/spi/unim.c b/u-boot/drivers/mtd/nand/spi/unim.c index b4e3e5b1aa..e6f7b1637e 100644 --- a/u-boot/drivers/mtd/nand/spi/unim.c +++ b/u-boot/drivers/mtd/nand/spi/unim.c @@ -12,7 +12,8 @@ #endif #include -#define SPINAND_MFR_UNIM 0xA1 +#define SPINAND_MFR_UNIM_ZL 0xA1 +#define SPINAND_MFR_UNIM 0xB0 static SPINAND_OP_VARIANTS(read_cache_variants, SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), @@ -27,8 +28,8 @@ static SPINAND_OP_VARIANTS(write_cache_variants, SPINAND_PROG_LOAD(true, 0, NULL, 0)); static SPINAND_OP_VARIANTS(update_cache_variants, - SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), - SPINAND_PROG_LOAD(false, 0, NULL, 0)); + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), + SPINAND_PROG_LOAD(true, 0, NULL, 0)); static int tx25g01_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *region) @@ -59,6 +60,59 @@ static const struct mtd_ooblayout_ops tx25g01_ooblayout = { .rfree = tx25g01_ooblayout_free, }; + +static int um19a0xisw_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + return -ERANGE; +} + +static int um19a0xisw_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 2; + region->length = 62; + + return 0; +} + +static const struct mtd_ooblayout_ops um19a0xisw_ooblayout = { + .ecc = um19a0xisw_ooblayout_ecc, + .rfree = um19a0xisw_ooblayout_free, +}; + +static int um19a1xisw_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 64; + region->length = 64; + + return 0; +} + +static int um19a1xisw_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 2; + region->length = 62; + + return 0; +} + +static const struct mtd_ooblayout_ops um19a1xisw_ooblayout = { + .ecc = um19a1xisw_ooblayout_ecc, + .rfree = um19a1xisw_ooblayout_free, +}; + /* * ecc bits: 0xC0[4,6] * [0b000], No bit errors were detected; @@ -82,7 +136,32 @@ static int tx25g01_ecc_get_status(struct spinand_device *spinand, return -EBADMSG; } -static const struct spinand_info unim_spinand_table[] = { +/* + * ecc bits: 0xC0[4,6] + * [0b000], No bit errors were detected; + * [0b001] and [0b011], 1~6 Bit errors were detected and corrected. Not + * reach Flipping Bits; + * [0b101], Bit error count equals the bit flip + * detection threshold + * [0b010], Multiple bit errors were detected and + * not corrected. + * others, Reserved. + */ +static int um19axxisw_ecc_ecc_get_status(struct spinand_device *spinand, + u8 status) +{ + struct nand_device *nand = spinand_to_nand(spinand); + u8 eccsr = (status & GENMASK(6, 4)) >> 4; + + if (eccsr <= 1 || eccsr == 3) + return eccsr; + else if (eccsr == 5) + return nand->eccreq.strength; + else + return -EBADMSG; +} + +static const struct spinand_info unim_zl_spinand_table[] = { SPINAND_INFO("TX25G01", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xF1), NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), @@ -94,9 +173,56 @@ static const struct spinand_info unim_spinand_table[] = { SPINAND_ECCINFO(&tx25g01_ooblayout, tx25g01_ecc_get_status)), }; +static const struct spinand_info unim_spinand_table[] = { + SPINAND_INFO("UM19A1HISW", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&um19a1xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), + SPINAND_INFO("UM19A0HCSW", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&um19a0xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), + SPINAND_INFO("UM19A0LCSW", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&um19a0xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), + SPINAND_INFO("UM19A1LISW", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), + NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&um19a1xisw_ooblayout, um19axxisw_ecc_ecc_get_status)), +}; + static const struct spinand_manufacturer_ops unim_spinand_manuf_ops = { }; +const struct spinand_manufacturer unim_zl_spinand_manufacturer = { + .id = SPINAND_MFR_UNIM_ZL, + .name = "UNIM_ZL", + .chips = unim_zl_spinand_table, + .nchips = ARRAY_SIZE(unim_zl_spinand_table), + .ops = &unim_spinand_manuf_ops, +}; + const struct spinand_manufacturer unim_spinand_manufacturer = { .id = SPINAND_MFR_UNIM, .name = "UNIM", diff --git a/u-boot/drivers/mtd/nand/spi/winbond.c b/u-boot/drivers/mtd/nand/spi/winbond.c index e05a0f7338..18ebeab65e 100644 --- a/u-boot/drivers/mtd/nand/spi/winbond.c +++ b/u-boot/drivers/mtd/nand/spi/winbond.c @@ -210,6 +210,15 @@ static const struct spinand_info winbond_spinand_table[] = { 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W25N01JWZEIG", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xBC), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), }; static int winbond_spinand_init(struct spinand_device *spinand) diff --git a/u-boot/drivers/mtd/nand/spi/xincun.c b/u-boot/drivers/mtd/nand/spi/xincun.c index dc6334d5f1..e8eadf565b 100644 --- a/u-boot/drivers/mtd/nand/spi/xincun.c +++ b/u-boot/drivers/mtd/nand/spi/xincun.c @@ -94,6 +94,15 @@ static const struct spinand_info xincun_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&xcsp2aapk_ooblayout, xcsp2aapk_ecc_get_status)), + SPINAND_INFO("XCSP1AAPK", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), + NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xcsp2aapk_ooblayout, xcsp2aapk_ecc_get_status)), }; static const struct spinand_manufacturer_ops xincun_spinand_manuf_ops = { diff --git a/u-boot/drivers/mtd/nand/spi/xtx.c b/u-boot/drivers/mtd/nand/spi/xtx.c index accae71102..f376ecc5ff 100644 --- a/u-boot/drivers/mtd/nand/spi/xtx.c +++ b/u-boot/drivers/mtd/nand/spi/xtx.c @@ -345,6 +345,33 @@ static const struct spinand_info xtx_spinand_table[] = { &update_cache_variants), SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26G01DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x31), + NAND_MEMORG(1, 2048, 64, 64, 1024, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01b_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26G02DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x32), + NAND_MEMORG(1, 2048, 64, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01b_ooblayout, xt26g11c_ecc_get_status)), + SPINAND_INFO("XT26G04DWSIGA", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x33), + NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g01c_ooblayout, xt26g11c_ecc_get_status)), }; static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = { diff --git a/u-boot/drivers/mtd/spi/spi-nor-core.c b/u-boot/drivers/mtd/spi/spi-nor-core.c index 9d69456579..e31c8bd420 100644 --- a/u-boot/drivers/mtd/spi/spi-nor-core.c +++ b/u-boot/drivers/mtd/spi/spi-nor-core.c @@ -2633,6 +2633,7 @@ int spi_nor_scan(struct spi_nor *nor) nor->sector_size = mtd->erasesize; #ifndef CONFIG_SPL_BUILD + printf("JEDEC id bytes: %02x, %02x, %02x\n", info->id[0], info->id[1], info->id[2]); printf("SF: Detected %s with page size ", nor->name); print_size(nor->page_size, ", erase size "); print_size(nor->erase_size, ", total "); diff --git a/u-boot/drivers/mtd/spi/spi-nor-ids.c b/u-boot/drivers/mtd/spi/spi-nor-ids.c index 8be74f340f..b959e922c1 100644 --- a/u-boot/drivers/mtd/spi/spi-nor-ids.c +++ b/u-boot/drivers/mtd/spi/spi-nor-ids.c @@ -184,7 +184,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("gd25lq256d", 0xc86019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | - SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, /* adding these 1.8V QSPI flash parts */ {INFO("gd25lb256", 0xc86719, 0, 64 * 1024, 512, SECT_4K | @@ -537,6 +537,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("PY25Q64HA", 0x852017, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("PY25Q128HA", 0x852018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("PY25Q256HB", 0x852019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("PY25Q128LA", 0x856518, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, #endif #ifdef CONFIG_SPI_FLASH_FMSH /* FUDAN MICRO (Shanghai) Co., Ltd. */ diff --git a/u-boot/drivers/pci/pci-uclass.c b/u-boot/drivers/pci/pci-uclass.c index 86df141d60..50bc324383 100644 --- a/u-boot/drivers/pci/pci-uclass.c +++ b/u-boot/drivers/pci/pci-uclass.c @@ -947,7 +947,6 @@ static int pci_bridge_write_config(struct udevice *bus, pci_dev_t bdf, static int skip_to_next_device(struct udevice *bus, struct udevice **devp) { struct udevice *dev; - int ret = 0; /* * Scan through all the PCI controllers. On x86 there will only be one @@ -959,9 +958,7 @@ static int skip_to_next_device(struct udevice *bus, struct udevice **devp) *devp = dev; return 0; } - ret = uclass_next_device(&bus); - if (ret) - return ret; + uclass_next_device(&bus); } while (bus); return 0; @@ -971,7 +968,6 @@ int pci_find_next_device(struct udevice **devp) { struct udevice *child = *devp; struct udevice *bus = child->parent; - int ret; /* First try all the siblings */ *devp = NULL; @@ -984,9 +980,7 @@ int pci_find_next_device(struct udevice **devp) } /* We ran out of siblings. Try the next bus */ - ret = uclass_next_device(&bus); - if (ret) - return ret; + uclass_next_device(&bus); return bus ? skip_to_next_device(bus, devp) : 0; } @@ -994,12 +988,9 @@ int pci_find_next_device(struct udevice **devp) int pci_find_first_device(struct udevice **devp) { struct udevice *bus; - int ret; *devp = NULL; - ret = uclass_first_device(UCLASS_PCI, &bus); - if (ret) - return ret; + uclass_first_device(UCLASS_PCI, &bus); return skip_to_next_device(bus, devp); } diff --git a/u-boot/drivers/phy/phy-rockchip-naneng-combphy.c b/u-boot/drivers/phy/phy-rockchip-naneng-combphy.c index 5ec79aa85e..05b41b84ba 100644 --- a/u-boot/drivers/phy/phy-rockchip-naneng-combphy.c +++ b/u-boot/drivers/phy/phy-rockchip-naneng-combphy.c @@ -16,6 +16,7 @@ #include #include #include +#include #define BIT_WRITEABLE_SHIFT 16 @@ -63,6 +64,7 @@ struct rockchip_combphy_grfcfg { struct combphy_reg pipe_xpcs_phy_ready; struct combphy_reg u3otg0_port_en; struct combphy_reg u3otg1_port_en; + struct combphy_reg u3otg0_pipe_clk_sel; struct combphy_reg pipe_phy_grf_reset; }; @@ -95,6 +97,20 @@ static int param_write(struct regmap *base, return regmap_write(base, reg->offset, val); } +static u32 rockchip_combphy_is_ready(struct rockchip_combphy_priv *priv) +{ + const struct rockchip_combphy_grfcfg *cfg = priv->cfg->grfcfg; + u32 mask, val; + + mask = GENMASK(cfg->pipe_phy_status.bitend, + cfg->pipe_phy_status.bitstart); + + regmap_read(priv->phy_grf, cfg->pipe_phy_status.offset, &val); + val = (val & mask) >> cfg->pipe_phy_status.bitstart; + + return val; +} + static int rockchip_combphy_pcie_init(struct rockchip_combphy_priv *priv) { int ret = 0; @@ -155,6 +171,53 @@ static int rockchip_combphy_sgmii_init(struct rockchip_combphy_priv *priv) return ret; } +int rockchip_combphy_usb3_uboot_init(void) +{ + struct udevice *udev; + struct rockchip_combphy_priv *priv; + const struct rockchip_combphy_grfcfg *cfg; + u32 val; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_PHY, + DM_GET_DRIVER(rockchip_naneng_combphy), + &udev); + if (ret) { + pr_err("%s: get usb3-phy node failed: %d\n", __func__, ret); + return ret; + } + + priv = dev_get_priv(udev); + priv->mode = PHY_TYPE_USB3; + cfg = priv->cfg->grfcfg; + + rockchip_combphy_usb3_init(priv); + reset_deassert(&priv->phy_rst); + + if (cfg->pipe_phy_grf_reset.enable) + param_write(priv->phy_grf, &cfg->pipe_phy_grf_reset, false); + + if (priv->mode == PHY_TYPE_USB3) { + ret = readx_poll_timeout(rockchip_combphy_is_ready, + priv, val, + val == cfg->pipe_phy_status.enable, + 1000); + if (ret) { + dev_err(priv->dev, "wait phy status ready timeout\n"); + param_write(priv->phy_grf, &cfg->usb_mode_set, false); + if (cfg->u3otg0_pipe_clk_sel.disable) + param_write(priv->phy_grf, &cfg->u3otg0_pipe_clk_sel, false); + return ret; + } + } + + /* Select clk_usb3otg0_pipe for source clk */ + if (cfg->u3otg0_pipe_clk_sel.disable) + param_write(priv->phy_grf, &cfg->u3otg0_pipe_clk_sel, true); + + return ret; +} + static int rockchip_combphy_set_mode(struct rockchip_combphy_priv *priv) { switch (priv->mode) { @@ -333,6 +396,12 @@ static int rk3528_combphy_cfg(struct rockchip_combphy_priv *priv) val |= 0x01; writel(val, priv->mmio + 0x200); + /* Set Rx squelch input filler bandwidth */ + val = readl(priv->mmio + 0x20c); + val &= ~GENMASK(2, 0); + val |= 0x06; + writel(val, priv->mmio + 0x20c); + param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); param_write(priv->phy_grf, &cfg->usb_mode_set, true); @@ -379,6 +448,7 @@ static const struct rockchip_combphy_grfcfg rk3528_combphy_grfcfgs = { .con2_for_pcie = { 0x48008, 15, 0, 0x00, 0x101 }, .con3_for_pcie = { 0x4800c, 15, 0, 0x00, 0x0200 }, /* pipe-grf */ + .u3otg0_pipe_clk_sel = { 0x40044, 7, 7, 0x01, 0x00 }, .u3otg0_port_en = { 0x40044, 15, 0, 0x0181, 0x1100 }, }; @@ -439,6 +509,9 @@ static int rk3562_combphy_cfg(struct rockchip_combphy_priv *priv) /* Set PLL KVCO to min and set PLL charge pump current to max */ writel(0xf0, priv->mmio + (0xa << 2)); + /* Set Rx squelch input filler bandwidth */ + writel(0x0e, priv->mmio + (0x14 << 2)); + param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); param_write(priv->phy_grf, &cfg->pipe_txelec_sel, false); @@ -563,8 +636,8 @@ static int rk3568_combphy_cfg(struct rockchip_combphy_priv *priv) /* Set PLL KVCO to min and set PLL charge pump current to max */ writel(0xf0, priv->mmio + (0xa << 2)); - /*Set Rx squelch input filler badwidth*/ - writel(0x0d, priv->mmio + (0x14 << 2)); + /* Set Rx squelch input filler bandwidth */ + writel(0x0e, priv->mmio + (0x14 << 2)); param_write(priv->phy_grf, &cfg->pipe_sel_usb, true); param_write(priv->phy_grf, &cfg->pipe_txcomp_sel, false); diff --git a/u-boot/drivers/phy/phy-rockchip-usbdp.c b/u-boot/drivers/phy/phy-rockchip-usbdp.c index c4ad1de347..9aeac3261b 100644 --- a/u-boot/drivers/phy/phy-rockchip-usbdp.c +++ b/u-boot/drivers/phy/phy-rockchip-usbdp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -23,7 +24,62 @@ #include -#define BIT_WRITEABLE_SHIFT 16 +/* RK3588 USBDP PHY Register Definitions */ + +#define UDPHY_PCS 0x4000 +#define UDPHY_PMA 0x8000 + +/* VO GRF Registers */ +#define DP_SINK_HPD_CFG BIT(11) +#define DP_SINK_HPD_SEL BIT(10) +#define DP_AUX_DIN_SEL BIT(9) +#define DP_AUX_DOUT_SEL BIT(8) +#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n)) +#define DP_LANE_SEL_ALL GENMASK(7, 0) + +/* PMA CMN Registers */ +#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */ +#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4) +#define CMN_DP_LANE_EN_N(n) BIT(n) +#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4) +#define CMN_DP_LANE_EN_ALL GENMASK(3, 0) + +#define CMN_DP_LINK_OFFSET 0x28c /*cmn_reg00A3 */ +#define CMN_DP_TX_LINK_BW GENMASK(6, 5) +#define CMN_DP_TX_LANE_SWAP_EN BIT(2) + +#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */ +#define CMN_ROPLL_SSC_EN BIT(1) +#define CMN_LCPLL_SSC_EN BIT(0) + +#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */ +#define CMN_ANA_LCPLL_LOCK_DONE BIT(7) +#define CMN_ANA_LCPLL_AFC_DONE BIT(6) + +#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */ +#define CMN_ANA_ROPLL_LOCK_DONE BIT(1) +#define CMN_ANA_ROPLL_AFC_DONE BIT(0) + +#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */ +#define CMN_DP_INIT_RSTN BIT(3) +#define CMN_DP_CMN_RSTN BIT(2) +#define CMN_CDR_WTCHDG_EN BIT(1) +#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0) + +#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */ +#define LN_ANA_TX_SER_TXCLK_INV BIT(1) + +#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */ +#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0) + +#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */ +#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0) + +#define BIT_WRITEABLE_SHIFT 16 +#define PHY_AUX_DP_DATA_POL_NORMAL 0 +#define PHY_AUX_DP_DATA_POL_INVERT 1 +#define PHY_LANE_MUX_USB 0 +#define PHY_LANE_MUX_DP 1 enum { DP_BW_RBR, @@ -77,6 +133,11 @@ struct udphy_grf_cfg { struct udphy_grf_reg rx_lfps; }; +struct udphy_vogrf_cfg { + /* vo-grf */ + u32 dp_lane_reg; +}; + struct dp_tx_drv_ctrl { u32 trsv_reg0204; u32 trsv_reg0205; @@ -92,14 +153,8 @@ struct rockchip_udphy_cfg { int num_rsts; struct udphy_grf_cfg grfcfg; + struct udphy_vogrf_cfg vogrfcfg[2]; const struct dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4]; - int (*combophy_init)(struct rockchip_udphy *udphy); - int (*dp_phy_set_rate)(struct rockchip_udphy *udphy, - struct phy_configure_opts_dp *dp); - int (*dp_phy_set_voltages)(struct rockchip_udphy *udphy, - struct phy_configure_opts_dp *dp); - int (*dplane_enable)(struct rockchip_udphy *udphy, int dp_lanes); - int (*dplane_select)(struct rockchip_udphy *udphy); }; struct rockchip_udphy { @@ -223,7 +278,7 @@ static const struct dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = { }, }; -static const struct reg_sequence rk3588_udphy_24m_refclk_cfg[] = { +static const struct reg_sequence udphy_24m_refclk_cfg[] = { {0x0090, 0x68}, {0x0094, 0x68}, {0x0128, 0x24}, {0x012c, 0x44}, {0x0130, 0x3f}, {0x0134, 0x44}, @@ -262,7 +317,7 @@ static const struct reg_sequence rk3588_udphy_24m_refclk_cfg[] = { {0x1a5c, 0xe0}, {0x1a64, 0xa8} }; -static const struct reg_sequence rk3588_udphy_init_sequence[] = { +static const struct reg_sequence udphy_init_sequence[] = { {0x0104, 0x44}, {0x0234, 0xE8}, {0x0248, 0x44}, {0x028C, 0x18}, {0x081C, 0xE5}, {0x0878, 0x00}, @@ -452,9 +507,26 @@ static void udphy_usb_bvalid_enable(struct rockchip_udphy *udphy, u8 enable) static int udphy_dplane_select(struct rockchip_udphy *udphy) { const struct rockchip_udphy_cfg *cfg = udphy->cfgs; + u32 value = 0; - if (cfg->dplane_select) - return cfg->dplane_select(udphy); + switch (udphy->mode) { + case UDPHY_MODE_DP: + value |= 2 << udphy->dp_lane_sel[2] * 2; + value |= 3 << udphy->dp_lane_sel[3] * 2; + case UDPHY_MODE_DP_USB: + value |= 0 << udphy->dp_lane_sel[0] * 2; + value |= 1 << udphy->dp_lane_sel[1] * 2; + break; + case UDPHY_MODE_USB: + break; + default: + break; + } + + regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg, + ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) | + FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | + FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); return 0; } @@ -482,18 +554,25 @@ static int udphy_dplane_get(struct rockchip_udphy *udphy) static int udphy_dplane_enable(struct rockchip_udphy *udphy, int dp_lanes) { - const struct rockchip_udphy_cfg *cfg = udphy->cfgs; - int ret = 0; + int i; + u32 val = 0; - if (cfg->dplane_enable) - ret = cfg->dplane_enable(udphy, dp_lanes); + for (i = 0; i < dp_lanes; i++) + val |= BIT(udphy->dp_lane_sel[i]); - return ret; + regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, + FIELD_PREP(CMN_DP_LANE_EN_ALL, val)); + + if (!dp_lanes) + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, + CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); + + return 0; } __maybe_unused -static int upphy_set_typec_default_mapping(struct rockchip_udphy *udphy) +static int udphy_set_typec_default_mapping(struct rockchip_udphy *udphy) { if (udphy->flip) { udphy->dp_lane_sel[0] = 0; @@ -524,16 +603,137 @@ static int upphy_set_typec_default_mapping(struct rockchip_udphy *udphy) return 0; } -static int udphy_setup(struct rockchip_udphy *udphy) +static int udphy_refclk_set(struct rockchip_udphy *udphy) +{ + int ret; + + /* configure phy reference clock */ + ret = __regmap_multi_reg_write(udphy->pma_regmap, udphy_24m_refclk_cfg, + ARRAY_SIZE(udphy_24m_refclk_cfg)); + if (ret) + return ret; + + return 0; +} + +static int udphy_status_check(struct rockchip_udphy *udphy) +{ + unsigned int val; + int ret; + + /* LCPLL check */ + if (udphy->mode & UDPHY_MODE_USB) { + ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, + val, (val & CMN_ANA_LCPLL_AFC_DONE) && + (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100); + if (ret) { + dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); + return ret; + } + } + + if (udphy->mode & UDPHY_MODE_USB) { + if (!udphy->flip) { + ret = regmap_read_poll_timeout(udphy->pma_regmap, + TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, + val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, + 200, 100); + if (ret) + dev_notice(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); + } else { + ret = regmap_read_poll_timeout(udphy->pma_regmap, + TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, + val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, + 200, 100); + if (ret) + dev_notice(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); + } + } + + return 0; +} + +static int udphy_init(struct rockchip_udphy *udphy) { const struct rockchip_udphy_cfg *cfg = udphy->cfgs; + int ret; + + /* enable rx lfps for usb */ + if (udphy->mode & UDPHY_MODE_USB) + grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); + + /* Step 1: power on pma and deassert apb rstn */ + grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); + + udphy_reset_deassert(udphy, "pma_apb"); + udphy_reset_deassert(udphy, "pcs_apb"); + + /* Step 2: set init sequence and phy refclk */ + ret = __regmap_multi_reg_write(udphy->pma_regmap, udphy_init_sequence, + ARRAY_SIZE(udphy_init_sequence)); + if (ret) { + dev_err(udphy->dev, "init sequence set error %d\n", ret); + goto assert_apb; + } + + ret = udphy_refclk_set(udphy); + if (ret) { + dev_err(udphy->dev, "refclk set error %d\n", ret); + goto assert_apb; + } + + /* Step 3: configure lane mux */ + regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, + CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL, + FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | + FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | + FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | + FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | + FIELD_PREP(CMN_DP_LANE_EN_ALL, 0)); + + /* Step 4: deassert init rstn and wait for 200ns from datasheet */ + if (udphy->mode & UDPHY_MODE_USB) + udphy_reset_deassert(udphy, "init"); + + if (udphy->mode & UDPHY_MODE_DP) { + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, + CMN_DP_INIT_RSTN, + FIELD_PREP(CMN_DP_INIT_RSTN, 0x1)); + } + + udelay(1); + + /* Step 5: deassert cmn/lane rstn */ + if (udphy->mode & UDPHY_MODE_USB) { + udphy_reset_deassert(udphy, "cmn"); + udphy_reset_deassert(udphy, "lane"); + } + + /* Step 6: wait for lock done of pll */ + ret = udphy_status_check(udphy); + if (ret) + goto assert_phy; + + return 0; + +assert_phy: + udphy_reset_assert(udphy, "init"); + udphy_reset_assert(udphy, "cmn"); + udphy_reset_assert(udphy, "lane"); + +assert_apb: + udphy_reset_assert(udphy, "pma_apb"); + udphy_reset_assert(udphy, "pcs_apb"); + return ret; +} + +static int udphy_setup(struct rockchip_udphy *udphy) +{ int ret = 0; - if (cfg->combophy_init) { - ret = cfg->combophy_init(udphy); - if (ret) - dev_err(udphy->dev, "failed to init combophy\n"); - } + ret = udphy_init(udphy); + if (ret) + dev_err(udphy->dev, "failed to init combophy\n"); return ret; } @@ -551,11 +751,10 @@ static int udphy_disable(struct rockchip_udphy *udphy) static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct udevice *dev) { - const struct device_node *np = ofnode_to_np(dev->node); - struct property *prop; + const void *prop; int ret, i, len, num_lanes; - prop = of_find_property(np, "rockchip,dp-lane-mux", &len); + prop = dev_read_prop(dev, "rockchip,dp-lane-mux", &len); if (!prop) { dev_dbg(dev, "failed to find dp lane mux, following dp alt mode\n"); udphy->mode = UDPHY_MODE_USB; @@ -569,7 +768,7 @@ static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct udevic return -EINVAL; } - ret = of_read_u32_array(np, "rockchip,dp-lane-mux", udphy->dp_lane_sel, num_lanes); + ret = dev_read_u32_array(dev, "rockchip,dp-lane-mux", udphy->dp_lane_sel, num_lanes); if (ret) { dev_err(dev, "get dp lane mux failed\n"); return -EINVAL; @@ -813,20 +1012,115 @@ static int rockchip_dpphy_verify_config(struct rockchip_udphy *udphy, return 0; } +static int dp_phy_set_rate(struct rockchip_udphy *udphy, + struct phy_configure_opts_dp *dp) +{ + u32 val; + int ret; + + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, + CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); + + switch (dp->link_rate) { + case 1620: + udphy->bw = DP_BW_RBR; + break; + case 2700: + udphy->bw = DP_BW_HBR; + break; + case 5400: + udphy->bw = DP_BW_HBR2; + break; + case 8100: + udphy->bw = DP_BW_HBR3; + break; + default: + return -EINVAL; + } + + regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, + FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); + regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, + FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); + regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, + FIELD_PREP(CMN_DP_CMN_RSTN, 0x1)); + + ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, + FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) && + FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val), + 0, 1000); + if (ret) { + printf("ROPLL is not lock\n"); + return ret; + } + + return 0; +} + +static void dp_phy_set_voltage(struct rockchip_udphy *udphy, u8 bw, + u32 voltage, u32 pre, u32 lane) +{ + u32 offset = 0x800 * lane; + u32 val; + const struct rockchip_udphy_cfg *cfg = udphy->cfgs; + const struct dp_tx_drv_ctrl (*dp_ctrl)[4]; + + dp_ctrl = cfg->dp_tx_ctrl_cfg[bw]; + val = dp_ctrl[voltage][pre].trsv_reg0204; + regmap_write(udphy->pma_regmap, 0x0810 + offset, val); + + val = dp_ctrl[voltage][pre].trsv_reg0205; + regmap_write(udphy->pma_regmap, 0x0814 + offset, val); + + val = dp_ctrl[voltage][pre].trsv_reg0206; + regmap_write(udphy->pma_regmap, 0x0818 + offset, val); + + val = dp_ctrl[voltage][pre].trsv_reg0207; + regmap_write(udphy->pma_regmap, 0x081c + offset, val); +} + +static int dp_phy_set_voltages(struct rockchip_udphy *udphy, + struct phy_configure_opts_dp *dp) +{ + u32 i, lane; + + for (i = 0; i < dp->lanes; i++) { + lane = udphy->dp_lane_sel[i]; + switch (dp->link_rate) { + case 1620: + case 2700: + regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), + LN_ANA_TX_SER_TXCLK_INV, + FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, + udphy->lane_mux_sel[lane])); + break; + case 5400: + case 8100: + regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), + LN_ANA_TX_SER_TXCLK_INV, + FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0)); + break; + } + + dp_phy_set_voltage(udphy, udphy->bw, dp->voltage[i], dp->pre[i], lane); + } + + return 0; +} + static int rockchip_dpphy_configure(struct phy *phy, union phy_configure_opts *opts) { struct udevice *parent = phy->dev->parent; struct rockchip_udphy *udphy = dev_get_priv(parent); - const struct rockchip_udphy_cfg *cfg = udphy->cfgs; int ret; ret = rockchip_dpphy_verify_config(udphy, &opts->dp); if (ret) return ret; - if (opts->dp.set_rate && cfg->dp_phy_set_rate) { - ret = cfg->dp_phy_set_rate(udphy, &opts->dp); + if (opts->dp.set_rate) { + ret = dp_phy_set_rate(udphy, &opts->dp); if (ret) { printf("%s: rockchip_hdptx_phy_set_rate failed\n", udphy->dev->name); @@ -834,8 +1128,8 @@ static int rockchip_dpphy_configure(struct phy *phy, } } - if (opts->dp.set_voltages && cfg->dp_phy_set_voltages) { - ret = cfg->dp_phy_set_voltages(udphy, &opts->dp); + if (opts->dp.set_voltages) { + ret = dp_phy_set_voltages(udphy, &opts->dp); if (ret) { printf("%s: rockchip_dp_phy_set_voltages failed\n", udphy->dev->name); @@ -887,6 +1181,7 @@ int rockchip_u3phy_uboot_init(void) { struct udevice *udev; struct rockchip_udphy *udphy; + unsigned int val; int ret; ret = uclass_get_device_by_driver(UCLASS_PHY, @@ -900,23 +1195,45 @@ int rockchip_u3phy_uboot_init(void) /* DP only or high-speed, disable U3 port */ udphy = dev_get_priv(udev->parent); if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) { - udphy_u3_port_disable(udphy, true); - return 0; + pr_err("%s: udphy mode not support usb3\n", __func__); + goto disable_u3; } - return udphy_power_on(udphy, UDPHY_MODE_USB); + udphy->flip = false; + udphy_set_typec_default_mapping(udphy); + + ret = udphy_power_on(udphy, UDPHY_MODE_USB); + if (ret) { + pr_err("%s: udphy power on failed: %d\n", __func__, ret); + goto disable_u3; + } + + ret = regmap_read_poll_timeout(udphy->pma_regmap, + TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, + val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, + 200, 100); + if (ret) { + pr_err("%s: udphy rx cdr lock timeout\n", __func__); + goto disable_u3; + } + + return 0; + +disable_u3: + udphy_u3_port_disable(udphy, true); + + return -EOPNOTSUPP; } static int rockchip_udphy_probe(struct udevice *dev) { - const struct device_node *np = ofnode_to_np(dev->node); struct rockchip_udphy *udphy = dev_get_priv(dev); const struct rockchip_udphy_cfg *phy_cfgs; int id, ret; udphy->dev = dev; - id = of_alias_get_id(np, "usbdp"); + id = of_alias_get_id(ofnode_to_np(dev->node), "usbdp"); if (id < 0) id = 0; udphy->id = id; @@ -980,270 +1297,6 @@ static int rockchip_udphy_bind(struct udevice *parent) return 0; } -static int rk3588_udphy_refclk_set(struct rockchip_udphy *udphy) -{ - int ret; - - /* configure phy reference clock */ - ret = __regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_24m_refclk_cfg, - ARRAY_SIZE(rk3588_udphy_24m_refclk_cfg)); - if (ret) - return ret; - - return 0; -} - -static int rk3588_udphy_status_check(struct rockchip_udphy *udphy) -{ - unsigned int val; - int ret; - - /* LCPLL check */ - if (udphy->mode & UDPHY_MODE_USB) { - ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, - val, (val & CMN_ANA_LCPLL_AFC_DONE) && - (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100); - if (ret) { - dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); - return ret; - } - } - - if (udphy->mode & UDPHY_MODE_USB) { - if (!udphy->flip) { - ret = regmap_read_poll_timeout(udphy->pma_regmap, - TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, - val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, - 200, 100); - if (ret) - dev_notice(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); - } else { - ret = regmap_read_poll_timeout(udphy->pma_regmap, - TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, - val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, - 200, 100); - if (ret) - dev_notice(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); - } - } - - return 0; -} - -static int rk3588_udphy_init(struct rockchip_udphy *udphy) -{ - const struct rockchip_udphy_cfg *cfg = udphy->cfgs; - int ret; - - /* enable rx lfps for usb */ - if (udphy->mode & UDPHY_MODE_USB) - grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); - - /* Step 1: power on pma and deassert apb rstn */ - grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); - - udphy_reset_deassert(udphy, "pma_apb"); - udphy_reset_deassert(udphy, "pcs_apb"); - - /* Step 2: set init sequence and phy refclk */ - ret = __regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_init_sequence, - ARRAY_SIZE(rk3588_udphy_init_sequence)); - if (ret) { - dev_err(udphy->dev, "init sequence set error %d\n", ret); - goto assert_apb; - } - - ret = rk3588_udphy_refclk_set(udphy); - if (ret) { - dev_err(udphy->dev, "refclk set error %d\n", ret); - goto assert_apb; - } - - /* Step 3: configure lane mux */ - regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, - CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL, - FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | - FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | - FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | - FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | - FIELD_PREP(CMN_DP_LANE_EN_ALL, 0)); - - /* Step 4: deassert init rstn and wait for 200ns from datasheet */ - if (udphy->mode & UDPHY_MODE_USB) - udphy_reset_deassert(udphy, "init"); - - if (udphy->mode & UDPHY_MODE_DP) { - regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, - CMN_DP_INIT_RSTN, - FIELD_PREP(CMN_DP_INIT_RSTN, 0x1)); - } - - udelay(1); - - /* Step 5: deassert cmn/lane rstn */ - if (udphy->mode & UDPHY_MODE_USB) { - udphy_reset_deassert(udphy, "cmn"); - udphy_reset_deassert(udphy, "lane"); - } - - /* Step 6: wait for lock done of pll */ - ret = rk3588_udphy_status_check(udphy); - if (ret) - goto assert_phy; - - return 0; - -assert_phy: - udphy_reset_assert(udphy, "init"); - udphy_reset_assert(udphy, "cmn"); - udphy_reset_assert(udphy, "lane"); - -assert_apb: - udphy_reset_assert(udphy, "pma_apb"); - udphy_reset_assert(udphy, "pcs_apb"); - return ret; -} - -static int rk3588_udphy_dplane_enable(struct rockchip_udphy *udphy, int dp_lanes) -{ - int i; - u32 val = 0; - - for (i = 0; i < dp_lanes; i++) - val |= BIT(udphy->dp_lane_sel[i]); - - regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, - FIELD_PREP(CMN_DP_LANE_EN_ALL, val)); - - if (!dp_lanes) - regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, - CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); - - return 0; -} - -static int rk3588_udphy_dplane_select(struct rockchip_udphy *udphy) -{ - u32 value = 0; - - switch (udphy->mode) { - case UDPHY_MODE_DP: - value |= 2 << udphy->dp_lane_sel[2] * 2; - value |= 3 << udphy->dp_lane_sel[3] * 2; - case UDPHY_MODE_DP_USB: - value |= 0 << udphy->dp_lane_sel[0] * 2; - value |= 1 << udphy->dp_lane_sel[1] * 2; - break; - case UDPHY_MODE_USB: - break; - default: - break; - } - - regmap_write(udphy->vogrf, udphy->id ? RK3588_GRF_VO0_CON2 : RK3588_GRF_VO0_CON0, - ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) | - FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | - FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); - - return 0; -} - -static int rk3588_dp_phy_set_rate(struct rockchip_udphy *udphy, - struct phy_configure_opts_dp *dp) -{ - u32 val; - int ret; - - regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, - CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); - - switch (dp->link_rate) { - case 1620: - udphy->bw = DP_BW_RBR; - break; - case 2700: - udphy->bw = DP_BW_HBR; - break; - case 5400: - udphy->bw = DP_BW_HBR2; - break; - case 8100: - udphy->bw = DP_BW_HBR3; - break; - default: - return -EINVAL; - } - - regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, - FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); - regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, - FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); - regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, - FIELD_PREP(CMN_DP_CMN_RSTN, 0x1)); - - ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, - FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) && - FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val), - 0, 1000); - if (ret) { - printf("ROPLL is not lock\n"); - return ret; - } - - return 0; -} - -static void rk3588_dp_phy_set_voltage(struct rockchip_udphy *udphy, u8 bw, - u32 voltage, u32 pre, u32 lane) -{ - u32 offset = 0x800 * lane; - u32 val; - const struct rockchip_udphy_cfg *cfg = udphy->cfgs; - const struct dp_tx_drv_ctrl (*dp_ctrl)[4]; - - dp_ctrl = cfg->dp_tx_ctrl_cfg[bw]; - val = dp_ctrl[voltage][pre].trsv_reg0204; - regmap_write(udphy->pma_regmap, 0x0810 + offset, val); - - val = dp_ctrl[voltage][pre].trsv_reg0205; - regmap_write(udphy->pma_regmap, 0x0814 + offset, val); - - val = dp_ctrl[voltage][pre].trsv_reg0206; - regmap_write(udphy->pma_regmap, 0x0818 + offset, val); - - val = dp_ctrl[voltage][pre].trsv_reg0207; - regmap_write(udphy->pma_regmap, 0x081c + offset, val); -} - -static int rk3588_dp_phy_set_voltages(struct rockchip_udphy *udphy, - struct phy_configure_opts_dp *dp) -{ - u32 i, lane; - - for (i = 0; i < dp->lanes; i++) { - lane = udphy->dp_lane_sel[i]; - switch (dp->link_rate) { - case 1620: - case 2700: - regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), - LN_ANA_TX_SER_TXCLK_INV, - FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, - udphy->lane_mux_sel[lane])); - break; - case 5400: - case 8100: - regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), - LN_ANA_TX_SER_TXCLK_INV, - FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0)); - break; - } - - rk3588_dp_phy_set_voltage(udphy, udphy->bw, dp->voltage[i], dp->pre[i], lane); - } - - return 0; -} - static int rockchip_dpphy_probe(struct udevice *dev) { struct rockchip_udphy *udphy = dev_get_priv(dev->parent); @@ -1287,17 +1340,20 @@ static const struct rockchip_udphy_cfg rk3588_udphy_cfgs = { .low_pwrn = { 0x0004, 13, 13, 0, 1 }, .rx_lfps = { 0x0004, 14, 14, 0, 1 }, }, + .vogrfcfg = { + { + .dp_lane_reg = 0x0000, + }, + { + .dp_lane_reg = 0x0008, + }, + }, .dp_tx_ctrl_cfg = { rk3588_dp_tx_drv_ctrl_rbr_hbr, rk3588_dp_tx_drv_ctrl_rbr_hbr, rk3588_dp_tx_drv_ctrl_hbr2, rk3588_dp_tx_drv_ctrl_hbr3, }, - .combophy_init = rk3588_udphy_init, - .dp_phy_set_rate = rk3588_dp_phy_set_rate, - .dp_phy_set_voltages = rk3588_dp_phy_set_voltages, - .dplane_enable = rk3588_udphy_dplane_enable, - .dplane_select = rk3588_udphy_dplane_select, }; static const struct udevice_id rockchip_udphy_dt_match[] = { diff --git a/u-boot/drivers/pinctrl/Kconfig b/u-boot/drivers/pinctrl/Kconfig index 4899c71332..151297f3be 100644 --- a/u-boot/drivers/pinctrl/Kconfig +++ b/u-boot/drivers/pinctrl/Kconfig @@ -59,6 +59,22 @@ config PINCONF This option enables pin configuration through the generic pinctrl framework. +config PINCONF_RECURSIVE + bool "Support recursive binding for pin configuration nodes" + depends on PINCTRL_FULL + default n if ARCH_STM32MP + default y + help + In the Linux pinctrl binding, the pin configuration nodes need not be + direct children of the pin controller device (may be grandchildren for + example). It is define is each individual pin controller device. + Say Y here if you want to keep this behavior with the pinconfig + u-class: all sub are recursivelly bounded. + If the option is disabled, this behavior is deactivated and only + the direct children of pin controller will be assumed as pin + configuration; you can save memory footprint when this feature is + no needed. + config SPL_PINCTRL bool "Support pin controllers in SPL" depends on SPL && SPL_DM @@ -104,6 +120,15 @@ config SPL_PINCONF This option is an SPL-variant of the PINCONF option. See the help of PINCONF for details. +config SPL_PINCONF_RECURSIVE + bool "Support recursive binding for pin configuration nodes in SPL" + depends on SPL_PINCTRL_FULL + default n if ARCH_STM32MP + default y + help + This option is an SPL-variant of the PINCONF_RECURSIVE option. + See the help of PINCONF_RECURSIVE for details. + if PINCTRL || SPL_PINCTRL config PINCTRL_AR933X diff --git a/u-boot/drivers/pinctrl/pinctrl-generic.c b/u-boot/drivers/pinctrl/pinctrl-generic.c index a204035a9d..f3d7d5b8e3 100644 --- a/u-boot/drivers/pinctrl/pinctrl-generic.c +++ b/u-boot/drivers/pinctrl/pinctrl-generic.c @@ -227,6 +227,13 @@ static int pinconf_enable_setting(struct udevice *dev, bool is_group, } #endif +enum pinmux_subnode_type { + PST_NONE = 0, + PST_PIN, + PST_GROUP, + PST_PINMUX, +}; + /** * pinctrl_generic_set_state_one() - set state for a certain pin/group * Apply all pin multiplexing and pin configurations specified by @config @@ -234,13 +241,15 @@ static int pinconf_enable_setting(struct udevice *dev, bool is_group, * * @dev: pin controller device * @config: pseudo device pointing to config node - * @is_group: target of operation (true: pin group, false: pin) - * @selector: pin selector or group selector, depending on @is_group + * @subnode_type: target of operation (pin, group, or pin specified by a pinmux + * group) + * @selector: pin selector or group selector, depending on @subnode_type * @return: 0 on success, or negative error code on failure */ static int pinctrl_generic_set_state_one(struct udevice *dev, struct udevice *config, - bool is_group, unsigned selector) + enum pinmux_subnode_type subnode_type, + unsigned selector) { const char *propname; const void *value; @@ -248,17 +257,22 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, int len, func_selector, param, ret; u32 arg, default_val; + assert(subnode_type != PST_NONE); + dev_for_each_property(property, config) { value = dev_read_prop_by_prop(&property, &propname, &len); if (!value) return -EINVAL; - if (!strcmp(propname, "function")) { + /* pinmux subnodes already have their muxing set */ + if (subnode_type != PST_PINMUX && + !strcmp(propname, "function")) { func_selector = pinmux_func_name_to_selector(dev, value); if (func_selector < 0) return func_selector; - ret = pinmux_enable_setting(dev, is_group, + ret = pinmux_enable_setting(dev, + subnode_type == PST_GROUP, selector, func_selector); } else { @@ -272,7 +286,8 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, else arg = default_val; - ret = pinconf_enable_setting(dev, is_group, + ret = pinconf_enable_setting(dev, + subnode_type == PST_GROUP, selector, param, arg); } @@ -283,6 +298,41 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, return 0; } +/** + * pinctrl_generic_get_subnode_type() - determine whether there is a valid + * pins, groups, or pinmux property in the config node + * + * @dev: pin controller device + * @config: pseudo device pointing to config node + * @count: number of specifiers contained within the property + * @return: the type of the subnode, or PST_NONE + */ +static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev, + struct udevice *config, + int *count) +{ + const struct pinctrl_ops *ops = pinctrl_get_ops(dev); + + *count = dev_read_string_count(config, "pins"); + if (*count >= 0) + return PST_PIN; + + *count = dev_read_string_count(config, "groups"); + if (*count >= 0) + return PST_GROUP; + + if (ops->pinmux_property_set) { + *count = dev_read_size(config, "pinmux"); + if (*count >= 0 && !(*count % sizeof(u32))) { + *count /= sizeof(u32); + return PST_PINMUX; + } + } + + *count = 0; + return PST_NONE; +} + /** * pinctrl_generic_set_state_subnode() - apply all settings in config node * @@ -293,38 +343,55 @@ static int pinctrl_generic_set_state_one(struct udevice *dev, static int pinctrl_generic_set_state_subnode(struct udevice *dev, struct udevice *config) { - const char *subnode_target_type = "pins"; - bool is_group = false; + enum pinmux_subnode_type subnode_type; const char *name; - int strings_count, selector, i, ret; + int count, selector, i, ret, scratch; + const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */ - strings_count = dev_read_string_count(config, subnode_target_type); - if (strings_count < 0) { - subnode_target_type = "groups"; - is_group = true; - strings_count = dev_read_string_count(config, - subnode_target_type); - if (strings_count < 0) { + subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count); + + debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name, + count); + + if (subnode_type == PST_PINMUX) { + pinmux_groups = dev_read_prop(config, "pinmux", &scratch); + if (!pinmux_groups) + return -EINVAL; + } + + for (i = 0; i < count; i++) { + switch (subnode_type) { + case PST_PIN: + ret = dev_read_string_index(config, "pins", i, &name); + if (ret) + return ret; + selector = pinctrl_pin_name_to_selector(dev, name); + break; + case PST_GROUP: + ret = dev_read_string_index(config, "groups", i, &name); + if (ret) + return ret; + selector = pinctrl_group_name_to_selector(dev, name); + break; + case PST_PINMUX: { + const struct pinctrl_ops *ops = pinctrl_get_ops(dev); + u32 pinmux_group = fdt32_to_cpu(pinmux_groups[i]); + + /* Checked for in pinctrl_generic_get_subnode_type */ + selector = ops->pinmux_property_set(dev, pinmux_group); + break; + } + case PST_NONE: + default: /* skip this node; may contain config child nodes */ return 0; } - } - for (i = 0; i < strings_count; i++) { - ret = dev_read_string_index(config, subnode_target_type, i, - &name); - if (ret) - return ret; - - if (is_group) - selector = pinctrl_group_name_to_selector(dev, name); - else - selector = pinctrl_pin_name_to_selector(dev, name); if (selector < 0) return selector; - ret = pinctrl_generic_set_state_one(dev, config, - is_group, selector); + ret = pinctrl_generic_set_state_one(dev, config, subnode_type, + selector); if (ret) return ret; } diff --git a/u-boot/drivers/pinctrl/pinctrl-uclass.c b/u-boot/drivers/pinctrl/pinctrl-uclass.c index 04776f7395..a4bab4c993 100644 --- a/u-boot/drivers/pinctrl/pinctrl-uclass.c +++ b/u-boot/drivers/pinctrl/pinctrl-uclass.c @@ -79,25 +79,31 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename) */ state = simple_strtoul(statename, &end, 10); if (*end) - return -EINVAL; + return -ENOSYS; } snprintf(propname, sizeof(propname), "pinctrl-%d", state); list = dev_read_prop(dev, propname, &size); if (!list) - return -EINVAL; + return -ENOSYS; size /= sizeof(*list); for (i = 0; i < size; i++) { phandle = fdt32_to_cpu(*list++); ret = uclass_get_device_by_phandle_id(UCLASS_PINCONFIG, phandle, &config); - if (ret) - return ret; + if (ret) { + dev_warn(dev, "%s: uclass_get_device_by_phandle_id: err=%d\n", + __func__, ret); + continue; + } ret = pinctrl_config_one(config); - if (ret) - return ret; + if (ret) { + dev_warn(dev, "%s: pinctrl_config_one: err=%d\n", + __func__, ret); + continue; + } } return 0; @@ -117,6 +123,9 @@ static int pinconfig_post_bind(struct udevice *dev) ofnode node; int ret; + if (!dev_of_valid(dev)) + return 0; + dev_for_each_subnode(node, dev) { if (pre_reloc_only && !ofnode_pre_reloc(node)) @@ -146,7 +155,9 @@ static int pinconfig_post_bind(struct udevice *dev) UCLASS_DRIVER(pinconfig) = { .id = UCLASS_PINCONFIG, +#if CONFIG_IS_ENABLED(PINCONF_RECURSIVE) .post_bind = pinconfig_post_bind, +#endif .name = "pinconfig", }; @@ -156,17 +167,115 @@ U_BOOT_DRIVER(pinconfig_generic) = { }; #else -static int pinctrl_select_state_full(struct udevice *dev, const char *statename) -{ - return -ENODEV; -} - static int pinconfig_post_bind(struct udevice *dev) { return 0; } + +static int pinctrl_select_state_full(struct udevice *dev, const char *statename) +{ + return 0; +} #endif +static int +pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset, + struct udevice **pctldev, + unsigned int *pin_selector) +{ + struct ofnode_phandle_args args; + unsigned gpio_offset, pfc_base, pfc_pins; + int ret; + + ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3, + 0, &args); + if (ret) { + dev_dbg(dev, "%s: dev_read_phandle_with_args: err=%d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_ofnode(UCLASS_PINCTRL, + args.node, pctldev); + if (ret) { + dev_dbg(dev, + "%s: uclass_get_device_by_of_offset failed: err=%d\n", + __func__, ret); + return ret; + } + + gpio_offset = args.args[0]; + pfc_base = args.args[1]; + pfc_pins = args.args[2]; + + if (offset < gpio_offset || offset > gpio_offset + pfc_pins) { + dev_dbg(dev, + "%s: GPIO can not be mapped to pincontrol pin\n", + __func__); + return -EINVAL; + } + + offset -= gpio_offset; + offset += pfc_base; + *pin_selector = offset; + + return 0; +} + +/** + * pinctrl_gpio_request() - request a single pin to be used as GPIO + * + * @dev: GPIO peripheral device + * @offset: the GPIO pin offset from the GPIO controller + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +{ + const struct pinctrl_ops *ops; + struct udevice *pctldev; + unsigned int pin_selector; + int ret; + + ret = pinctrl_gpio_get_pinctrl_and_offset(dev, offset, + &pctldev, &pin_selector); + if (ret) + return ret; + + ops = pinctrl_get_ops(pctldev); + assert(ops); + if (!ops->gpio_request_enable) + return -ENOSYS; + + return ops->gpio_request_enable(pctldev, pin_selector); +} + +/** + * pinctrl_gpio_free() - free a single pin used as GPIO + * + * @dev: GPIO peripheral device + * @offset: the GPIO pin offset from the GPIO controller + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_gpio_free(struct udevice *dev, unsigned offset) +{ + const struct pinctrl_ops *ops; + struct udevice *pctldev; + unsigned int pin_selector; + int ret; + + ret = pinctrl_gpio_get_pinctrl_and_offset(dev, offset, + &pctldev, &pin_selector); + if (ret) + return ret; + + ops = pinctrl_get_ops(pctldev); + assert(ops); + if (!ops->gpio_disable_free) + return -ENOSYS; + + return ops->gpio_disable_free(pctldev, pin_selector); +} + /** * pinctrl_select_state_simple() - simple implementation of pinctrl_select_state * @@ -202,14 +311,20 @@ static int pinctrl_select_state_simple(struct udevice *dev) int pinctrl_select_state(struct udevice *dev, const char *statename) { + /* + * Some device which is logical like mmc.blk, do not have + * a valid ofnode. + */ + if (!ofnode_valid(dev->node)) + return 0; /* * Try full-implemented pinctrl first. * If it fails or is not implemented, try simple one. */ - if (pinctrl_select_state_full(dev, statename)) - return pinctrl_select_state_simple(dev); + if (CONFIG_IS_ENABLED(PINCTRL_FULL)) + return pinctrl_select_state_full(dev, statename); - return 0; + return pinctrl_select_state_simple(dev); } int pinctrl_request(struct udevice *dev, int func, int flags) @@ -257,6 +372,30 @@ int pinctrl_get_pins_count(struct udevice *dev) return ops->get_pins_count(dev); } +int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, + int size) +{ + struct pinctrl_ops *ops = pinctrl_get_ops(dev); + + if (!ops->get_pin_name) + return -ENOSYS; + + snprintf(buf, size, ops->get_pin_name(dev, selector)); + + return 0; +} + +int pinctrl_get_pin_muxing(struct udevice *dev, int selector, char *buf, + int size) +{ + struct pinctrl_ops *ops = pinctrl_get_ops(dev); + + if (!ops->get_pin_muxing) + return -ENOSYS; + + return ops->get_pin_muxing(dev, selector, buf, size); +} + /** * pinconfig_post_bind() - post binding for PINCTRL uclass * Recursively bind child nodes as pinconfig devices in case of full pinctrl. @@ -264,7 +403,7 @@ int pinctrl_get_pins_count(struct udevice *dev) * @dev: pinctrl device * @return: 0 on success, or negative error code on failure */ -static int pinctrl_post_bind(struct udevice *dev) +static int __maybe_unused pinctrl_post_bind(struct udevice *dev) { const struct pinctrl_ops *ops = pinctrl_get_ops(dev); diff --git a/u-boot/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/u-boot/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c index 7f1fa1a76a..79475f5854 100644 --- a/u-boot/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c +++ b/u-boot/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "pinctrl-rockchip.h" @@ -353,6 +355,11 @@ static int rockchip_pinconf_set(struct rockchip_pin_bank *bank, u32 pin, u32 param, u32 arg) { int rc; +#if CONFIG_IS_ENABLED(DM_GPIO) && \ + (CONFIG_IS_ENABLED(SPL_GPIO_SUPPORT) || !defined(CONFIG_SPL_BUILD)) + struct gpio_desc desc; + char gpio_name[16]; +#endif switch (param) { case PIN_CONFIG_BIAS_DISABLE: @@ -377,6 +384,32 @@ static int rockchip_pinconf_set(struct rockchip_pin_bank *bank, return rc; break; + case PIN_CONFIG_OUTPUT: +#if CONFIG_IS_ENABLED(DM_GPIO) && \ + (CONFIG_IS_ENABLED(SPL_GPIO_SUPPORT) || !defined(CONFIG_SPL_BUILD)) + desc.flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE; + if (!arg) desc.flags |= GPIOD_ACTIVE_LOW; + snprintf(gpio_name, 16, "%s%d", bank->name, pin); + rc = dm_gpio_lookup_name(gpio_name, &desc); + if (rc < 0) { + debug("%s: GPIO %s-%d lookup failed (ret=%d)\n", __func__, + bank->name, pin, rc); + return rc; + } + + rc = dm_gpio_request(&desc, gpio_name); + if (rc < 0) { + debug("%s: GPIO %s-%d request failed (ret=%d)\n", __func__, + bank->name, pin, rc); + return rc; + } + dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT); + dm_gpio_set_value(&desc, arg ? 1 : 0); + debug("%s: GPIO %s-%d set to %d\n", __func__, bank->name, pin, arg); +#else + return -ENOSYS; +#endif + break; default: break; } @@ -393,6 +426,8 @@ static const struct pinconf_param rockchip_conf_params[] = { { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 }, { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 }, + { "output-high", PIN_CONFIG_OUTPUT, 1, }, + { "output-low", PIN_CONFIG_OUTPUT, 0, }, }; static int rockchip_pinconf_prop_name_to_param(const char *property, diff --git a/u-boot/drivers/pinctrl/rockchip/pinctrl-rv1126.c b/u-boot/drivers/pinctrl/rockchip/pinctrl-rv1126.c index 03bf70395a..d1ae132b64 100644 --- a/u-boot/drivers/pinctrl/rockchip/pinctrl-rv1126.c +++ b/u-boot/drivers/pinctrl/rockchip/pinctrl-rv1126.c @@ -292,7 +292,7 @@ static int rv1126_set_drive(struct rockchip_pin_bank *bank, rv1126_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); /* enable the write to the equivalent lower bits */ - data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16); + data = ((1 << RV1126_DRV_BITS_PER_PIN) - 1) << (bit + 16); data |= (strength << bit); return regmap_write(regmap, reg, data); diff --git a/u-boot/drivers/power/charge_animation.c b/u-boot/drivers/power/charge_animation.c index 63c99a7829..89c5db231f 100644 --- a/u-boot/drivers/power/charge_animation.c +++ b/u-boot/drivers/power/charge_animation.c @@ -138,6 +138,7 @@ static int regulators_parse_assigned_mem_state(struct udevice *dev) return 0; } +#ifdef CONFIG_IRQ static int regulators_enable_assigned_state_mem(struct udevice *dev) { struct charge_animation_pdata *pdata = dev_get_platdata(dev); @@ -187,7 +188,7 @@ static void pmics_resume(void) { pmics_ops(false); } - +#endif static int charge_animation_ofdata_to_platdata(struct udevice *dev) { struct charge_animation_pdata *pdata = dev_get_platdata(dev); @@ -1066,8 +1067,21 @@ static const struct dm_charge_display_ops charge_animation_ops = { static int charge_animation_probe(struct udevice *dev) { struct charge_animation_priv *priv = dev_get_priv(dev); + __maybe_unused struct udevice *rk_pm_cfg; int ret, soc; +#ifdef CONFIG_ROCKCHIP_PM_CONFIG + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(rockchip_pm_config), + &rk_pm_cfg); + if (ret) { + if (ret == -ENODEV) + printf("Can't find rockchip_pm_config\n"); + else + printf("Get rockchip_pm_config failed: %d\n", ret); + } +#endif + /* Get PMIC: used for power off system */ ret = uclass_get_device(UCLASS_PMIC, 0, &priv->pmic); if (ret) { diff --git a/u-boot/drivers/power/pmic/rk8xx.c b/u-boot/drivers/power/pmic/rk8xx.c index 19877f31bf..398bc2e81e 100644 --- a/u-boot/drivers/power/pmic/rk8xx.c +++ b/u-boot/drivers/power/pmic/rk8xx.c @@ -37,6 +37,28 @@ static struct virq_chip rk805_irq_chip = { .num_irqs = ARRAY_SIZE(rk805_irqs), }; +/* RK806 */ +static const struct virq_reg rk806_irqs[] = { + [RK8XX_IRQ_PWRON_FALL] = { + .mask = RK806_IRQ_PWRON_FALL_MSK, + .reg_offset = 0, + }, + [RK8XX_IRQ_PWRON_RISE] = { + .mask = RK806_IRQ_PWRON_RISE_MSK, + .reg_offset = 0, + }, +}; + +static struct virq_chip rk806_irq_chip = { + .status_base = RK806_INT_STS0, + .mask_base = RK806_INT_MSK0, + .num_regs = 1, + .read = pmic_reg_read, + .write = pmic_reg_write, + .irqs = rk806_irqs, + .num_irqs = ARRAY_SIZE(rk806_irqs), +}; + /* RK808 */ static const struct virq_reg rk808_irqs[] = { [RK8XX_IRQ_PLUG_OUT] = { @@ -167,6 +189,8 @@ static struct reg_data rk818_init_current[] = { static const struct pmic_child_info pmic_children_info[] = { { .prefix = "DCDC", .driver = "rk8xx_buck"}, { .prefix = "LDO", .driver = "rk8xx_ldo"}, + { .prefix = "NLDO", .driver = "rk8xx_ldo"}, + { .prefix = "PLDO", .driver = "rk8xx_pldo"}, { .prefix = "SWITCH", .driver = "rk8xx_switch"}, { }, }; @@ -237,9 +261,57 @@ static int rk8xx_suspend(struct udevice *dev) { struct rk8xx_priv *priv = dev_get_priv(dev); int ret = 0; - u8 val; + u8 i, val; switch (priv->variant) { + case RK806_ID: + ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1); + if (ret) + return ret; + val &= RK806_PWRCTRL_FUN_MSK; + ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1); + if (ret) + return ret; + + ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG1, &val, 1); + if (ret) + return ret; + + val &= RK806_PWRCTRL_FUN_MSK; + ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG1, &val, 1); + if (ret) + return ret; + + for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) { + ret = rk8xx_read(dev, i, &val, 1); + if (ret) + return ret; + val &= RK806_VSEL_CTRL_MSK; + ret = rk8xx_write(dev, i, &val, 1); + if (ret) + return ret; + } + + ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1); + if (ret) + return ret; + val &= RK806_PWRCTRL_FUN_MSK; + val |= RK806_ENABLE_PWRCTRL; + ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1); + if (ret) + return ret; + + for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) { + ret = rk8xx_read(dev, i, &val, 1); + if (ret) + return ret; + val &= RK806_VSEL_CTRL_MSK; + val |= RK806_VSEL_PWRCTRL1; + ret = rk8xx_write(dev, i, &val, 1); + if (ret) + return ret; + } + break; case RK809_ID: case RK817_ID: /* pmic_sleep active high */ @@ -262,8 +334,34 @@ static int rk8xx_resume(struct udevice *dev) { struct rk8xx_priv *priv = dev_get_priv(dev); int ret = 0; + u8 i, val; switch (priv->variant) { + case RK806_ID: + for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) { + ret = rk8xx_read(dev, i, &val, 1); + if (ret) + return ret; + val &= RK806_VSEL_CTRL_MSK; + ret = rk8xx_write(dev, i, &val, 1); + if (ret) + return ret; + } + + ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG0, &val, 1); + if (ret) + return ret; + val &= RK806_PWRCTRL_FUN_MSK; + ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG0, &val, 1); + if (ret) + return ret; + + ret = rk8xx_read(dev, RK806_PWRCTRL_CONFIG1, &val, 1); + if (ret) + return ret; + val &= RK806_PWRCTRL_FUN_MSK; + ret = rk8xx_write(dev, RK806_PWRCTRL_CONFIG1, &val, 1); + break; case RK809_ID: case RK817_ID: ret = rk8xx_write(dev, RK817_PMIC_SYS_CFG3, &priv->sleep_pin, 1); @@ -282,6 +380,10 @@ static int rk8xx_shutdown(struct udevice *dev) int ret = 0; switch (priv->variant) { + case RK806_ID: + devctrl_reg = RK806_SYS_CFG3; + dev_off = RK806_DEV_OFF; + break; case RK808_ID: devctrl_reg = REG_DEVCTRL; dev_off = BIT(3); @@ -412,6 +514,8 @@ static int rk8xx_ofdata_to_platdata(struct udevice *dev) val = dev_read_bool(dev, "vsys-off-shutdown"); rk8xx->sys_can_sd = val; + rk8xx->rst_fun = dev_read_u32_default(dev, "pmic-reset-func", 0); + return 0; } @@ -423,6 +527,10 @@ static int rk8xx_irq_chip_init(struct udevice *dev) int ret; switch (priv->variant) { + case RK806_ID: + irq_chip = &rk806_irq_chip; + irq_plugout = 0; + break; case RK808_ID: irq_chip = &rk808_irq_chip; break; @@ -496,6 +604,9 @@ static int rk8xx_probe(struct udevice *dev) device_is_compatible(dev, "rockchip,rk809")) { id_msb = RK817_ID_MSB; id_lsb = RK817_ID_LSB; + } else if (device_is_compatible(dev, "rockchip,rk806")) { + id_msb = RK806_CHIP_NAME; + id_lsb = RK806_CHIP_VER; } else { id_msb = ID_MSB; id_lsb = ID_LSB; @@ -511,6 +622,35 @@ static int rk8xx_probe(struct udevice *dev) priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; show_variant = priv->variant; switch (priv->variant) { + case RK806_ID: + on_source = RK806_ON_SOURCE; + off_source = RK806_OFF_SOURCE; + ret = rk8xx_read(dev, RK806_HW_VER, &value, 1); + if (ret) + panic("RK806: read RK806_HW_VER error!\n"); + + if ((lsb & RK806_VERSION_MSK) == RK806_VERSION_AB) { + ret = rk8xx_read(dev, RK806_SYS_CFG1, &value, 1); + if (ret) { + dev_err(dev, "rk806 RK806_SYS_CFG1 read error: %d\n", ret); + return ret; + } + value |= RK806_ABNORDET_EN; + rk8xx_write(dev, RK806_SYS_CFG1, &value, 1); + } + + if (priv->rst_fun) { + rk8xx_read(dev, RK806_SYS_CFG3, &value, 1); + value &= RK806_RESET_FUN_CLR; + if (priv->rst_fun == RK806_RST_MODE1) { + value |= (RK806_RST_MODE1 << 6); + rk8xx_write(dev, RK806_SYS_CFG3, &value, 1); + } else if (priv->rst_fun == RK806_RST_MODE2) { + value |= (RK806_RST_MODE2 << 6); + rk8xx_write(dev, RK806_SYS_CFG3, &value, 1); + } + } + break; case RK808_ID: show_variant = 0x808; /* RK808 hardware ID is 0 */ pwron_key = RK8XX_DEVCTRL_REG; @@ -666,6 +806,7 @@ static struct dm_pmic_ops rk8xx_ops = { static const struct udevice_id rk8xx_ids[] = { { .compatible = "rockchip,rk805" }, + { .compatible = "rockchip,rk806" }, { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk809" }, { .compatible = "rockchip,rk816" }, diff --git a/u-boot/drivers/power/pmic/rk8xx_spi.c b/u-boot/drivers/power/pmic/rk8xx_spi.c index 7f775b7c32..00d3bc3a71 100644 --- a/u-boot/drivers/power/pmic/rk8xx_spi.c +++ b/u-boot/drivers/power/pmic/rk8xx_spi.c @@ -14,47 +14,8 @@ DECLARE_GLOBAL_DATA_PTR; -#define RK806_CHIP_NAME 0x5A -#define RK806_CHIP_VER 0x5B -#define RK806_HW_VER 0x21 -#define HW_DUAL_PMIC 0x28 -#define HW_SINGLE_PMIC 0xe8 - -#define RK806_CMD_READ 0 -#define RK806_CMD_WRITE BIT(7) -#define RK806_CMD_CRC_EN BIT(6) -#define RK806_CMD_CRC_DIS 0 -#define RK806_CMD_LEN_MSK 0x0f -#define RK806_REG_H 0x00 - -#define RK806_SYS_CFG1 0x5f -#define RK806_PWRCTRL_CONFIG0 0x62 -#define RK806_PWRCTRL_CONFIG1 0x63 -#define RK806_VSEL_CTR_SEL0 0x64 -#define RK806_DVS_CTR_SEL4 0x6e -#define RK806_SYS_CFG3 0x72 -#define RK806_PWRON_KEY 0x76 -#define RK806_INT_STS0 0x77 -#define RK806_INT_MSK0 0x78 -#define RK806_INT_STS1 0x79 -#define RK806_INT_MSK1 0x7A -#define RK806_GPIO_INT_CONFIG 0x7B -#define RK806_ON_SOURCE 0x74 -#define RK806_OFF_SOURCE 0x75 - -#define RK806_IRQ_PWRON_FALL_MSK BIT(0) -#define RK806_IRQ_PWRON_RISE_MSK BIT(1) -#define RK806_DEV_OFF BIT(0) -#define RK806_RST_MODE1 0x01 -#define RK806_RST_MODE2 0x02 -#define RK806_PWRCTRL_FUN_MSK 0x88 -#define RK806_VSEL_CTRL_MSK 0xcc -#define RK806_VSEL_PWRCTRL1 0x11 -#define RK806_ENABLE_PWRCTRL 0x04 -#define VERSION_AB 0x01 - #if CONFIG_IS_ENABLED(IRQ) -/* RK805 */ +/* RK806 */ static const struct virq_reg rk806_irqs[] = { [RK8XX_IRQ_PWRON_FALL] = { .mask = RK806_IRQ_PWRON_FALL_MSK, @@ -78,9 +39,9 @@ static struct virq_chip rk806_irq_chip = { #endif static const struct pmic_child_info pmic_children_info[] = { - { .prefix = "DCDC", .driver = "rk8xx_spi_buck"}, - { .prefix = "NLDO", .driver = "rk8xx_spi_ldo"}, - { .prefix = "PLDO", .driver = "rk8xx_spi_pldo"}, + { .prefix = "DCDC", .driver = "rk8xx_buck"}, + { .prefix = "NLDO", .driver = "rk8xx_ldo"}, + { .prefix = "PLDO", .driver = "rk8xx_pldo"}, { }, }; @@ -212,7 +173,7 @@ static int rk8xx_spi_ofdata_to_platdata(struct udevice *dev) } rk8xx->irq = phandle_gpio_to_irq(phandle, interrupt); - if (rk8xx->irq < 0) + if (rk8xx->irq < 0 && rk8xx->irq != -EBUSY) printf("Failed to request rk8xx irq, ret=%d\n", rk8xx->irq); return 0; @@ -318,19 +279,19 @@ static int rk8xx_spi_probe(struct udevice *dev) } } - if ((lsb & 0x0f) == VERSION_AB) { + if ((lsb & RK806_VERSION_MSK) == RK806_VERSION_AB) { ret = rk806_spi_read(dev, RK806_SYS_CFG1, &value, 1); if (ret) { dev_err(dev, "rk806 RK806_SYS_CFG1 read error: %d\n", ret); return ret; } - value |= 0x80; + value |= RK806_ABNORDET_EN; rk806_spi_write(dev, RK806_SYS_CFG1, &value, 1); } if (priv->rst_fun) { rk806_spi_read(dev, RK806_SYS_CFG3, &value, 1); - value &= 0x3f; + value &= RK806_RESET_FUN_CLR; if (priv->rst_fun == RK806_RST_MODE1) { value |= (RK806_RST_MODE1 << 6); rk806_spi_write(dev, RK806_SYS_CFG3, &value, 1); @@ -388,7 +349,7 @@ static int rk806_suspend(struct udevice *dev) if (ret) return ret; - for (i = RK806_VSEL_CTR_SEL0; i <= 0x6e; i++) { + for (i = RK806_VSEL_CTR_SEL0; i <= RK806_DVS_CTR_SEL4; i++) { ret = rk806_spi_read(dev, i, &val, 1); if (ret) return ret; diff --git a/u-boot/drivers/power/regulator/Kconfig b/u-boot/drivers/power/regulator/Kconfig index 37a75ccbcd..1ec20ccebf 100644 --- a/u-boot/drivers/power/regulator/Kconfig +++ b/u-boot/drivers/power/regulator/Kconfig @@ -110,22 +110,13 @@ config REGULATOR_RK860X config REGULATOR_RK8XX bool "Enable driver for RK8XX regulators" - depends on DM_REGULATOR && PMIC_RK8XX + depends on DM_REGULATOR && (PMIC_RK8XX || PMIC_SPI_RK8XX) ---help--- Enable support for the regulator functions of the RK8XX PMIC. The driver implements get/set api for the various BUCKS and LDOs supported by the PMIC device. This driver is controlled by a device tree node which includes voltage limits. -config REGULATOR_RK806 - bool "Enable driver for RK8XX regulators" - depends on DM_REGULATOR && PMIC_SPI_RK8XX - ---help--- - Enable support for the regulator functions of the RK806 PMIC. The - driver implements get/set api for the various BUCKS and LDOs supported - by the PMIC device. This driver is controlled by a device tree node - which includes voltage limits - config REGULATOR_S5M8767 bool "Enable support for S5M8767 regulator" depends on DM_REGULATOR && PMIC_S5M8767 diff --git a/u-boot/drivers/power/regulator/Makefile b/u-boot/drivers/power/regulator/Makefile index 73671aa8bd..1dbd8d253c 100644 --- a/u-boot/drivers/power/regulator/Makefile +++ b/u-boot/drivers/power/regulator/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_RK860X) += rk860x_regulator.o obj-$(CONFIG_REGULATOR_RK8XX) += rk8xx.o -obj-$(CONFIG_REGULATOR_RK806) += rk806.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o obj-$(CONFIG_REGULATOR_TPS65090) += tps65090_regulator.o diff --git a/u-boot/drivers/power/regulator/rk806.c b/u-boot/drivers/power/regulator/rk806.c deleted file mode 100644 index a219ea4233..0000000000 --- a/u-boot/drivers/power/regulator/rk806.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * Copyright (C) 2021 Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_SPL_BUILD -#define ENABLE_DRIVER -#endif - -/* Not used or exisit register and configure */ -#define NA -1 - -/* rk806 buck*/ -#define RK806_BUCK_ON_VSEL(n) (0x1a + n - 1) -#define RK806_BUCK_SLP_VSEL(n) (0x24 + n - 1) -#define RK806_BUCK_CONFIG(n) (0x10 + n - 1) -#define RK806_BUCK_VSEL_MASK 0xff - -/* RK806 LDO */ -#define RK806_NLDO_ON_VSEL(n) (0x43 + n - 1) -#define RK806_NLDO_SLP_VSEL(n) (0x48 + n - 1) -#define RK806_NLDO_VSEL_MASK 0xff -#define RK806_PLDO_ON_VSEL(n) (0x4e + n - 1) -#define RK806_PLDO_SLP_VSEL(n) (0x54 + n - 1) -#define RK806_PLDO_VSEL_MASK 0xff - -/* RK806 ENABLE */ -#define RK806_POWER_EN(n) (0x00 + n) -#define RK806_NLDO_EN(n) (0x03 + n) -#define RK806_PLDO_EN(n) (0x04 + n) - -#define RK806_BUCK_SUSPEND_EN 0x06 -#define RK806_NLDO_SUSPEND_EN 0x07 -#define RK806_PLDO_SUSPEND_EN 0x08 - -#define RK806_RAMP_RATE_MASK1 0xc0 -#define RK806_RAMP_RATE_REG1(n) (0x10 + n) -#define RK806_RAMP_RATE_REG1_8 0xeb -#define RK806_RAMP_RATE_REG9_10 0xea - -#define RK806_RAMP_RATE_4LSB_PER_1CLK 0x00/* LDO 100mV/uS buck 50mV/us */ -#define RK806_RAMP_RATE_2LSB_PER_1CLK 0x01/* LDO 50mV/uS buck 25mV/us */ -#define RK806_RAMP_RATE_1LSB_PER_1CLK 0x02/* LDO 25mV/uS buck 12.5mV/us */ -#define RK806_RAMP_RATE_1LSB_PER_2CLK 0x03/* LDO 12.5mV/uS buck 6.25mV/us */ - -#define RK806_RAMP_RATE_1LSB_PER_4CLK 0x04/* LDO 6.28/2mV/uS buck 3.125mV/us */ -#define RK806_RAMP_RATE_1LSB_PER_8CLK 0x05/* LDO 3.12mV/uS buck 1.56mV/us */ -#define RK806_RAMP_RATE_1LSB_PER_13CLK 0x06/* LDO 1.9mV/uS buck 961mV/us */ -#define RK806_RAMP_RATE_1LSB_PER_32CLK 0x07/* LDO 0.78mV/uS buck 0.39mV/us */ - -#define RK806_PLDO0_2_MSK(pldo) (BIT(pldo + 5)) -#define RK806_PLDO0_2_SET(pldo) (BIT(pldo + 1) | RK806_PLDO0_2_MSK(pldo)) -#define RK806_PLDO0_2_CLR(pldo) RK806_PLDO0_2_MSK(pldo) - -struct rk8xx_reg_info { - uint min_uv; - uint step_uv; - u8 vsel_reg; - u8 vsel_sleep_reg; - u8 config_reg; - u8 vsel_mask; - u8 min_sel; - /* only for buck now */ - u8 max_sel; - u8 range_num; -}; - -static const struct rk8xx_reg_info rk806_buck[] = { - /* buck 1 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xa0, 0xec, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 2 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 3 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 4 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 5 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 6 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 7 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 8 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 9 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, - /* buck 10 */ - { 500000, 6250, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, - { 1500000, 25000, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, - { 3400000, 0, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, -}; - -static const struct rk8xx_reg_info rk806_nldo[] = { - /* nldo1 */ - { 500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, - /* nldo2 */ - { 500000, 12500, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, - /* nldo3 */ - { 500000, 12500, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, - /* nldo4 */ - { 500000, 12500, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, - /* nldo5 */ - { 500000, 12500, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, -}; - -static const struct rk8xx_reg_info rk806_pldo[] = { - /* pldo1 */ - { 500000, 12500, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, - /* pldo2 */ - { 500000, 12500, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, - /* pldo3 */ - { 500000, 12500, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, - /* pldo4 */ - { 500000, 12500, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, - /* pldo5 */ - { 500000, 12500, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, - /* pldo6 */ - { 500000, 12500, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0x00, }, - { 3400000, 0, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, -}; - -static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, - int num, int uvolt) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - - switch (priv->variant) { - case RK806_ID: - switch (num) { - case 0 ... 9: - if (uvolt < 1500000) - return &rk806_buck[num * 3 + 0]; - else if (uvolt < 3400000) - return &rk806_buck[num * 3 + 1]; - else - return &rk806_buck[num * 3 + 2]; - break; - } - default: - return &rk806_buck[num * 3 + 0]; - } -} - -static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) -{ - const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt); - int mask = info->vsel_mask; - int val; - - if (info->vsel_reg == NA) - return -EINVAL; - - if (info->step_uv == 0) /* Fixed voltage */ - val = info->min_sel; - else - val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - - debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, buck + 1, info->vsel_reg, mask, val); - - return pmic_clrsetbits(pmic, info->vsel_reg, mask, val); -} - -static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - uint value, en_reg; - int ret; - - switch (priv->variant) { - case RK806_ID: - en_reg = RK806_POWER_EN(buck / 4); - if (enable) - value = ((1 << buck % 4) | (1 << (buck % 4 + 4))); - else - value = ((0 << buck % 4) | (1 << (buck % 4 + 4))); - - ret = pmic_reg_write(pmic, en_reg, value); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -#ifdef ENABLE_DRIVER -static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt) -{ - const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt); - int mask = info->vsel_mask; - int val; - - if (info->vsel_sleep_reg == NA) - return -EINVAL; - - if (info->step_uv == 0) - val = info->min_sel; - else - val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - - debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, buck + 1, info->vsel_sleep_reg, mask, val); - - return pmic_clrsetbits(pmic, info->vsel_sleep_reg, mask, val); -} - -static int _buck_get_enable(struct udevice *pmic, int buck) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - uint mask = 0; - int ret = 0; - - switch (priv->variant) { - case RK806_ID: - mask = 1 << buck % 4; - ret = pmic_reg_read(pmic, RK806_POWER_EN(buck / 4)); - break; - default: - ret = 0; - } - - if (ret < 0) - return ret; - - return ret & mask ? true : false; -} - -static int _buck_set_ramp_delay(struct udevice *pmic, int buck, u32 ramp_delay) -{ - const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, 0); - struct rk8xx_priv *priv = dev_get_priv(pmic); - int ramp_value = 0, reg_value; - int ramp_reg1, ramp_reg2; - - if (info->config_reg == NA) - return -EINVAL; - - switch (priv->variant) { - case RK806_ID: - switch (ramp_delay) { - case 1 ... 390: - ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; - break; - case 391 ... 961: - ramp_value = RK806_RAMP_RATE_1LSB_PER_13CLK; - break; - case 962 ... 1560: - ramp_value = RK806_RAMP_RATE_1LSB_PER_8CLK; - break; - case 1561 ... 3125: - ramp_value = RK806_RAMP_RATE_1LSB_PER_4CLK; - break; - case 3126 ... 6250: - ramp_value = RK806_RAMP_RATE_1LSB_PER_2CLK; - break; - case 6251 ... 12500: - ramp_value = RK806_RAMP_RATE_1LSB_PER_1CLK; - break; - case 12501 ... 25000: - ramp_value = RK806_RAMP_RATE_2LSB_PER_1CLK; - break; - case 25001 ... 50000: /* 50mV/us */ - ramp_value = RK806_RAMP_RATE_4LSB_PER_1CLK; - break; - default: - ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; - printf("buck%d ramp_delay: %d not supported\n", - buck, ramp_delay); - break; - } - break; - default: - ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; - return -EINVAL; - } - - ramp_reg1 = RK806_RAMP_RATE_REG1(buck); - if (buck < 8) - ramp_reg2 = RK806_RAMP_RATE_REG1_8; - else - ramp_reg2 = RK806_RAMP_RATE_REG9_10; - - reg_value = pmic_reg_read(pmic, ramp_reg1); - if (reg_value < 0) { - printf("buck%d read ramp reg(0x%x) error: %d", buck, ramp_reg1, reg_value); - return reg_value; - } - reg_value &= 0x3f; - - pmic_reg_write(pmic, - ramp_reg1, - reg_value | (ramp_value & 0x03) << 0x06); - - reg_value = pmic_reg_read(pmic, ramp_reg2); - if (reg_value < 0) { - printf("buck%d read ramp reg(0x%x) error: %d", buck, ramp_reg2, reg_value); - return reg_value; - } - - return pmic_reg_write(pmic, - ramp_reg2, - reg_value | (ramp_value & 0x04) << (buck % 8)); -} - -static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) -{ - uint mask; - int ret; - - if (buck <= 7) { - mask = 1 << buck; - ret = pmic_clrsetbits(pmic, RK806_BUCK_SUSPEND_EN, mask, - enable ? mask : 0); - } else { - if (buck == 8) - mask = 0x40; - else - mask = 0x80; - ret = pmic_clrsetbits(pmic, RK806_NLDO_SUSPEND_EN, mask, - enable ? mask : 0); - } - - return ret; -} - -static int _buck_get_suspend_enable(struct udevice *pmic, int buck) -{ - uint mask, val; - int ret; - - if (buck <= 7) { - mask = 1 << buck % 7; - val = pmic_reg_read(pmic, RK806_BUCK_SUSPEND_EN); - } else { - mask = 1 << ((buck - 7) + 6); - val = pmic_reg_read(pmic, RK806_NLDO_SUSPEND_EN); - } - - if (val < 0) - return val; - ret = val & mask ? 1 : 0; - - return ret; -} - -static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, - int num, int uvolt) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - - switch (priv->variant) { - case RK806_ID: - if (uvolt < 3400000) - return &rk806_nldo[num * 2]; - else - return &rk806_nldo[num * 2 + 1]; - default: - return &rk806_nldo[num * 2]; - } -} - -static const struct rk8xx_reg_info *get_pldo_reg(struct udevice *pmic, - int num, int uvolt) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - - switch (priv->variant) { - case RK806_ID: - if (uvolt < 3400000) - return &rk806_pldo[num * 2]; - else - return &rk806_pldo[num * 2 + 1]; - default: - return &rk806_pldo[num * 2]; - } -} - -static int _ldo_get_enable(struct udevice *pmic, int ldo) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - uint mask = 0; - int ret = 0; - - switch (priv->variant) { - case RK806_ID: - if (ldo < 4) { - mask = 1 << ldo % 4; - ret = pmic_reg_read(pmic, RK806_NLDO_EN(ldo / 4)); - } else { - mask = 1 << 2; - ret = pmic_reg_read(pmic, RK806_NLDO_EN(2)); - } - break; - default: - return false; - } - - if (ret < 0) - return ret; - - return ret & mask ? true : false; -} - -static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - uint value, en_reg; - int ret = 0; - - switch (priv->variant) { - case RK806_ID: - if (ldo < 4) { - en_reg = RK806_NLDO_EN(0); - if (enable) - value = ((1 << ldo % 4) | (1 << (ldo % 4 + 4))); - else - value = ((0 << ldo % 4) | (1 << (ldo % 4 + 4))); - ret = pmic_reg_write(pmic, en_reg, value); - } else { - en_reg = RK806_NLDO_EN(2); - if (enable) - value = 0x44; - else - value = 0x40; - ret = pmic_reg_write(pmic, en_reg, value); - } - break; - default: - return -EINVAL; - } - - return ret; -} - -static int _pldo_get_enable(struct udevice *pmic, int pldo) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - uint mask = 0, en_reg; - int ret = 0; - - switch (priv->variant) { - case RK806_ID: - if ((pldo < 3) || (pldo == 5)) { - en_reg = RK806_PLDO_EN(0); - mask = RK806_PLDO0_2_SET(pldo); - if (pldo == 5) - mask = (1 << 0); - ret = pmic_reg_read(pmic, en_reg); - } else if ((pldo == 3) || (pldo == 4)) { - en_reg = RK806_PLDO_EN(1); - if (pldo == 3) - mask = (1 << 0); - else - mask = (1 << 1); - ret = pmic_reg_read(pmic, en_reg); - } - break; - - default: - return -EINVAL; - } - - if (ret < 0) - return ret; - - return ret & mask ? true : false; -} - -static int _pldo_set_enable(struct udevice *pmic, int pldo, bool enable) -{ - struct rk8xx_priv *priv = dev_get_priv(pmic); - uint value, en_reg; - int ret = 0; - - switch (priv->variant) { - case RK806_ID: - if (pldo < 3) { - en_reg = RK806_PLDO_EN(0); - if (enable) - value = RK806_PLDO0_2_SET(pldo); - else - value = RK806_PLDO0_2_CLR(pldo); - ret = pmic_reg_write(pmic, en_reg, value); - } else if (pldo == 3) { - en_reg = RK806_PLDO_EN(1); - if (enable) - value = ((1 << 0) | (1 << 4)); - else - value = (1 << 4); - ret = pmic_reg_write(pmic, en_reg, value); - } else if (pldo == 4) { - en_reg = RK806_PLDO_EN(1); - if (enable) - value = ((1 << 1) | (1 << 5)); - else - value = ((0 << 1) | (1 << 5)); - ret = pmic_reg_write(pmic, en_reg, value); - } else if (pldo == 5) { - en_reg = RK806_PLDO_EN(0); - if (enable) - value = ((1 << 0) | (1 << 4)); - else - value = ((0 << 0) | (1 << 4)); - ret = pmic_reg_write(pmic, en_reg, value); - } - - break; - default: - return -EINVAL; - } - - return ret; -} - -static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) -{ - uint mask; - int ret; - - mask = 1 << ldo; - ret = pmic_clrsetbits(pmic, RK806_NLDO_SUSPEND_EN, mask, - enable ? mask : 0); - - return ret; -} - -static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) -{ - uint mask, val; - int ret; - - mask = 1 << ldo; - val = pmic_reg_read(pmic, RK806_NLDO_SUSPEND_EN); - - if (val < 0) - return val; - ret = val & mask ? 1 : 0; - - return ret; -} - -static int buck_get_value(struct udevice *dev) -{ - int buck = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0); - int mask = info->vsel_mask; - int i, ret, val; - - if (info->vsel_reg == NA) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, info->vsel_reg); - if (ret < 0) - return ret; - - val = ret & mask; - if (val >= info->min_sel && val <= info->max_sel) - goto finish; - - /* unlucky to try */ - for (i = 1; i < info->range_num; i++) { - info++; - if (val <= info->max_sel && val >= info->min_sel) - break; - } - -finish: - return info->min_uv + (val - info->min_sel) * info->step_uv; -} - -static int buck_set_value(struct udevice *dev, int uvolt) -{ - int buck = dev->driver_data - 1; - - return _buck_set_value(dev->parent, buck, uvolt); -} - -static int buck_get_suspend_value(struct udevice *dev) -{ - int buck = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0); - int mask = info->vsel_mask; - int i, ret, val; - - if (info->vsel_sleep_reg == NA) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg); - if (ret < 0) - return ret; - - val = ret & mask; - if (val <= info->max_sel && val >= info->min_sel) - goto finish; - - /* unlucky to try */ - for (i = 1; i < info->range_num; i++) { - info++; - if (val <= info->max_sel && val >= info->min_sel) - break; - } - -finish: - return info->min_uv + (val - info->min_sel) * info->step_uv; -} - -static int buck_set_suspend_value(struct udevice *dev, int uvolt) -{ - int buck = dev->driver_data - 1; - - return _buck_set_suspend_value(dev->parent, buck, uvolt); -} - -static int buck_set_enable(struct udevice *dev, bool enable) -{ - int buck = dev->driver_data - 1; - - return _buck_set_enable(dev->parent, buck, enable); -} - -static int buck_set_suspend_enable(struct udevice *dev, bool enable) -{ - int buck = dev->driver_data - 1; - - return _buck_set_suspend_enable(dev->parent, buck, enable); -} - -static int buck_get_suspend_enable(struct udevice *dev) -{ - int buck = dev->driver_data - 1; - - return _buck_get_suspend_enable(dev->parent, buck); -} - -static int buck_set_ramp_delay(struct udevice *dev, u32 ramp_delay) -{ - int buck = dev->driver_data - 1; - - return _buck_set_ramp_delay(dev->parent, buck, ramp_delay); -} - -static int buck_get_enable(struct udevice *dev) -{ - int buck = dev->driver_data - 1; - - return _buck_get_enable(dev->parent, buck); -} - -static int ldo_get_value(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); - int mask = info->vsel_mask; - int ret, val; - - if (info->vsel_reg == NA) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, info->vsel_reg); - if (ret < 0) - return ret; - val = ret & mask; - - return info->min_uv + val * info->step_uv; -} - -static int ldo_set_value(struct udevice *dev, int uvolt) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); - int mask = info->vsel_mask; - int val; - - if (info->vsel_reg == NA) - return -EINVAL; - - if (info->step_uv == 0) - val = info->min_sel; - else - val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - - debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo + 1, info->vsel_reg, mask, val); - - return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); -} - -static int pldo_get_value(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, 0); - int mask = info->vsel_mask; - int ret, val; - - if (info->vsel_reg == NA) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, info->vsel_reg); - if (ret < 0) - return ret; - val = ret & mask; - - return info->min_uv + val * info->step_uv; -} - -static int pldo_set_value(struct udevice *dev, int uvolt) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, uvolt); - int mask = info->vsel_mask; - int val; - - if (info->vsel_reg == NA) - return -EINVAL; - - if (info->step_uv == 0) - val = info->min_sel; - else - val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - - debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo + 1, info->vsel_reg, mask, val); - - return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); -} - -static int ldo_set_suspend_value(struct udevice *dev, int uvolt) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); - int mask = info->vsel_mask; - int val; - - if (info->vsel_sleep_reg == NA) - return -EINVAL; - - if (info->step_uv == 0) - val = info->min_sel; - else - val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - - debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo + 1, info->vsel_sleep_reg, mask, val); - - return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val); -} - -static int ldo_get_suspend_value(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); - int mask = info->vsel_mask; - int val, ret; - - if (info->vsel_sleep_reg == NA) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg); - if (ret < 0) - return ret; - - val = ret & mask; - - return info->min_uv + val * info->step_uv; -} - -static int ldo_set_enable(struct udevice *dev, bool enable) -{ - int ldo = dev->driver_data - 1; - - return _ldo_set_enable(dev->parent, ldo, enable); -} - -static int ldo_set_suspend_enable(struct udevice *dev, bool enable) -{ - int ldo = dev->driver_data - 1; - - return _ldo_set_suspend_enable(dev->parent, ldo, enable); -} - -static int ldo_get_suspend_enable(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - - return _ldo_get_suspend_enable(dev->parent, ldo); -} - -static int ldo_get_enable(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - - return _ldo_get_enable(dev->parent, ldo); -} - -static int pldo_set_enable(struct udevice *dev, bool enable) -{ - int ldo = dev->driver_data - 1; - - return _pldo_set_enable(dev->parent, ldo, enable); -} - -static int pldo_get_enable(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - - return _pldo_get_enable(dev->parent, ldo); -} - -static int pldo_set_suspend_value(struct udevice *dev, int uvolt) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, uvolt);; - int mask = info->vsel_mask; - int val; - - if (info->vsel_sleep_reg == NA) - return -EINVAL; - - if (info->step_uv == 0) - val = info->min_sel; - else - val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - - return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val); -} - -static int pldo_get_suspend_value(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, 0); - int mask = info->vsel_mask; - int val, ret; - - if (info->vsel_sleep_reg == NA) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg); - if (ret < 0) - return ret; - - val = ret & mask; - - return info->min_uv + val * info->step_uv; -} - -static int _pldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) -{ - uint mask; - int ret; - - if (ldo < 5) - mask = 1 << (ldo + 1); - else - mask = 1; - ret = pmic_clrsetbits(pmic, RK806_PLDO_SUSPEND_EN, mask, - enable ? mask : 0); - - return ret; -} - -static int _pldo_get_suspend_enable(struct udevice *pmic, int ldo) -{ - uint mask, val; - int ret; - - if (ldo < 5) - mask = 1 << (ldo + 1); - else - mask = 1; - val = pmic_reg_read(pmic, RK806_PLDO_SUSPEND_EN); - - if (val < 0) - return val; - ret = val & mask ? 1 : 0; - - return ret; -} - -static int pldo_set_suspend_enable(struct udevice *dev, bool enable) -{ - int ldo = dev->driver_data - 1; - - return _pldo_set_suspend_enable(dev->parent, ldo, enable); -} - -static int pldo_get_suspend_enable(struct udevice *dev) -{ - int ldo = dev->driver_data - 1; - - return _pldo_get_suspend_enable(dev->parent, ldo); -} - -static int rk8xx_buck_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - uc_pdata = dev_get_uclass_platdata(dev); - uc_pdata->type = REGULATOR_TYPE_BUCK; - uc_pdata->mode_count = 0; - - return 0; -} - -static int rk8xx_ldo_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - uc_pdata = dev_get_uclass_platdata(dev); - uc_pdata->type = REGULATOR_TYPE_LDO; - uc_pdata->mode_count = 0; - - return 0; -} - -static int rk8xx_pldo_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - uc_pdata = dev_get_uclass_platdata(dev); - uc_pdata->type = REGULATOR_TYPE_LDO; - uc_pdata->mode_count = 0; - - return 0; -} - -static const struct dm_regulator_ops rk8xx_buck_ops = { - .get_value = buck_get_value, - .set_value = buck_set_value, - .set_suspend_value = buck_set_suspend_value, - .get_suspend_value = buck_get_suspend_value, - .get_enable = buck_get_enable, - .set_enable = buck_set_enable, - .set_suspend_enable = buck_set_suspend_enable, - .get_suspend_enable = buck_get_suspend_enable, - .set_ramp_delay = buck_set_ramp_delay, -}; - -static const struct dm_regulator_ops rk8xx_ldo_ops = { - .get_value = ldo_get_value, - .set_value = ldo_set_value, - .set_suspend_value = ldo_set_suspend_value, - .get_suspend_value = ldo_get_suspend_value, - .get_enable = ldo_get_enable, - .set_enable = ldo_set_enable, - .set_suspend_enable = ldo_set_suspend_enable, - .get_suspend_enable = ldo_get_suspend_enable, -}; - -static const struct dm_regulator_ops rk8xx_pldo_ops = { - .get_value = pldo_get_value, - .set_value = pldo_set_value, - .set_suspend_value = pldo_set_suspend_value, - .get_suspend_value = pldo_get_suspend_value, - .get_enable = pldo_get_enable, - .set_enable = pldo_set_enable, - .set_suspend_enable = pldo_set_suspend_enable, - .get_suspend_enable = pldo_get_suspend_enable, -}; - -U_BOOT_DRIVER(rk8xx_spi_buck) = { - .name = "rk8xx_spi_buck", - .id = UCLASS_REGULATOR, - .ops = &rk8xx_buck_ops, - .probe = rk8xx_buck_probe, -}; - -U_BOOT_DRIVER(rk8xx_spi_ldo) = { - .name = "rk8xx_spi_ldo", - .id = UCLASS_REGULATOR, - .ops = &rk8xx_ldo_ops, - .probe = rk8xx_ldo_probe, -}; - -U_BOOT_DRIVER(rk8xx_spi_pldo) = { - .name = "rk8xx_spi_pldo", - .id = UCLASS_REGULATOR, - .ops = &rk8xx_pldo_ops, - .probe = rk8xx_pldo_probe, -}; -#endif diff --git a/u-boot/drivers/power/regulator/rk8xx.c b/u-boot/drivers/power/regulator/rk8xx.c index 47f2b7c134..dbad1fe7af 100644 --- a/u-boot/drivers/power/regulator/rk8xx.c +++ b/u-boot/drivers/power/regulator/rk8xx.c @@ -94,6 +94,88 @@ struct rk8xx_reg_info { u8 range_num; }; +static const struct rk8xx_reg_info rk806_buck[] = { + /* buck 1 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xa0, 0xec, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 2 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 3 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 4 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 5 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 6 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 7 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 8 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 9 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, + /* buck 10 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0x00, 0x9f, 3}, + { 1500000, 25000, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xa0, 0xed, 3}, + { 3400000, 0, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xed, 0xff, 3}, +}; + +static const struct rk8xx_reg_info rk806_nldo[] = { + /* nldo1 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, + /* nldo2 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, + /* nldo3 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, + /* nldo4 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, + /* nldo5 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0xE8, }, +}; + +static const struct rk8xx_reg_info rk806_pldo[] = { + /* pldo1 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, + /* pldo2 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, + /* pldo3 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, + /* pldo4 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, + /* pldo5 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, + /* pldo6 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0x00, }, + { 3400000, 0, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0xE8, }, +}; + static const struct rk8xx_reg_info rk808_buck[] = { { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f, 1}, { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f, 1}, @@ -227,6 +309,16 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK806_ID: + switch (num) { + case 0 ... 9: + if (uvolt < 1500000) + return &rk806_buck[num * 3 + 0]; + else if (uvolt < 3400000) + return &rk806_buck[num * 3 + 1]; + else + return &rk806_buck[num * 3 + 2]; + } case RK805_ID: case RK816_ID: switch (num) { @@ -293,7 +385,7 @@ static int _buck_set_value(struct udevice *pmic, int buck, int uvolt) val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, buck+1, info->vsel_reg, mask, val); + __func__, uvolt, buck + 1, info->vsel_reg, mask, val); if (priv->variant == RK816_ID) { pmic_clrsetbits(pmic, info->vsel_reg, mask, val); @@ -310,6 +402,15 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) struct rk8xx_priv *priv = dev_get_priv(pmic); switch (priv->variant) { + case RK806_ID: + en_reg = RK806_POWER_EN(buck / 4); + if (enable) + value = ((1 << buck % 4) | (1 << (buck % 4 + 4))); + else + value = ((0 << buck % 4) | (1 << (buck % 4 + 4))); + + ret = pmic_reg_write(pmic, en_reg, value); + break; case RK805_ID: case RK816_ID: if (buck >= 4) { @@ -377,7 +478,7 @@ static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt) val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; debug("%s: volt=%d, buck=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, buck+1, info->vsel_sleep_reg, mask, val); + __func__, uvolt, buck + 1, info->vsel_sleep_reg, mask, val); return pmic_clrsetbits(pmic, info->vsel_sleep_reg, mask, val); } @@ -389,6 +490,10 @@ static int _buck_get_enable(struct udevice *pmic, int buck) int ret = 0; switch (priv->variant) { + case RK806_ID: + mask = 1 << buck % 4; + ret = pmic_reg_read(pmic, RK806_POWER_EN(buck / 4)); + break; case RK805_ID: case RK816_ID: if (buck >= 4) { @@ -430,6 +535,7 @@ static int _buck_set_ramp_delay(struct udevice *pmic, int buck, u32 ramp_delay) const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, 0); struct rk8xx_priv *priv = dev_get_priv(pmic); u32 ramp_value, ramp_mask; + int reg_value, ramp_reg1, ramp_reg2; if (info->config_reg == NA) return -ENOSYS; @@ -456,6 +562,64 @@ static int _buck_set_ramp_delay(struct udevice *pmic, int buck, u32 ramp_delay) buck, ramp_delay); } break; + case RK806_ID: + switch (ramp_delay) { + case 1 ... 390: + ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; + break; + case 391 ... 961: + ramp_value = RK806_RAMP_RATE_1LSB_PER_13CLK; + break; + case 962 ... 1560: + ramp_value = RK806_RAMP_RATE_1LSB_PER_8CLK; + break; + case 1561 ... 3125: + ramp_value = RK806_RAMP_RATE_1LSB_PER_4CLK; + break; + case 3126 ... 6250: + ramp_value = RK806_RAMP_RATE_1LSB_PER_2CLK; + break; + case 6251 ... 12500: + ramp_value = RK806_RAMP_RATE_1LSB_PER_1CLK; + break; + case 12501 ... 25000: + ramp_value = RK806_RAMP_RATE_2LSB_PER_1CLK; + break; + case 25001 ... 50000: /* 50mV/us */ + ramp_value = RK806_RAMP_RATE_4LSB_PER_1CLK; + break; + default: + ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; + printf("buck%d ramp_delay: %d not supported\n", + buck, ramp_delay); + return -EINVAL; + } + ramp_reg1 = RK806_RAMP_RATE_REG1(buck); + if (buck < 8) + ramp_reg2 = RK806_RAMP_RATE_REG1_8; + else + ramp_reg2 = RK806_RAMP_RATE_REG9_10; + + reg_value = pmic_reg_read(pmic, ramp_reg1); + if (reg_value < 0) { + printf("buck%d read ramp reg(0x%x) error: %d", buck, ramp_reg1, reg_value); + return reg_value; + } + reg_value &= 0x3f; + + pmic_reg_write(pmic, + ramp_reg1, + reg_value | (ramp_value & 0x03) << 0x06); + + reg_value = pmic_reg_read(pmic, ramp_reg2); + if (reg_value < 0) { + printf("buck%d read ramp reg(0x%x) error: %d", buck, ramp_reg2, reg_value); + return reg_value; + } + + return pmic_reg_write(pmic, + ramp_reg2, + reg_value | (ramp_value & 0x04) << (buck % 8)); case RK808_ID: case RK816_ID: case RK818_ID: @@ -521,6 +685,20 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask, enable ? mask : 0); break; + case RK806_ID: + if (buck <= 7) { + mask = 1 << buck; + ret = pmic_clrsetbits(pmic, RK806_BUCK_SUSPEND_EN, mask, + enable ? mask : 0); + } else { + if (buck == 8) + mask = 0x40; + else + mask = 0x80; + ret = pmic_clrsetbits(pmic, RK806_NLDO_SUSPEND_EN, mask, + enable ? mask : 0); + } + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -554,6 +732,19 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) case RK816_ID: mask = 1 << buck; val = pmic_reg_read(pmic, RK816_REG_DCDC_SLP_EN); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + break; + case RK806_ID: + if (buck <= 7) { + mask = 1 << buck % 7; + val = pmic_reg_read(pmic, RK806_BUCK_SUSPEND_EN); + } else { + mask = 1 << ((buck - 7) + 6); + val = pmic_reg_read(pmic, RK806_NLDO_SUSPEND_EN); + } + if (val < 0) return val; ret = val & mask ? 1 : 0; @@ -594,6 +785,11 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, case RK805_ID: case RK816_ID: return &rk816_ldo[num]; + case RK806_ID: + if (uvolt < 3400000) + return &rk806_nldo[num * 2]; + else + return &rk806_nldo[num * 2 + 1]; case RK809_ID: case RK817_ID: if (uvolt < 3400000) @@ -624,6 +820,15 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) ret = pmic_reg_read(pmic, RK816_REG_LDO_EN1); } break; + case RK806_ID: + if (ldo < 4) { + mask = 1 << ldo % 4; + ret = pmic_reg_read(pmic, RK806_NLDO_EN(ldo / 4)); + } else { + mask = 1 << 2; + ret = pmic_reg_read(pmic, RK806_NLDO_EN(2)); + } + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; @@ -676,11 +881,28 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) ret = pmic_reg_write(pmic, en_reg, value); break; + case RK806_ID: + if (ldo < 4) { + en_reg = RK806_NLDO_EN(0); + if (enable) + value = ((1 << ldo % 4) | (1 << (ldo % 4 + 4))); + else + value = ((0 << ldo % 4) | (1 << (ldo % 4 + 4))); + ret = pmic_reg_write(pmic, en_reg, value); + } else { + en_reg = RK806_NLDO_EN(2); + if (enable) + value = 0x44; + else + value = 0x40; + ret = pmic_reg_write(pmic, en_reg, value); + } + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask, - enable ? mask : 0); + enable ? mask : 0); break; case RK809_ID: case RK817_ID: @@ -722,6 +944,11 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) ret = pmic_clrsetbits(pmic, RK816_REG_LDO_SLP_EN, mask, enable ? mask : 0); break; + case RK806_ID: + mask = 1 << ldo; + ret = pmic_clrsetbits(pmic, RK806_NLDO_SUSPEND_EN, mask, + enable ? mask : 0); + break; case RK808_ID: case RK818_ID: mask = 1 << ldo; @@ -756,6 +983,14 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) case RK816_ID: mask = 1 << ldo; val = pmic_reg_read(pmic, RK816_REG_LDO_SLP_EN); + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + break; + case RK806_ID: + mask = 1 << ldo; + val = pmic_reg_read(pmic, RK806_NLDO_SUSPEND_EN); + if (val < 0) return val; ret = val & mask ? 1 : 0; @@ -929,7 +1164,7 @@ static int ldo_set_value(struct udevice *dev, int uvolt) val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo+1, info->vsel_reg, mask, val); + __func__, uvolt, ldo + 1, info->vsel_reg, mask, val); return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); } @@ -950,7 +1185,7 @@ static int ldo_set_suspend_value(struct udevice *dev, int uvolt) val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo+1, info->vsel_sleep_reg, mask, val); + __func__, uvolt, ldo + 1, info->vsel_sleep_reg, mask, val); return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val); } @@ -1165,6 +1400,238 @@ static int switch_set_value(struct udevice *dev, int uvolt) return 0; } +static const struct rk8xx_reg_info *get_pldo_reg(struct udevice *pmic, + int num, int uvolt) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + + switch (priv->variant) { + case RK806_ID: + if (uvolt < 3400000) + return &rk806_pldo[num * 2]; + else + return &rk806_pldo[num * 2 + 1]; + default: + return &rk806_pldo[num * 2]; + } +} + +static int _pldo_get_enable(struct udevice *pmic, int pldo) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint mask = 0, en_reg; + int ret = 0; + + switch (priv->variant) { + case RK806_ID: + if ((pldo < 3) || (pldo == 5)) { + en_reg = RK806_PLDO_EN(0); + mask = RK806_PLDO0_2_SET(pldo); + if (pldo == 5) + mask = (1 << 0); + ret = pmic_reg_read(pmic, en_reg); + } else if ((pldo == 3) || (pldo == 4)) { + en_reg = RK806_PLDO_EN(1); + if (pldo == 3) + mask = (1 << 0); + else + mask = (1 << 1); + ret = pmic_reg_read(pmic, en_reg); + } + break; + + default: + return -EINVAL; + } + + if (ret < 0) + return ret; + + return ret & mask ? true : false; +} + +static int _pldo_set_enable(struct udevice *pmic, int pldo, bool enable) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint value, en_reg; + int ret = 0; + + switch (priv->variant) { + case RK806_ID: + if (pldo < 3) { + en_reg = RK806_PLDO_EN(0); + if (enable) + value = RK806_PLDO0_2_SET(pldo); + else + value = RK806_PLDO0_2_CLR(pldo); + ret = pmic_reg_write(pmic, en_reg, value); + } else if (pldo == 3) { + en_reg = RK806_PLDO_EN(1); + if (enable) + value = ((1 << 0) | (1 << 4)); + else + value = (1 << 4); + ret = pmic_reg_write(pmic, en_reg, value); + } else if (pldo == 4) { + en_reg = RK806_PLDO_EN(1); + if (enable) + value = ((1 << 1) | (1 << 5)); + else + value = ((0 << 1) | (1 << 5)); + ret = pmic_reg_write(pmic, en_reg, value); + } else if (pldo == 5) { + en_reg = RK806_PLDO_EN(0); + if (enable) + value = ((1 << 0) | (1 << 4)); + else + value = ((0 << 0) | (1 << 4)); + ret = pmic_reg_write(pmic, en_reg, value); + } + + break; + default: + return -EINVAL; + } + + return ret; +} + +static int pldo_get_value(struct udevice *dev) +{ + int ldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, 0); + int mask = info->vsel_mask; + int ret, val; + + if (info->vsel_reg == NA) + return -EINVAL; + + ret = pmic_reg_read(dev->parent, info->vsel_reg); + if (ret < 0) + return ret; + val = ret & mask; + + return info->min_uv + val * info->step_uv; +} + +static int pldo_set_value(struct udevice *dev, int uvolt) +{ + int ldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, uvolt); + int mask = info->vsel_mask; + int val; + + if (info->vsel_reg == NA) + return -EINVAL; + + if (info->step_uv == 0) + val = info->min_sel; + else + val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; + + debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", + __func__, uvolt, ldo + 1, info->vsel_reg, mask, val); + + return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); +} + +static int pldo_set_enable(struct udevice *dev, bool enable) +{ + int ldo = dev->driver_data - 1; + + return _pldo_set_enable(dev->parent, ldo, enable); +} + +static int pldo_get_enable(struct udevice *dev) +{ + int ldo = dev->driver_data - 1; + + return _pldo_get_enable(dev->parent, ldo); +} + +static int pldo_set_suspend_value(struct udevice *dev, int uvolt) +{ + int ldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, uvolt);; + int mask = info->vsel_mask; + int val; + + if (info->vsel_sleep_reg == NA) + return -EINVAL; + + if (info->step_uv == 0) + val = info->min_sel; + else + val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; + + return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val); +} + +static int pldo_get_suspend_value(struct udevice *dev) +{ + int ldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, ldo, 0); + int mask = info->vsel_mask; + int val, ret; + + if (info->vsel_sleep_reg == NA) + return -EINVAL; + + ret = pmic_reg_read(dev->parent, info->vsel_sleep_reg); + if (ret < 0) + return ret; + + val = ret & mask; + + return info->min_uv + val * info->step_uv; +} + +static int _pldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) +{ + uint mask; + int ret; + + if (ldo < 5) + mask = 1 << (ldo + 1); + else + mask = 1; + ret = pmic_clrsetbits(pmic, RK806_PLDO_SUSPEND_EN, mask, + enable ? mask : 0); + + return ret; +} + +static int _pldo_get_suspend_enable(struct udevice *pmic, int ldo) +{ + uint mask, val; + int ret; + + if (ldo < 5) + mask = 1 << (ldo + 1); + else + mask = 1; + val = pmic_reg_read(pmic, RK806_PLDO_SUSPEND_EN); + + if (val < 0) + return val; + ret = val & mask ? 1 : 0; + + return ret; +} +static int pldo_set_suspend_enable(struct udevice *dev, bool enable) +{ + int ldo = dev->driver_data - 1; + + return _pldo_set_suspend_enable(dev->parent, ldo, enable); +} + +static int pldo_get_suspend_enable(struct udevice *dev) +{ + int ldo = dev->driver_data - 1; + + return _pldo_get_suspend_enable(dev->parent, ldo); +} + static int rk8xx_buck_probe(struct udevice *dev) { struct dm_regulator_uclass_platdata *uc_pdata; @@ -1201,6 +1668,17 @@ static int rk8xx_switch_probe(struct udevice *dev) return 0; } +static int rk8xx_pldo_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + uc_pdata->type = REGULATOR_TYPE_LDO; + uc_pdata->mode_count = 0; + + return 0; +} + static const struct dm_regulator_ops rk8xx_buck_ops = { .get_value = buck_get_value, .set_value = buck_set_value, @@ -1235,6 +1713,17 @@ static const struct dm_regulator_ops rk8xx_switch_ops = { .get_suspend_value = switch_get_suspend_value, }; +static const struct dm_regulator_ops rk8xx_pldo_ops = { + .get_value = pldo_get_value, + .set_value = pldo_set_value, + .set_suspend_value = pldo_set_suspend_value, + .get_suspend_value = pldo_get_suspend_value, + .get_enable = pldo_get_enable, + .set_enable = pldo_set_enable, + .set_suspend_enable = pldo_set_suspend_enable, + .get_suspend_enable = pldo_get_suspend_enable, +}; + U_BOOT_DRIVER(rk8xx_buck) = { .name = "rk8xx_buck", .id = UCLASS_REGULATOR, @@ -1255,6 +1744,13 @@ U_BOOT_DRIVER(rk8xx_switch) = { .ops = &rk8xx_switch_ops, .probe = rk8xx_switch_probe, }; + +U_BOOT_DRIVER(rk8xx_spi_pldo) = { + .name = "rk8xx_pldo", + .id = UCLASS_REGULATOR, + .ops = &rk8xx_pldo_ops, + .probe = rk8xx_pldo_probe, +}; #endif int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt) diff --git a/u-boot/drivers/rkflash/flash.c b/u-boot/drivers/rkflash/flash.c index c038d5bae8..aa7c831f86 100644 --- a/u-boot/drivers/rkflash/flash.c +++ b/u-boot/drivers/rkflash/flash.c @@ -452,7 +452,8 @@ u32 nandc_flash_init(void __iomem *nandc_addr) id_byte[0][1] != 0xAA && id_byte[0][1] != 0xAC && id_byte[0][1] != 0x6A && - id_byte[0][1] != 0xD7) { + id_byte[0][1] != 0xD7 && + id_byte[0][1] != 0x63) { pr_err("The device not support yet!\n"); return FTL_UNSUPPORTED_FLASH; @@ -511,6 +512,11 @@ u32 nandc_flash_init(void __iomem *nandc_addr) nand_para.sec_per_page = 16; nand_para.page_per_blk = 128; nand_para.plane_per_die = 2; + } else if (id_byte[0][1] == 0x63 && id_byte[0][3] == 0x19) { /* IS34ML08G088 */ + nand_para.sec_per_page = 8; + nand_para.page_per_blk = 64; + nand_para.plane_per_die = 2; + nand_para.blk_per_plane = 2048; } flash_die_info_init(); flash_bch_sel(nand_para.ecc_bits); diff --git a/u-boot/drivers/rkflash/sfc_nand.c b/u-boot/drivers/rkflash/sfc_nand.c index ae5c999bec..4de03a6816 100644 --- a/u-boot/drivers/rkflash/sfc_nand.c +++ b/u-boot/drivers/rkflash/sfc_nand.c @@ -74,18 +74,22 @@ static struct nand_info spi_nand_tbl[] = { { 0xC8, 0x55, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status2 }, /* GD5F1GQ4UExxH */ { 0xC8, 0xD9, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, - /* GD5F1GQ5REYIG */ - { 0xC8, 0x41, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, + /* GD5F1GQ5REYIG Add 3rd code to distingush with F50L2G41KA */ + { 0xC8, 0x41, 0xC8, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, /* GD5F2GQ5REYIG */ { 0xC8, 0x42, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, /* GD5F2GM7RxG */ - { 0xC8, 0x82, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, + { 0xC8, 0x82, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, /* GD5F2GM7UxG */ - { 0xC8, 0x92, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, + { 0xC8, 0x92, 0x00, 4, 0x40, 1, 2048, 0x0C, 19, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, /* GD5F1GM7UxG */ - { 0xC8, 0x91, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status2 }, + { 0xC8, 0x91, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, /* GD5F4GQ4UAYIG 1*4096 */ { 0xC8, 0xF4, 0x00, 4, 0x40, 2, 2048, 0x0C, 20, 0x8, 1, { 0x04, 0x08, 0x14, 0x18 }, &sfc_nand_get_ecc_status0 }, + /* GD5F1GM7REYIGR */ + { 0xC8, 0x81, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, + /* GD5F4GM8UEYIGR */ + { 0xC8, 0x95, 0x00, 4, 0x40, 1, 4096, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status3 }, /* W25N01GV */ { 0xEF, 0xAA, 0x21, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x14, 0x24, 0xFF }, &sfc_nand_get_ecc_status1 }, @@ -137,6 +141,10 @@ static struct nand_info spi_nand_tbl[] = { { 0xCD, 0x70, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* F35UQA512M */ { 0xCD, 0x60, 0x00, 4, 0x40, 1, 512, 0x4C, 17, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, + /* F35UQA002G-WWT */ + { 0xCD, 0x62, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, + /* F35UQA001G-WWT */ + { 0xCD, 0x61, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* DS35Q1GA-IB */ { 0xE5, 0x71, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, @@ -158,6 +166,8 @@ static struct nand_info spi_nand_tbl[] = { { 0xE5, 0xF5, 0x00, 4, 0x40, 1, 512, 0x0C, 17, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, /* DS35M12B-IB */ { 0xE5, 0xA5, 0x00, 4, 0x40, 1, 512, 0x0C, 17, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + /* DS35Q1GD-IB */ + { 0xE5, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, /* EM73C044VCC-H */ { 0xD5, 0x22, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x8, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, @@ -186,6 +196,18 @@ static struct nand_info spi_nand_tbl[] = { { 0x0B, 0x13, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status7 }, /* XT26G11C */ { 0x0B, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, + /* XT26Q02DWSIGA */ + { 0x0B, 0x52, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, + /* XT26Q01DWSIGA */ + { 0x0B, 0x51, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, + /* XT26Q04DWSIGA */ + { 0x0B, 0x53, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 }, + /* XT26G01DWSIGA */ + { 0x0B, 0x31, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, + /* XT26G02DWSIGA */ + { 0x0B, 0x32, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, + /* XT26G04DWSIGA */ + { 0x0B, 0x33, 0x00, 8, 0x40, 1, 2048, 0x4C, 20, 0x8, 1, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status0 }, /* MT29F2G01ABA, XT26G02E, F50L2G41XA */ { 0x2C, 0x24, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x8, 0, { 0x20, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, @@ -200,11 +222,27 @@ static struct nand_info spi_nand_tbl[] = { { 0xA1, 0xE5, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x1, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* FM25LS01 */ { 0xA1, 0xA5, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, + /* FM25S01BI3 */ + { 0xA1, 0xD4, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + /* FM25G02BI3 */ + { 0xA1, 0xD2, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, /* IS37SML01G1 */ { 0xC8, 0x21, 0x00, 4, 0x40, 1, 1024, 0x00, 18, 0x1, 0, { 0x08, 0x0C, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* F50L1G41LB */ { 0xC8, 0x01, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x1, 0, { 0x14, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, + /* F50L2G41KA */ + { 0xC8, 0x41, 0x7F, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + + /* UM19A1HISW */ + { 0xB0, 0x24, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + /* UM19A0HCSW */ + { 0xB0, 0x14, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + /* UM19A0LCSW */ + { 0xB0, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + /* UM19A1LISW */ + { 0xB0, 0x25, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status6 }, + /* ATO25D1GA */ { 0x9B, 0x12, 0x00, 4, 0x40, 1, 1024, 0x40, 18, 0x1, 1, { 0x14, 0x24, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* BWJX08K-2Gb */ @@ -215,16 +253,23 @@ static struct nand_info spi_nand_tbl[] = { { 0xEA, 0xC1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* TX25G01 */ { 0xA1, 0xF1, 0x00, 4, 0x40, 1, 1024, 0x0C, 18, 0x4, 1, { 0x04, 0x14, 0xFF, 0xFF }, &sfc_nand_get_ecc_status8 }, - /* ANV1GCP0CLG, HYF1GQ4UTXCAE */ + + /* S35ML01G3, ANV1GCP0CLG, HYF1GQ4UTXCAE, YX25G1E */ { 0x01, 0x15, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status9 }, - /* S35ML02G3, ANV1GCP0CLG */ + /* S35ML02G3, ANV2GCP0CLG, HYF2GQ4UTXCAE, YX25G2E */ { 0x01, 0x25, 0x00, 4, 0x40, 2, 1024, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status9 }, /* S35ML04G3 */ { 0x01, 0x35, 0x00, 4, 0x40, 2, 2048, 0x4C, 20, 0x4, 0, { 0x04, 0x08, 0x0C, 0x10 }, &sfc_nand_get_ecc_status9 }, + /* GSS01GSAK1 */ { 0x52, 0xBA, 0x13, 4, 0x40, 1, 1024, 0x4C, 18, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, /* GSS02GSAK1 */ { 0x52, 0xBA, 0x23, 4, 0x40, 1, 2048, 0x4C, 19, 0x4, 0, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status1 }, + + /* XCSP2AAPK */ + { 0x8C, 0xA1, 0x00, 4, 0x40, 1, 2048, 0x4C, 19, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, + /* XCSP1AAPK */ + { 0x8C, 0x01, 0x00, 4, 0x40, 1, 1024, 0x4C, 18, 0x8, 1, { 0x04, 0x08, 0xFF, 0xFF }, &sfc_nand_get_ecc_status0 }, }; static struct nand_info *p_nand_info; @@ -947,6 +992,9 @@ u32 sfc_nand_read(u32 row, u32 *p_page_buf, u32 column, u32 len) sfc_nand_rw_preset(); sfc_nand_wait_busy(&status, 1000 * 1000); + if (sfc_nand_dev.manufacturer == 0x01 && status) + sfc_nand_wait_busy(&status, 1000 * 1000); + ecc_result = p_nand_info->ecc_status(); op.sfcmd.d32 = 0; diff --git a/u-boot/drivers/rkflash/sfc_nor.c b/u-boot/drivers/rkflash/sfc_nor.c index 6471efaf90..94867b38be 100644 --- a/u-boot/drivers/rkflash/sfc_nor.c +++ b/u-boot/drivers/rkflash/sfc_nor.c @@ -40,6 +40,10 @@ static struct flash_info spi_flash_tbl[] = { { 0xc8671A, 128, 8, 0x13, 0x12, 0x6C, 0x34, 0x21, 0xDC, 0x1C, 17, 0, 0 }, /* GD55LB01GEFIRR */ { 0xc8671B, 128, 8, 0x13, 0x12, 0x6C, 0x34, 0x21, 0xDC, 0x1C, 18, 0, 0 }, + /* GD55LT01GEFIRT */ + { 0xc8661B, 128, 8, 0x13, 0x12, 0x6C, 0x34, 0x21, 0xDC, 0x1C, 18, 0, 0 }, + /* GD25LB256EYIGR */ + { 0xc86719, 128, 8, 0x13, 0x12, 0x6C, 0x34, 0x21, 0xDC, 0x1C, 16, 0, 0 }, /* W25Q32JV */ { 0xef4016, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 13, 9, 0 }, @@ -152,6 +156,8 @@ static struct flash_info spi_flash_tbl[] = { { 0x852018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0 }, /* PY25Q256H */ { 0x852019, 128, 8, 0x13, 0x12, 0x6C, 0x34, 0x21, 0xDC, 0x1C, 16, 9, 0 }, + /* PY25Q128LA */ + { 0x856518, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0 }, /* ZB25VQ64 */ { 0x5e4017, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 9, 0 }, @@ -160,7 +166,7 @@ static struct flash_info spi_flash_tbl[] = { /* ZB25LQ128 */ { 0x5e5018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0 }, - /* BH25Q128AS */ + /* BH25Q128AS, BY25Q128AS */ { 0x684018, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 9, 0 }, /* BH25Q64BS */ { 0x684017, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 14, 9, 0 }, @@ -195,6 +201,9 @@ static struct flash_info spi_flash_tbl[] = { /* NM25Q128EVB */ { 0x522118, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 15, 10, 0 }, + + /* GT25Q40D */ + { 0xc44013, 128, 8, 0x03, 0x02, 0x6B, 0x32, 0x20, 0xD8, 0x0C, 10, 9, 0 }, }; static int snor_write_en(void) diff --git a/u-boot/drivers/serial/serial-uclass.c b/u-boot/drivers/serial/serial-uclass.c index c9ba9e2ad8..2026d7df87 100644 --- a/u-boot/drivers/serial/serial-uclass.c +++ b/u-boot/drivers/serial/serial-uclass.c @@ -116,7 +116,7 @@ static void serial_find_console_or_panic(void) #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)) { + (!uclass_first_device_check(UCLASS_SERIAL, &dev) && dev)) { gd->cur_serial_dev = dev; return; } diff --git a/u-boot/drivers/spi/rockchip_sfc.c b/u-boot/drivers/spi/rockchip_sfc.c index 13e4ab01ac..5e8c680da6 100644 --- a/u-boot/drivers/spi/rockchip_sfc.c +++ b/u-boot/drivers/spi/rockchip_sfc.c @@ -81,7 +81,7 @@ #define SFC_FSR_TX_IS_EMPTY BIT(1) #define SFC_FSR_RX_IS_EMPTY BIT(2) #define SFC_FSR_RX_IS_FULL BIT(3) -#define SFC_FSR_TXLV_MASK GENMASK(12, 8) +#define SFC_FSR_TXLV_MASK GENMASK(13, 8) #define SFC_FSR_TXLV_SHIFT 8 #define SFC_FSR_RXLV_MASK GENMASK(20, 16) #define SFC_FSR_RXLV_SHIFT 16 @@ -149,11 +149,9 @@ /* Data */ #define SFC_DATA 0x108 -/* The controller and documentation reports that it supports up to 4 CS - * devices (0-3), however I have only been able to test a single CS (CS 0) - * due to the configuration of my device. - */ -#define SFC_MAX_CHIPSELECT_NUM 4 +#define SFC_CS1_REG_OFFSET 0x200 + +#define SFC_MAX_CHIPSELECT_NUM 2 /* The SFC can transfer max 16KB - 1 at one time * we set it to 15.5KB here for alignment. @@ -180,14 +178,16 @@ struct rockchip_sfc { struct clk hclk; struct clk clk; u32 max_freq; - u32 speed; + u32 cur_speed; + u32 cur_real_speed; + u32 speed[SFC_MAX_CHIPSELECT_NUM]; bool use_dma; u32 max_iosize; u16 version; u32 last_async_size; u32 async; - u32 dll_cells; + u32 dll_cells[SFC_MAX_CHIPSELECT_NUM]; u32 max_dll_cells; }; @@ -202,11 +202,13 @@ static int rockchip_sfc_reset(struct rockchip_sfc *sfc) !(status & SFC_RCVR_RESET), 1000000); if (err) - printf("SFC reset never finished\n"); + dev_err(sfc->dev, "SFC reset never finished\n"); /* Still need to clear the masked interrupt from RISR */ writel(0xFFFFFFFF, sfc->regbase + SFC_ICLR); + dev_dbg(sfc->dev, "reset\n"); + return err; } @@ -217,7 +219,7 @@ static u16 rockchip_sfc_get_version(struct rockchip_sfc *sfc) static u32 rockchip_sfc_get_max_iosize(struct rockchip_sfc *sfc) { - if (rockchip_sfc_get_version(sfc) >= SFC_VER_4) + if (sfc->version >= SFC_VER_4) return SFC_MAX_IOSIZE_VER4; return SFC_MAX_IOSIZE_VER3; @@ -225,19 +227,15 @@ static u32 rockchip_sfc_get_max_iosize(struct rockchip_sfc *sfc) static u32 rockchip_sfc_get_max_dll_cells(struct rockchip_sfc *sfc) { - switch (rockchip_sfc_get_version(sfc)) { - case SFC_VER_8: - case SFC_VER_6: - case SFC_VER_5: + if (sfc->version > SFC_VER_4) return SFC_DLL_CTRL0_DLL_MAX_VER5; - case SFC_VER_4: + else if (sfc->version == SFC_VER_4) return SFC_DLL_CTRL0_DLL_MAX_VER4; - default: + else return 0; - } } -static __maybe_unused void rockchip_sfc_set_delay_lines(struct rockchip_sfc *sfc, u16 cells) +static __maybe_unused void rockchip_sfc_set_delay_lines(struct rockchip_sfc *sfc, u16 cells, u8 cs) { u16 cell_max = (u16)rockchip_sfc_get_max_dll_cells(sfc); u32 val = 0; @@ -248,7 +246,7 @@ static __maybe_unused void rockchip_sfc_set_delay_lines(struct rockchip_sfc *sfc if (cells) val = SFC_DLL_CTRL0_SCLK_SMP_DLL | cells; - writel(val, sfc->regbase + SFC_DLL_CTRL0); + writel(val, sfc->regbase + cs * SFC_CS1_REG_OFFSET + SFC_DLL_CTRL0); } static int rockchip_sfc_init(struct rockchip_sfc *sfc) @@ -302,13 +300,14 @@ static int rockchip_sfc_probe(struct udevice *bus) if (ret) dev_dbg(sfc->dev, "sfc Enable clock fail for %s: %d\n", bus->name, ret); #endif + /* Initial the version at the first */ + sfc->version = rockchip_sfc_get_version(sfc); ret = rockchip_sfc_init(sfc); if (ret) goto err_init; sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc); - sfc->version = rockchip_sfc_get_version(sfc); sfc->max_freq = SFC_MAX_SPEED; sfc->dev = bus; @@ -399,7 +398,7 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, const struct spi_mem_op *op, u32 len) { - struct dm_spi_slave_platdata *plat = dev_get_platdata(sfc->dev); + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(mem->dev); u32 ctrl = 0, cmd = 0; /* set CMD */ @@ -414,7 +413,7 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, cmd |= SFC_CMD_ADDR_24BITS << SFC_CMD_ADDR_SHIFT; } else { cmd |= SFC_CMD_ADDR_XBITS << SFC_CMD_ADDR_SHIFT; - writel(op->addr.nbytes * 8 - 1, sfc->regbase + SFC_ABIT); + writel(op->addr.nbytes * 8 - 1, sfc->regbase + plat->cs * SFC_CS1_REG_OFFSET + SFC_ABIT); } ctrl |= ((op->addr.buswidth >> 1) << SFC_CTRL_ADDR_BITS_SHIFT); @@ -454,7 +453,7 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc, dev_dbg(sfc->dev, "sfc ctrl=%x cmd=%x addr=%llx len=%x\n", ctrl, cmd, op->addr.val, len); - writel(ctrl, sfc->regbase + SFC_CTRL); + writel(ctrl, sfc->regbase + plat->cs * SFC_CS1_REG_OFFSET + SFC_CTRL); writel(cmd, sfc->regbase + SFC_CMD); if (op->addr.nbytes) writel(op->addr.val, sfc->regbase + SFC_ADDR); @@ -613,13 +612,127 @@ static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us) return ret; } +#if CONFIG_IS_ENABLED(CLK) +static int rockchip_sfc_exec_op_bypass(struct rockchip_sfc *sfc, + struct spi_slave *mem, + const struct spi_mem_op *op) +{ + u32 len = min_t(u32, op->data.nbytes, sfc->max_iosize); + u32 ret; + + rockchip_sfc_adjust_op_work((struct spi_mem_op *)op); + rockchip_sfc_xfer_setup(sfc, mem, op, len); + ret = rockchip_sfc_xfer_data_poll(sfc, op, len); + if (ret != len) { + dev_err(sfc->dev, "xfer data failed ret %d\n", ret); + + return -EIO; + } + + return rockchip_sfc_xfer_done(sfc, 100000); +} + +static void rockchip_sfc_delay_lines_tuning(struct rockchip_sfc *sfc, struct spi_slave *mem) +{ + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(mem->dev); + struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_IN(3, NULL, 1)); + u8 id[3], id_temp[3]; + u16 cell_max = (u16)rockchip_sfc_get_max_dll_cells(sfc); + u16 right, left = 0; + u16 step = SFC_DLL_TRANING_STEP; + bool dll_valid = false; + u8 cs = plat->cs; + + clk_set_rate(&sfc->clk, SFC_DLL_THRESHOLD_RATE); + op.data.buf.in = &id; + rockchip_sfc_exec_op_bypass(sfc, mem, &op); + if ((0xFF == id[0] && 0xFF == id[1]) || + (0x00 == id[0] && 0x00 == id[1])) { + dev_dbg(sfc->dev, "no dev, dll by pass\n"); + clk_set_rate(&sfc->clk, sfc->speed[cs]); + sfc->speed[cs] = SFC_DLL_THRESHOLD_RATE; + + return; + } + + clk_set_rate(&sfc->clk, sfc->speed[cs]); + op.data.buf.in = &id_temp; + for (right = 0; right <= cell_max; right += step) { + int ret; + + rockchip_sfc_set_delay_lines(sfc, right, cs); + rockchip_sfc_exec_op_bypass(sfc, mem, &op); + dev_dbg(sfc->dev, "dll read flash id:%x %x %x\n", + id_temp[0], id_temp[1], id_temp[2]); + + ret = memcmp(&id, &id_temp, 3); + if (dll_valid && ret) { + right -= step; + + break; + } + if (!dll_valid && !ret) + left = right; + + if (!ret) + dll_valid = true; + + /* Add cell_max to loop */ + if (right == cell_max) + break; + if (right + step > cell_max) + right = cell_max - step; + } + + if (dll_valid && (right - left) >= SFC_DLL_TRANING_VALID_WINDOW) { + if (left == 0 && right < cell_max) + sfc->dll_cells[cs] = left + (right - left) * 2 / 5; + else + sfc->dll_cells[cs] = left + (right - left) / 2; + } else { + sfc->dll_cells[cs] = 0; + } + + if (sfc->dll_cells[cs]) { + dev_dbg(sfc->dev, "%d %d %d dll training success in %dMHz max_cells=%u sfc_ver=%d\n", + left, right, sfc->dll_cells[cs], sfc->speed[cs], + rockchip_sfc_get_max_dll_cells(sfc), rockchip_sfc_get_version(sfc)); + rockchip_sfc_set_delay_lines(sfc, (u16)sfc->dll_cells[cs], cs); + } else { + dev_err(sfc->dev, "%d %d dll training failed in %dMHz, reduce the speed\n", + left, right, sfc->speed[cs]); + rockchip_sfc_set_delay_lines(sfc, 0, cs); + clk_set_rate(&sfc->clk, SFC_DLL_THRESHOLD_RATE); + sfc->cur_speed = SFC_DLL_THRESHOLD_RATE; + sfc->cur_real_speed = clk_get_rate(&sfc->clk); + sfc->speed[cs] = SFC_DLL_THRESHOLD_RATE; + } +} + +#endif + static int rockchip_sfc_exec_op(struct spi_slave *mem, const struct spi_mem_op *op) { struct rockchip_sfc *sfc = dev_get_platdata(mem->dev->parent); + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(mem->dev); u32 len = min_t(u32, op->data.nbytes, sfc->max_iosize); int ret; + if (rockchip_sfc_get_version(sfc) >= SFC_VER_4 && + sfc->cur_speed != sfc->speed[plat->cs]) { + sfc->speed[plat->cs] = sfc->cur_speed; +#if CONFIG_IS_ENABLED(CLK) + if (sfc->cur_real_speed > SFC_DLL_THRESHOLD_RATE) + rockchip_sfc_delay_lines_tuning(sfc, mem); + else +#endif + rockchip_sfc_set_delay_lines(sfc, 0, plat->cs); + } + /* Wait for last async transfer finished */ if (sfc->last_async_size) { rockchip_sfc_wait_for_dma_finished(sfc, sfc->last_async_size); @@ -655,103 +768,6 @@ static int rockchip_sfc_adjust_op_size(struct spi_slave *mem, struct spi_mem_op return 0; } -#if CONFIG_IS_ENABLED(CLK) -static int rockchip_sfc_exec_op_bypass(struct rockchip_sfc *sfc, - struct spi_slave *mem, - const struct spi_mem_op *op) -{ - u32 len = min_t(u32, op->data.nbytes, sfc->max_iosize); - u32 ret; - - rockchip_sfc_adjust_op_work((struct spi_mem_op *)op); - rockchip_sfc_xfer_setup(sfc, mem, op, len); - ret = rockchip_sfc_xfer_data_poll(sfc, op, len); - if (ret != len) { - dev_err(sfc->dev, "xfer data failed ret %d\n", ret); - - return -EIO; - } - - return rockchip_sfc_xfer_done(sfc, 100000); -} - -static void rockchip_sfc_delay_lines_tuning(struct rockchip_sfc *sfc, struct spi_slave *mem) -{ - struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x9F, 1), - SPI_MEM_OP_NO_ADDR, - SPI_MEM_OP_NO_DUMMY, - SPI_MEM_OP_DATA_IN(3, NULL, 1)); - u8 id[3], id_temp[3]; - u16 cell_max = (u16)rockchip_sfc_get_max_dll_cells(sfc); - u16 right, left = 0; - u16 step = SFC_DLL_TRANING_STEP; - bool dll_valid = false; - - clk_set_rate(&sfc->clk, SFC_DLL_THRESHOLD_RATE); - op.data.buf.in = &id; - rockchip_sfc_exec_op_bypass(sfc, mem, &op); - if ((0xFF == id[0] && 0xFF == id[1]) || - (0x00 == id[0] && 0x00 == id[1])) { - dev_dbg(sfc->dev, "no dev, dll by pass\n"); - clk_set_rate(&sfc->clk, sfc->speed); - - return; - } - - clk_set_rate(&sfc->clk, sfc->speed); - op.data.buf.in = &id_temp; - for (right = 0; right <= cell_max; right += step) { - int ret; - - rockchip_sfc_set_delay_lines(sfc, right); - rockchip_sfc_exec_op_bypass(sfc, mem, &op); - dev_dbg(sfc->dev, "dll read flash id:%x %x %x\n", - id_temp[0], id_temp[1], id_temp[2]); - - ret = memcmp(&id, &id_temp, 3); - if (dll_valid && ret) { - right -= step; - - break; - } - if (!dll_valid && !ret) - left = right; - - if (!ret) - dll_valid = true; - - /* Add cell_max to loop */ - if (right == cell_max) - break; - if (right + step > cell_max) - right = cell_max - step; - } - - if (dll_valid && (right - left) >= SFC_DLL_TRANING_VALID_WINDOW) { - if (left == 0 && right < cell_max) - sfc->dll_cells = left + (right - left) * 2 / 5; - else - sfc->dll_cells = left + (right - left) / 2; - } else { - sfc->dll_cells = 0; - } - - if (sfc->dll_cells) { - dev_dbg(sfc->dev, "%d %d %d dll training success in %dMHz max_cells=%u sfc_ver=%d\n", - left, right, sfc->dll_cells, sfc->speed, - rockchip_sfc_get_max_dll_cells(sfc), rockchip_sfc_get_version(sfc)); - rockchip_sfc_set_delay_lines(sfc, (u16)sfc->dll_cells); - } else { - dev_err(sfc->dev, "%d %d dll training failed in %dMHz, reduce the speed\n", - left, right, sfc->speed); - rockchip_sfc_set_delay_lines(sfc, 0); - clk_set_rate(&sfc->clk, SFC_DLL_THRESHOLD_RATE); - sfc->speed = clk_get_rate(&sfc->clk); - } -} - -#endif - static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) { struct rockchip_sfc *sfc = dev_get_platdata(bus); @@ -759,7 +775,7 @@ static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) if (speed > sfc->max_freq) speed = sfc->max_freq; - if (speed == sfc->speed) + if (speed == sfc->cur_speed) return 0; #if CONFIG_IS_ENABLED(CLK) @@ -770,16 +786,11 @@ static int rockchip_sfc_set_speed(struct udevice *bus, uint speed) speed); return ret; } - sfc->speed = speed; - if (rockchip_sfc_get_version(sfc) >= SFC_VER_4) { - if (clk_get_rate(&sfc->clk) > SFC_DLL_THRESHOLD_RATE) - rockchip_sfc_delay_lines_tuning(sfc, NULL); - else - rockchip_sfc_set_delay_lines(sfc, 0); - } + sfc->cur_speed = speed; + sfc->cur_real_speed = clk_get_rate(&sfc->clk); - dev_dbg(sfc->dev, "set_freq=%dHz real_freq=%ldHz\n", - sfc->speed, clk_get_rate(&sfc->clk)); + dev_dbg(sfc->dev, "set_freq=%dHz real_freq=%dHz\n", + sfc->cur_speed, sfc->cur_real_speed); #else dev_dbg(sfc->dev, "sfc failed, CLK not support\n"); #endif diff --git a/u-boot/drivers/usb/common/common.c b/u-boot/drivers/usb/common/common.c index 467cc01f6f..6fb1b1d049 100644 --- a/u-boot/drivers/usb/common/common.c +++ b/u-boot/drivers/usb/common/common.c @@ -49,6 +49,13 @@ static const char *const speed_names[] = { [USB_SPEED_SUPER] = "super-speed", }; +const char *usb_speed_string(enum usb_device_speed speed) +{ + if (speed < 0 || speed >= ARRAY_SIZE(speed_names)) + speed = USB_SPEED_UNKNOWN; + return speed_names[speed]; +} + enum usb_device_speed usb_get_maximum_speed(ofnode node) { const char *max_speed; diff --git a/u-boot/drivers/usb/dwc3/core.c b/u-boot/drivers/usb/dwc3/core.c index ca14bab386..6f5e5249d0 100644 --- a/u-boot/drivers/usb/dwc3/core.c +++ b/u-boot/drivers/usb/dwc3/core.c @@ -30,6 +30,7 @@ #include "io.h" #include "linux-compat.h" +#include "rockusb.h" DECLARE_GLOBAL_DATA_PTR; @@ -724,6 +725,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) */ hird_threshold = 12; + dwc->check_linksts = true; + dwc->ts = get_timer(0); dwc->maximum_speed = dwc3_dev->maximum_speed; dwc->has_lpm_erratum = dwc3_dev->has_lpm_erratum; if (dwc3_dev->lpm_nyet_threshold) @@ -754,6 +757,9 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) /* default to superspeed if no maximum_speed passed */ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) dwc->maximum_speed = USB_SPEED_SUPER; + else if (dwc->maximum_speed == USB_SPEED_SUPER && + rkusb_force_usb2_enabled()) + dwc->maximum_speed = USB_SPEED_HIGH; dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; diff --git a/u-boot/drivers/usb/dwc3/core.h b/u-boot/drivers/usb/dwc3/core.h index a67c899436..5b0255bc77 100644 --- a/u-boot/drivers/usb/dwc3/core.h +++ b/u-boot/drivers/usb/dwc3/core.h @@ -844,6 +844,9 @@ struct dwc3 { unsigned tx_de_emphasis:2; unsigned usb2_phyif_utmi_width:5; int index; + u64 ts; + u8 connected; + bool check_linksts; struct list_head list; }; diff --git a/u-boot/drivers/usb/dwc3/ep0.c b/u-boot/drivers/usb/dwc3/ep0.c index 8b98391ab9..ad806defbb 100644 --- a/u-boot/drivers/usb/dwc3/ep0.c +++ b/u-boot/drivers/usb/dwc3/ep0.c @@ -511,6 +511,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) return -EINVAL; } + dwc->connected = 1; reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg &= ~(DWC3_DCFG_DEVADDR_MASK); reg |= DWC3_DCFG_DEVADDR(addr); diff --git a/u-boot/drivers/usb/dwc3/gadget.c b/u-boot/drivers/usb/dwc3/gadget.c index 1f8d464935..dbbb889ece 100644 --- a/u-boot/drivers/usb/dwc3/gadget.c +++ b/u-boot/drivers/usb/dwc3/gadget.c @@ -730,10 +730,10 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, * for OUT endpoints, the total size of a Buffer Descriptor must be a * multiple of MaxPacketSize. So amend the TRB size to apply this rule. */ - if (usb_endpoint_dir_out(dep->endpoint.desc)) { + if (usb_endpoint_dir_out(dep->endpoint.desc) && + (length % dep->endpoint.maxpacket)) length = dep->endpoint.maxpacket * - ((length - 1) / dep->endpoint.maxpacket + 1); - } + ((length - 1) / dep->endpoint.maxpacket + 1); trb->size = DWC3_TRB_SIZE_LENGTH(length); trb->bpl = lower_32_bits(dma); @@ -1566,6 +1566,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g) __dwc3_gadget_ep_disable(dwc->eps[1]); dwc->gadget_driver = NULL; + dwc->connected = 0; spin_unlock_irqrestore(&dwc->lock, flags); @@ -1695,6 +1696,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, unsigned int count; unsigned int s_pkt = 0; unsigned int trb_status; + unsigned int length; if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) /* @@ -1751,7 +1753,14 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, * should receive and we simply bounce the request back to the * gadget driver for further processing. */ - req->request.actual += req->request.length - count; + if (usb_endpoint_dir_out(dep->endpoint.desc) && + (req->request.length % dep->endpoint.maxpacket)) { + length = dep->endpoint.maxpacket * + ((req->request.length - 1) / dep->endpoint.maxpacket + 1); + req->request.actual += length - count; + } else { + req->request.actual += req->request.length - count; + } if (s_pkt) return 1; if ((event->status & DEPEVT_STATUS_LST) && @@ -2211,6 +2220,9 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) break; } + dev_info(dwc->dev, "usb device is %s\n", + usb_speed_string(dwc->gadget.speed)); + /* Enable USB2 LPM Capability */ if ((dwc->revision > DWC3_REVISION_194A) @@ -2284,6 +2296,11 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; unsigned int pwropt; + if (dwc->link_state == DWC3_LINK_STATE_POLL && dwc->check_linksts) { + dwc->check_linksts = false; + dwc->ts = get_timer(0); + } + /* * WORKAROUND: DWC3 < 2.50a have an issue when configured without * Hibernation mode enabled which would show up when device detects @@ -2576,6 +2593,33 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) return ret; } +struct dwc3 *the_controller; +#define WAIT_USB_CONN_TIMEOUT (3 * CONFIG_SYS_HZ) + +bool dwc3_gadget_is_connected(void) +{ + struct dwc3 *dev = the_controller; + + /* + * If the speed is super-speed and wait device + * connection time out, it means that usb3 + * enumeration failed. And in a special case, + * if the usb3 host rx-termination is present, + * but host doesn't send LFPS (e.g usb3 host + * initialized fail), this cause dwc3 usb fail + * to detect speed and the speed will be unknown. + */ + if ((dev->gadget.speed == USB_SPEED_UNKNOWN || + dev->gadget.speed == USB_SPEED_SUPER) && + !dev->connected) { + debug("ts %ld\n", get_timer(dev->ts)); + if (get_timer(dev->ts) > WAIT_USB_CONN_TIMEOUT) + return false; + } + + return true; +} + /** * dwc3_gadget_init - Initializes gadget related registers * @dwc: pointer to our controller context structure @@ -2585,6 +2629,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) int dwc3_gadget_init(struct dwc3 *dwc) { int ret; + the_controller = dwc; dwc->ctrl_req = dma_alloc_coherent(sizeof(*dwc->ctrl_req), (unsigned long *)&dwc->ctrl_req_addr); diff --git a/u-boot/drivers/usb/gadget/composite.c b/u-boot/drivers/usb/gadget/composite.c index 89341e8832..76dbd95006 100644 --- a/u-boot/drivers/usb/gadget/composite.c +++ b/u-boot/drivers/usb/gadget/composite.c @@ -838,11 +838,15 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) * bcdUSB should be 0x0300 for superspeed, * but we change it to 0x0301 for rockusb. */ +#ifndef CONFIG_SUPPORT_USBPLUG if (!strncmp(cdev->driver->name, "rkusb_ums_dnl", 13)) cdev->desc.bcdUSB = cpu_to_le16(0x0301); else cdev->desc.bcdUSB = cpu_to_le16(0x0300); +#else + cdev->desc.bcdUSB = cpu_to_le16(0x0300); +#endif cdev->desc.bMaxPacketSize0 = 9; } else { cdev->desc.bMaxPacketSize0 = diff --git a/u-boot/drivers/usb/gadget/ether.c b/u-boot/drivers/usb/gadget/ether.c index 0c6b0fca53..0d3b1241d9 100644 --- a/u-boot/drivers/usb/gadget/ether.c +++ b/u-boot/drivers/usb/gadget/ether.c @@ -2679,10 +2679,10 @@ int usb_ether_init(void) struct udevice *usb_dev; int ret; - ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev); - if (!usb_dev || ret) { + uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev); + if (!usb_dev) { pr_err("No USB device found\n"); - return ret; + return -ENODEV; } ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", &dev); diff --git a/u-boot/drivers/usb/gadget/f_mass_storage.c b/u-boot/drivers/usb/gadget/f_mass_storage.c index 8f6d055f07..9437d86586 100644 --- a/u-boot/drivers/usb/gadget/f_mass_storage.c +++ b/u-boot/drivers/usb/gadget/f_mass_storage.c @@ -319,6 +319,7 @@ struct fsg_common { u32 tag; u32 residue; u32 usb_amount_left; + u32 usb_trb_size; /* usb transfer size */ unsigned int can_stall:1; unsigned int free_storage_on_release:1; @@ -674,6 +675,12 @@ static int sleep_thread(struct fsg_common *common) k = 0; } +#ifdef CONFIG_USB_DWC3_GADGET + if (rkusb_usb3_capable() && !dwc3_gadget_is_connected() + && !rkusb_force_usb2_enabled()) + return -ENODEV; +#endif + usb_gadget_handle_interrupts(0); } common->thread_wakeup_needed = 0; @@ -730,7 +737,7 @@ static int do_read(struct fsg_common *common) * the next page. * If this means reading 0 then we were asked to read past * the end of file. */ - amount = min(amount_left, FSG_BUFLEN); + amount = min(amount_left, common->usb_trb_size); partial_page = file_offset & (PAGE_CACHE_SIZE - 1); if (partial_page > 0) amount = min(amount, (unsigned int) PAGE_CACHE_SIZE - @@ -870,7 +877,7 @@ static int do_write(struct fsg_common *common) * If this means getting 0, then we were asked * to write past the end of file. * Finally, round down to a block boundary. */ - amount = min(amount_left_to_req, FSG_BUFLEN); + amount = min(amount_left_to_req, common->usb_trb_size); partial_page = usb_offset & (PAGE_CACHE_SIZE - 1); if (partial_page > 0) amount = min(amount, @@ -1042,7 +1049,7 @@ static int do_verify(struct fsg_common *common) * And don't try to read past the end of the file. * If this means reading 0 then we were asked to read * past the end of file. */ - amount = min(amount_left, FSG_BUFLEN); + amount = min(amount_left, common->usb_trb_size); if (amount == 0) { curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; @@ -1437,7 +1444,8 @@ static int pad_with_zeros(struct fsg_dev *fsg) return rc; } - nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); + nsend = min(fsg->common->usb_amount_left, + fsg->common->usb_trb_size); memset(bh->buf + nkeep, 0, nsend - nkeep); bh->inreq->length = nsend; bh->inreq->zero = 0; @@ -1479,7 +1487,8 @@ static int throw_away_data(struct fsg_common *common) bh = common->next_buffhd_to_fill; if (bh->state == BUF_STATE_EMPTY && common->usb_amount_left > 0) { - amount = min(common->usb_amount_left, FSG_BUFLEN); + amount = min(common->usb_amount_left, + common->usb_trb_size); /* amount is always divisible by 512, hence by * the bulk-out maxpacket size */ @@ -2496,6 +2505,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, common->gadget = gadget; common->ep0 = gadget->ep0; common->ep0req = cdev->req; + common->usb_trb_size = FSG_BUFLEN; /* Maybe allocate device-global string IDs, and patch descriptors */ if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { diff --git a/u-boot/drivers/usb/gadget/f_rockusb.c b/u-boot/drivers/usb/gadget/f_rockusb.c index 7547c7ca6f..a40cd54892 100644 --- a/u-boot/drivers/usb/gadget/f_rockusb.c +++ b/u-boot/drivers/usb/gadget/f_rockusb.c @@ -14,6 +14,11 @@ #include #include #include +#include +#include +#include +#include +#include #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION #include @@ -174,17 +179,39 @@ static int rkusb_do_reset(struct fsg_common *common, return 0; } +__weak bool rkusb_usb3_capable(void) +{ + return false; +} + +static int rkusb_do_switch_to_usb3(struct fsg_common *common, + struct fsg_buffhd *bh) +{ + g_dnl_set_serialnumber((char *)&common->cmnd[1]); + rkusb_switch_to_usb3_enable(true); + bh->state = BUF_STATE_EMPTY; + + return 0; +} + static int rkusb_do_test_unit_ready(struct fsg_common *common, struct fsg_buffhd *bh) { struct blk_desc *desc = &ums[common->lun].block_dev; + u32 usb_trb_size; + u16 residue; if ((desc->if_type == IF_TYPE_MTD && desc->devnum == BLK_MTD_SPI_NOR) || desc->if_type == IF_TYPE_SPINOR) - common->residue = 0x03 << 24; /* 128KB Max block xfer for SPI Nor */ + residue = 0x03; /* 128KB Max block xfer for SPI Nor */ + else if (common->cmnd[1] == 0xf7 && FSG_BUFLEN >= 0x400000) + residue = 0x0a; /* Max block xfer for USB DWC3 */ else - common->residue = 0x06 << 24; /* Max block xfer support from host */ + residue = 0x06; /* Max block xfer support from host */ + usb_trb_size = (1 << residue) * 4096; + common->usb_trb_size = min(usb_trb_size, FSG_BUFLEN); + common->residue = residue << 24; common->data_dir = DATA_DIR_NONE; bh->state = BUF_STATE_EMPTY; @@ -475,6 +502,7 @@ static int rkusb_do_vs_write(struct fsg_common *common) data = bh->buf + sizeof(struct vendor_item); if (!type) { + #ifndef CONFIG_SUPPORT_USBPLUG if (vhead->id == HDCP_14_HDMI_ID || vhead->id == HDCP_14_HDMIRX_ID || vhead->id == HDCP_14_DP_ID) { @@ -484,6 +512,7 @@ static int rkusb_do_vs_write(struct fsg_common *common) return -EIO; } } + #endif /* Vendor storage */ rc = vendor_storage_write(vhead->id, @@ -542,6 +571,30 @@ static int rkusb_do_vs_write(struct fsg_common *common) curlun->sense_data = SS_WRITE_ERROR; return -EIO; } + } else if (memcmp(data, "ENDA", 4) == 0) { + if (vhead->size - 8 != 16) { + printf("check oem encrypt data size fail!\n"); + curlun->sense_data = SS_WRITE_ERROR; + return -EIO; + } + if (trusty_write_oem_encrypt_data((uint32_t *)(data + 8), 4) != 0) { + printf("trusty_write_oem_encrypt_data error!"); + curlun->sense_data = SS_WRITE_ERROR; + return -EIO; + } + } else if (memcmp(data, "OTPK", 4) == 0) { + uint32_t key_len = vhead->size - 9; + uint8_t key_id = *((uint8_t *)data + 8); + if (key_len != 16 && key_len != 24 && key_len != 32) { + printf("check oem otp key size fail!\n"); + curlun->sense_data = SS_WRITE_ERROR; + return -EIO; + } + if (trusty_write_oem_otp_key(key_id, (uint8_t *)(data + 9), key_len) != 0) { + printf("trusty_write_oem_huk error!"); + curlun->sense_data = SS_WRITE_ERROR; + return -EIO; + } } else { printf("Unknown tag\n"); curlun->sense_data = SS_WRITE_ERROR; @@ -638,6 +691,31 @@ static int rkusb_do_vs_read(struct fsg_common *common) vhead->size = rc; #else printf("Please enable CONFIG_RK_AVB_LIBAVB_USER!\n"); +#endif + } else if (type == 3) { + /* efuse or otp*/ +#ifdef CONFIG_OPTEE_CLIENT + if (vhead->id == 120) { + u8 value; + char *written_str = "key is written!"; + char *not_written_str = "key is not written!"; + if (trusty_ta_encryption_key_is_written(&value) != 0) { + printf("trusty_ta_encryption_key_is_written error!"); + return -EIO; + } + if (value) { + memcpy(data, written_str, strlen(written_str)); + vhead->size = strlen(written_str); + } else { + memcpy(data, not_written_str, strlen(not_written_str)); + vhead->size = strlen(not_written_str); + } + } else { + printf("Unknown tag\n"); + return -EIO; + } +#else + printf("Please enable CONFIG_OPTEE_CLIENT\n"); #endif } else { return -EINVAL; @@ -654,6 +732,66 @@ static int rkusb_do_vs_read(struct fsg_common *common) } #endif +static int rkusb_do_switch_storage(struct fsg_common *common) +{ + enum if_type type, cur_type = ums[common->lun].block_dev.if_type; + int devnum, cur_devnum = ums[common->lun].block_dev.devnum; + struct blk_desc *block_dev; + u32 media = BOOT_TYPE_UNKNOWN; + + media = 1 << common->cmnd[1]; + + switch (media) { +#ifdef CONFIG_MMC + case BOOT_TYPE_EMMC: + type = IF_TYPE_MMC; + devnum = 0; + mmc_initialize(gd->bd); + break; +#endif + case BOOT_TYPE_MTD_BLK_NAND: + type = IF_TYPE_MTD; + devnum = 0; + break; + case BOOT_TYPE_MTD_BLK_SPI_NAND: + type = IF_TYPE_MTD; + devnum = 1; + break; + case BOOT_TYPE_MTD_BLK_SPI_NOR: + type = IF_TYPE_MTD; + devnum = 2; + break; + default: + printf("Bootdev 0x%x is not support\n", media); + return -ENODEV; + } + + if (cur_type == type && cur_devnum == devnum) + return 0; + +#if CONFIG_IS_ENABLED(SUPPORT_USBPLUG) + block_dev = usbplug_blk_get_devnum_by_type(type, devnum); +#else + block_dev = blk_get_devnum_by_type(type, devnum); +#endif + if (!block_dev) { + printf("Bootdev if_type=%d num=%d toggle fail\n", type, devnum); + return -ENODEV; + } + + ums[common->lun].num_sectors = block_dev->lba; + ums[common->lun].block_dev = *block_dev; + + printf("RKUSB: LUN %d, dev %d, hwpart %d, sector %#x, count %#x\n", + 0, + ums[common->lun].block_dev.devnum, + ums[common->lun].block_dev.hwpart, + ums[common->lun].start_sector, + ums[common->lun].num_sectors); + + return 0; +} + static int rkusb_do_get_storage_info(struct fsg_common *common, struct fsg_buffhd *bh) { @@ -726,7 +864,12 @@ static int rkusb_do_read_capacity(struct fsg_common *common, * bit[7]: Read SecureMode * bit[8]: New IDB feature * bit[9]: Get storage media info - * bit[10:63}: Reserved. + * bit[10]: LBAwrite Parity + * bit[11]: Read Otp Data + * bit[12]: usb3 download + * bit[13]: Write OTP proof + * bit[14]: Write Cipher Key + * bit[15:63}: Reserved. */ memset((void *)&buf[0], 0, len); if (type == IF_TYPE_MMC || type == IF_TYPE_SD || type == IF_TYPE_NVME) @@ -750,6 +893,17 @@ static int rkusb_do_read_capacity(struct fsg_common *common, buf[1] |= BIT(1); /* Switch Storage */ buf[1] |= BIT(2); /* LBAwrite Parity */ + if (rkusb_usb3_capable() && !rkusb_force_usb2_enabled()) + buf[1] |= BIT(4); + else + buf[1] &= ~BIT(4); + +#ifdef CONFIG_ROCKCHIP_OTP + buf[1] |= BIT(3); /* Read Otp Data */ + buf[1] |= BIT(5); /* Write OTP proof */ + buf[1] |= BIT(6); /* Write Cipher Key */ +#endif + /* Set data xfer size */ common->residue = len; common->data_size_from_cmnd = len; @@ -757,6 +911,30 @@ static int rkusb_do_read_capacity(struct fsg_common *common, return len; } +#ifdef CONFIG_ROCKCHIP_OTP +static int rkusb_do_read_otp(struct fsg_common *common, + struct fsg_buffhd *bh) +{ + u32 len = common->data_size; + u32 type = common->cmnd[1]; + u8 *buf = (u8 *)bh->buf; + struct udevice *dev; + + buf[0] = 0; + if (type == 0) { /* soc uuid */ + if (!uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(rockchip_otp), &dev)) { + if (!misc_read(dev, CFG_CPUID_OFFSET, (void *)&buf[1], len)) + buf[0] = len; + } + } + + common->residue = len; + common->data_size_from_cmnd = len; + + return len; +} +#endif + static void rkusb_fixup_cbwcb(struct fsg_common *common, struct fsg_buffhd *bh) { @@ -857,6 +1035,10 @@ static int rkusb_cmd_process(struct fsg_common *common, rc = RKUSB_RC_FINISHED; break; #endif + case RKUSB_SWITCH_STORAGE: + *reply = rkusb_do_switch_storage(common); + rc = RKUSB_RC_FINISHED; + break; case RKUSB_GET_STORAGE_MEDIA: *reply = rkusb_do_get_storage_info(common, bh); rc = RKUSB_RC_FINISHED; @@ -867,11 +1049,23 @@ static int rkusb_cmd_process(struct fsg_common *common, rc = RKUSB_RC_FINISHED; break; + case RKUSB_SWITCH_USB3: + *reply = rkusb_do_switch_to_usb3(common, bh); + rc = RKUSB_RC_FINISHED; + break; + case RKUSB_RESET: *reply = rkusb_do_reset(common, bh); rc = RKUSB_RC_FINISHED; break; +#ifdef CONFIG_ROCKCHIP_OTP + case RKUSB_READ_OTP_DATA: + *reply = rkusb_do_read_otp(common, bh); + rc = RKUSB_RC_FINISHED; + break; +#endif + case RKUSB_READ_10: case RKUSB_WRITE_10: printf("CMD Not support, pls use new version Tool\n"); @@ -888,7 +1082,6 @@ static int rkusb_cmd_process(struct fsg_common *common, case RKUSB_SET_RESET_FLAG: case RKUSB_SPI_READ_10: case RKUSB_SPI_WRITE_10: - case RKUSB_SESSION: /* Fall through */ default: rc = RKUSB_RC_UNKNOWN_CMND; diff --git a/u-boot/drivers/usb/gadget/storage_common.c b/u-boot/drivers/usb/gadget/storage_common.c index c85a86cd2d..96ad7e544d 100644 --- a/u-boot/drivers/usb/gadget/storage_common.c +++ b/u-boot/drivers/usb/gadget/storage_common.c @@ -308,8 +308,12 @@ static struct fsg_lun *fsg_lun_from_dev(struct device *dev) /* Number of buffers we will use. 2 is enough for double-buffering */ #define FSG_NUM_BUFFERS 2 +#if defined(CONFIG_USB_DWC3_GADGET) && defined(ROCKUSB_FSG_BUFLEN) +#define FSG_BUFLEN ((u32)ROCKUSB_FSG_BUFLEN) +#else /* Default size of buffer length. */ #define FSG_BUFLEN ((u32)262144) +#endif /* Maximal number of LUNs supported in mass storage function */ #define FSG_MAX_LUNS 8 diff --git a/u-boot/drivers/video/drm/Kconfig b/u-boot/drivers/video/drm/Kconfig index cc27f66834..8b80d60da2 100644 --- a/u-boot/drivers/video/drm/Kconfig +++ b/u-boot/drivers/video/drm/Kconfig @@ -228,3 +228,6 @@ config ROCKCHIP_CUBIC_LUT_SIZE default 0 help Used to calc cubic lut size. + +source "drivers/video/drm/display-serdes/Kconfig" + diff --git a/u-boot/drivers/video/drm/Makefile b/u-boot/drivers/video/drm/Makefile index 4c28ee1ffa..a477dba5b3 100644 --- a/u-boot/drivers/video/drm/Makefile +++ b/u-boot/drivers/video/drm/Makefile @@ -9,7 +9,7 @@ obj-y += drm_modes.o ifndef CONFIG_SPL_BUILD obj-y += rockchip_display.o rockchip_display_helper.o rockchip_crtc.o rockchip_phy.o rockchip_bridge.o \ rockchip_vop.o rockchip_vop_reg.o rockchip_vop2.o bmp_helper.o \ - rockchip_connector.o rockchip_post_csc.o + rockchip_connector.o rockchip_post_csc.o libnsbmp.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_DP_HELPER) += drm_dp_helper.o @@ -31,13 +31,14 @@ obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX_HDMI) += phy-rockchip-samsung-hdptx-hdmi obj-$(CONFIG_DRM_ROCKCHIP_TVE) += rockchip_tve.o obj-$(CONFIG_DRM_ROCKCHIP_ANALOGIX_DP) += analogix_dp.o analogix_dp_reg.o obj-$(CONFIG_DRM_ROCKCHIP_DW_DP) += dw-dp.o -obj-$(CONFIG_DRM_ROCKCHIP_LVDS) += rockchip_lvds.o +obj-$(CONFIG_DRM_ROCKCHIP_LVDS) += rockchip_lvds.o drm_of.o obj-$(CONFIG_DRM_ROCKCHIP_RGB) += rockchip_rgb.o obj-$(CONFIG_DRM_ROCKCHIP_PANEL) += rockchip_panel.o obj-$(CONFIG_DRM_ROHM_BU18XL82) += rohm-bu18tl82.o rohm-bu18rl82.o obj-$(CONFIG_DRM_ROCKCHIP_RK618) += rk618.o rk618_lvds.o rk618_dsi.o obj-$(CONFIG_DRM_ROCKCHIP_RK1000) += rk1000.o rk1000_tve.o obj-$(CONFIG_DRM_ROCKCHIP_SAMSUNG_MIPI_DCPHY) += samsung_mipi_dcphy.o +obj-$(CONFIG_SERDES_DISPLAY) += display-serdes/ else obj-y += rockchip_spl_display.o rockchip_display_helper.o rockchip_crtc.o rockchip_connector.o rockchip_post_csc.o rockchip_vop2.o rockchip_phy.o rockchip-inno-hdmi-phy.o rockchip_dw_hdmi.o dw_hdmi.o endif diff --git a/u-boot/drivers/video/drm/analogix_dp.c b/u-boot/drivers/video/drm/analogix_dp.c index 70cd620fa8..9384542ad6 100644 --- a/u-boot/drivers/video/drm/analogix_dp.c +++ b/u-boot/drivers/video/drm/analogix_dp.c @@ -935,12 +935,29 @@ static int analogix_dp_connector_detect(struct rockchip_connector *conn, return analogix_dp_detect(dp); } +static int analogix_dp_connector_mode_valid(struct rockchip_connector *conn, + struct display_state *state) +{ + struct connector_state *conn_state = &state->conn_state; + struct videomode vm; + + drm_display_mode_to_videomode(&conn_state->mode, &vm); + + if (!vm.hfront_porch || !vm.hback_porch || !vm.vfront_porch || !vm.vback_porch) { + dev_err(dp->dev, "front porch or back porch can not be 0\n"); + return MODE_BAD; + } + + return MODE_OK; +} + static const struct rockchip_connector_funcs analogix_dp_connector_funcs = { .init = analogix_dp_connector_init, .get_edid = analogix_dp_connector_get_edid, .enable = analogix_dp_connector_enable, .disable = analogix_dp_connector_disable, .detect = analogix_dp_connector_detect, + .mode_valid = analogix_dp_connector_mode_valid, }; static u32 analogix_dp_parse_link_frequencies(struct analogix_dp_device *dp) diff --git a/u-boot/drivers/video/drm/display-serdes/Kconfig b/u-boot/drivers/video/drm/display-serdes/Kconfig new file mode 100644 index 0000000000..17511e113a --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/Kconfig @@ -0,0 +1,29 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0-only +# +# Multifunction miscellaneous devices +# +comment "driver for different display serdes" + +menuconfig SERDES_DISPLAY + tristate "rockchip display serdes drivers support" + select SERDES_DISPLAY_CHIP_ROHM + select SERDES_DISPLAY_CHIP_MAXIM + select SERDES_DISPLAY_CHIP_ROCKCHIP + select SERDES_DISPLAY_CHIP_NOVO + select I2C_MUX + select DRM_ROCKCHIP + default n + help + This driver supports different serdes devices from different vendor such as + maxim, rohm, rockchip etc. + +if SERDES_DISPLAY +source "drivers/video/drm/display-serdes/maxim/Kconfig" +source "drivers/video/drm/display-serdes/rohm/Kconfig" +source "drivers/video/drm/display-serdes/rockchip/Kconfig" +source "drivers/video/drm/display-serdes/novo/Kconfig" +endif + diff --git a/u-boot/drivers/video/drm/display-serdes/Makefile b/u-boot/drivers/video/drm/display-serdes/Makefile new file mode 100644 index 0000000000..c0ed7a6a3d --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/Makefile @@ -0,0 +1,15 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for multifunction miscellaneous devices that just used for display +# +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM) += maxim/ +obj-$(CONFIG_SERDES_DISPLAY_CHIP_ROHM) += rohm/ +obj-$(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP) += rockchip/ +obj-$(CONFIG_SERDES_DISPLAY_CHIP_NOVO) += novo/ + +obj-$(CONFIG_SERDES_DISPLAY) +=serdes-i2c.o serdes-core.o serdes-bridge.o serdes-bridge-split.o serdes-panel.o serdes-panel-split.o serdes-pinctrl.o serdes-gpio.o +endif diff --git a/u-boot/drivers/video/drm/display-serdes/core.h b/u-boot/drivers/video/drm/display-serdes/core.h new file mode 100644 index 0000000000..74ba7467f2 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/core.h @@ -0,0 +1,369 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * core.h -- core define for mfd display arch + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "gpio.h" + +#include "../drivers/video/drm/rockchip_bridge.h" +#include "../drivers/video/drm/rockchip_display.h" +#include "../drivers/video/drm/rockchip_panel.h" + +#ifndef __SERDES_DISPLAY_CORE_H__ +#define __SERDES_DISPLAY_CORE_H__ + +//#define SERDES_DEBUG_MFD +//#define SERDES_DEBUG_I2C +//#define SERDES_DEBUG_CHIP + +#ifdef SERDES_DEBUG_MFD +#define SERDES_DBG_MFD(x...) printf(x) +#else +#define SERDES_DBG_MFD(x...) +#endif + +#ifdef SERDES_DEBUG_I2C +#define SERDES_DBG_I2C(x...) printf(x) +#else +#define SERDES_DBG_I2C(x...) +#endif + +#ifdef SERDES_DEBUG_CHIP +#define SERDES_DBG_CHIP(x...) printf(x) +#else +#define SERDES_DBG_CHIP(x...) +#endif + +#define SERDES_UBOOT_DISPLAY_VERSION "serdes-uboot-displaly-v10-230920" +#define MAX_NUM_SERDES_SPLIT 8 +struct serdes; + +enum ser_link_mode { + SER_DUAL_LINK, + SER_LINKA, + SER_LINKB, + SER_SPLITTER_MODE, +}; + +/* Convenience macro to define a single named or anonymous pin descriptor */ +#define PINCTRL_PIN(a, b) { .number = a, .name = b } + +/** + * struct pinctrl_pin_desc - boards/machines provide information on their + * pins, pads or other muxable units in this struct + * @number: unique pin number from the global pin number space + * @name: a name for this pin + * @drv_data: driver-defined per-pin data. pinctrl core does not touch this + */ +struct pinctrl_pin_desc { + unsigned int number; + const char *name; + void *drv_data; +}; + +/** + * struct group_desc - generic pin group descriptor + * @name: name of the pin group + * @pins: array of pins that belong to the group + * @num_pins: number of pins in the group + * @data: pin controller driver specific data + */ +struct group_desc { + const char *name; + int *pins; + int num_pins; + void *data; +}; + +/** + * struct function_desc - generic function descriptor + * @name: name of the function + * @group_names: array of pin group names + * @num_group_names: number of pin group names + * @data: pin controller driver specific data + */ +struct function_desc { + const char *name; + const char **group_names; + int num_group_names; + void *data; +}; + +struct serdes_chip_pinctrl_info { + struct pinctrl_pin_desc *pins; + unsigned int num_pins; + struct group_desc *groups; + unsigned int num_groups; + struct function_desc *functions; + unsigned int num_functions; +}; + +struct serdes_chip_bridge_ops { + /*serdes chip function for bridge*/ + int (*power_on)(struct serdes *serdes); + int (*init)(struct serdes *serdes); + int (*attach)(struct serdes *serdes); + bool (*detect)(struct serdes *serdes); + int (*get_modes)(struct serdes *serdes); + int (*pre_enable)(struct serdes *serdes); + int (*enable)(struct serdes *serdes); + int (*disable)(struct serdes *serdes); + int (*post_disable)(struct serdes *serdes); +}; + +struct serdes_chip_panel_ops { + /*serdes chip function for bridge*/ + int (*power_on)(struct serdes *serdes); + int (*init)(struct serdes *serdes); + int (*disable)(struct serdes *serdes); + int (*unprepare)(struct serdes *serdes); + int (*prepare)(struct serdes *serdes); + int (*enable)(struct serdes *serdes); + int (*get_modes)(struct serdes *serdes); + int (*mode_set)(struct serdes *serdes); + int (*backlight_enable)(struct serdes *serdes); + int (*backlight_disable)(struct serdes *serdes); +}; + +struct serdes_chip_pinctrl_ops { + int (*pinmux_set)(struct serdes *serdes, unsigned int pin_selector, + unsigned int func_selector); + int (*pinmux_group_set)(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector); + int (*pinconf_set)(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, unsigned int argument); + int (*pinconf_group_set)(struct serdes *serdes, + unsigned int group_selector, + unsigned int param, unsigned int argument); +}; + +struct serdes_chip_gpio_ops { + /*serdes chip gpio function*/ + int (*direction_input)(struct serdes *serdes, int gpio); + int (*direction_output)(struct serdes *serdes, int gpio, int value); + int (*get_level)(struct serdes *serdes, int gpio); + int (*set_level)(struct serdes *serdes, int gpio, int value); + int (*set_config)(struct serdes *serdes, + int gpio, unsigned long config); + int (*to_irq)(struct serdes *serdes, int gpio); +}; + +struct serdes_chip_split_ops { + int (*select)(struct serdes *serdes, int chan); + int (*deselect)(struct serdes *serdes, int chan); + int (*set_i2c_addr)(struct serdes *serdes, int address, int link); +}; +struct serdes_chip_irq_ops { + /*serdes chip function for lock and err irq*/ + int (*lock_handle)(struct serdes *serdes); + int (*err_handle)(struct serdes *serdes); +}; + +struct serdes_chip_data { + const char *name; + enum serdes_type serdes_type; + enum serdes_id serdes_id; + enum reg_val_type reg_val_type; + int sequence_init; + int connector_type; + int reg_id; + int id_data; + int int_status_reg; + int int_trig; + int num_gpio; + int gpio_base; + int same_chip_count; + u8 bank_num; + + int (*chip_init)(struct serdes *serdes); + struct serdes_chip_pinctrl_info *pinctrl_info; + struct serdes_chip_bridge_ops *bridge_ops; + struct serdes_chip_panel_ops *panel_ops; + struct serdes_chip_pinctrl_ops *pinctrl_ops; + struct serdes_chip_gpio_ops *gpio_ops; + struct serdes_chip_split_ops *split_ops; + struct serdes_chip_irq_ops *irq_ops; +}; + +struct reg_sequence { + unsigned int reg; + unsigned int def; + unsigned int delay_us; +}; + +struct serdes_init_seq { + struct reg_sequence *reg_sequence; + unsigned int reg_seq_cnt; +}; + +struct serdes_gpio { + struct udevice *dev; + struct serdes_pinctrl *parent; +}; + +struct serdes_pinctrl { + struct udevice *dev; + struct serdes *parent; + struct serdes_gpio *serdes_gpio; + struct pinctrl_pin_desc *pdesc; + struct regmap *regmap; + struct pinctrl_desc *pinctrl_desc; + int pin_base; +}; + +struct serdes_panel { + struct rockchip_panel *panel; + const char *name; + u32 width_mm; + u32 height_mm; + u32 link_rate; + u32 lane_count; + bool ssc; + struct serdes *parent; + struct drm_display_mode mode; + struct udevice *backlight; + struct rockchip_panel_funcs *panel_ops; +}; + +struct serdes_panel_split { + struct rockchip_panel *panel; + + const char *name; + u32 width_mm; + u32 height_mm; + u32 link_rate; + u32 lane_count; + bool ssc; + struct serdes *parent; + struct drm_display_mode mode; + struct udevice *backlight; + struct rockchip_panel_funcs *panel_ops; +}; + +struct serdes_bridge { + bool sel_mipi; + struct mipi_dsi_device *dsi; + struct serdes *parent; + struct drm_display_mode mode; + struct rockchip_bridge *bridge; + struct rockchip_bridge_funcs *bridge_ops; +}; + +struct serdes_bridge_split { + bool sel_mipi; + struct mipi_dsi_device *dsi; + struct serdes *parent; + struct drm_display_mode mode; + struct rockchip_bridge *bridge; + struct rockchip_bridge_funcs *bridge_ops; +}; + +struct serdes { + struct udevice *dev; + struct udevice *vpower_supply; + struct serdes_init_seq *serdes_init_seq; + enum serdes_type type; + + /*serdes power and reset pin*/ + struct gpio_desc reset_gpio; + struct gpio_desc enable_gpio; + + /* serdes irq pin */ + struct gpio_desc lock_gpio; + struct gpio_desc err_gpio; + int lock_irq; + int err_irq; + int lock_irq_trig; + int err_irq_trig; + + bool sel_mipi; + struct mipi_dsi_device *dsi; + + bool split_mode_enable; + unsigned int reg_hw; + unsigned int reg_use; + unsigned int link_use; + unsigned int id_serdes_bridge_split; + unsigned int id_serdes_panel_split; + struct serdes *g_serdes_bridge_split; + + struct serdes_bridge *serdes_bridge; + struct serdes_bridge_split *serdes_bridge_split; + struct serdes_panel *serdes_panel; + struct serdes_panel_split *serdes_panel_split; + struct serdes_pinctrl *serdes_pinctrl; + struct serdes_chip_data *chip_data; +}; + +/* Device I/O API */ +int serdes_reg_read(struct serdes *serdes, unsigned int reg, unsigned int *val); +int serdes_reg_write(struct serdes *serdes, unsigned int reg, unsigned int val); +int serdes_set_bits(struct serdes *serdes, unsigned int reg, + unsigned int mask, unsigned int val); +int serdes_multi_reg_write(struct serdes *serdes, + const struct reg_sequence *regs, + int num_regs); +int serdes_i2c_set_sequence(struct serdes *serdes); +int serdes_parse_init_seq(struct udevice *dev, const u16 *data, + int length, struct serdes_init_seq *seq); +int serdes_get_init_seq(struct serdes *serdes); +int serdes_gpio_register(struct udevice *dev, struct serdes *serdes); +int serdes_pinctrl_register(struct udevice *dev, struct serdes *serdes); +int serdes_bridge_register(struct udevice *dev, struct serdes *serdes); +int serdes_bridge_split_register(struct udevice *dev, struct serdes *serdes); +int serdes_power_init(void); +int serdes_video_bridge_init(void); +int serdes_video_bridge_split_init(void); +int serdes_display_init(void); + +extern struct serdes_chip_data serdes_bu18tl82_data; +extern struct serdes_chip_data serdes_bu18rl82_data; +extern struct serdes_chip_data serdes_max96745_data; +extern struct serdes_chip_data serdes_max96752_data; +extern struct serdes_chip_data serdes_max96755_data; +extern struct serdes_chip_data serdes_max96772_data; +extern struct serdes_chip_data serdes_max96789_data; +extern struct serdes_chip_data serdes_rkx111_data; +extern struct serdes_chip_data serdes_rkx121_data; +extern struct serdes_chip_data serdes_nca9539_data; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/gpio.h b/u-boot/drivers/video/drm/display-serdes/gpio.h new file mode 100644 index 0000000000..0538b78af8 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/gpio.h @@ -0,0 +1,253 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * gpio.h -- GPIO for different serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __SERDES_DISPLAY_GPIO_H__ +#define __SERDES_DISPLAY_GPIO_H__ + +enum serdes_parent { + BU18TL82 = 0x1000, + BU18RL82 = 0x1001, + MAX96745 = 0x2000, + MAX96752 = 0x2001, + MAX96755 = 0x2003, + MAX96722 = 0x2004, + MAX96789 = 0x2005, + RKX111 = 0x3000, + RKX121 = 0x3001, +}; + +enum serdes_type { + TYPE_ID_INVALID = 0, + TYPE_SER, + TYPE_DES, + TYPE_OTHER, +}; + +enum reg_val_type { + REG_16BIT_VAL_8IT = 0, + REG_16BIT_VAL_16IT, + REG_8BIT_VAL_8IT, +}; + +enum serdes_bridge_type { + TYPE_BRIDGE_PANEL = 0, + TYPE_BRIDGE_BRIDGE, +}; + +enum serdes_id { + SERDES_ID_INVALID = 0, + + ROHM_ID_BU18TL82, + ROHM_ID_BU18RL82, + + MAXIM_ID_MAX96745, + MAXIM_ID_MAX96752, + MAXIM_ID_MAX96755, + MAXIM_ID_MAX96772, + MAXIM_ID_MAX96789, + + ROCKCHIP_ID_RKX111, + ROCKCHIP_ID_RKX121, + + NOVO_ID_NCA9539, + + SERDES_NUM_ID, +}; + +enum bu18tl82_gpio_list { + ROHM_BU18TL82_GPIO0 = 0, + ROHM_BU18TL82_GPIO1, + ROHM_BU18TL82_GPIO2, + ROHM_BU18TL82_GPIO3, + ROHM_BU18TL82_GPIO4, + ROHM_BU18TL82_GPIO5, + ROHM_BU18TL82_GPIO6, + ROHM_BU18TL82_GPIO7, +}; + +enum bu18rl82_gpio_list { + ROHM_BU18RL82_GPIO0 = 0, + ROHM_BU18RL82_GPIO1, + ROHM_BU18RL82_GPIO2, + ROHM_BU18RL82_GPIO3, + ROHM_BU18RL82_GPIO4, + ROHM_BU18RL82_GPIO5, + ROHM_BU18RL82_GPIO6, + ROHM_BU18RL82_GPIO7, +}; + +enum max96745_gpio_list { + MAXIM_MAX96745_MFP0 = 0, + MAXIM_MAX96745_MFP1, + MAXIM_MAX96745_MFP2, + MAXIM_MAX96745_MFP3, + MAXIM_MAX96745_MFP4, + MAXIM_MAX96745_MFP5, + MAXIM_MAX96745_MFP6, + MAXIM_MAX96745_MFP7, + MAXIM_MAX96745_MFP8, + MAXIM_MAX96745_MFP9, + MAXIM_MAX96745_MFP10, + MAXIM_MAX96745_MFP11, + MAXIM_MAX96745_MFP12, + MAXIM_MAX96745_MFP13, + MAXIM_MAX96745_MFP14, + MAXIM_MAX96745_MFP15, + MAXIM_MAX96745_MFP16, + MAXIM_MAX96745_MFP17, + MAXIM_MAX96745_MFP18, + MAXIM_MAX96745_MFP19, + MAXIM_MAX96745_MFP20, + MAXIM_MAX96745_MFP21, + MAXIM_MAX96745_MFP22, + MAXIM_MAX96745_MFP23, + MAXIM_MAX96745_MFP24, + MAXIM_MAX96745_MFP25, +}; + +enum max96752_gpio_list { + MAXIM_MAX96752_GPIO0 = 0, + MAXIM_MAX96752_GPIO1, + MAXIM_MAX96752_GPIO2, + MAXIM_MAX96752_GPIO3, + MAXIM_MAX96752_GPIO4, + MAXIM_MAX96752_GPIO5, + MAXIM_MAX96752_GPIO6, + MAXIM_MAX96752_GPIO7, + MAXIM_MAX96752_GPIO8, + MAXIM_MAX96752_GPIO9, + MAXIM_MAX96752_GPIO10, + MAXIM_MAX96752_GPIO11, + MAXIM_MAX96752_GPIO12, + MAXIM_MAX96752_GPIO13, + MAXIM_MAX96752_GPIO14, + MAXIM_MAX96752_GPIO15, +}; + +enum max96755_gpio_list { + MAXIM_MAX96755_MFP0 = 0, + MAXIM_MAX96755_MFP1, + MAXIM_MAX96755_MFP2, + MAXIM_MAX96755_MFP3, + MAXIM_MAX96755_MFP4, + MAXIM_MAX96755_MFP5, + MAXIM_MAX96755_MFP6, + MAXIM_MAX96755_MFP7, + MAXIM_MAX96755_MFP8, + MAXIM_MAX96755_MFP9, + MAXIM_MAX96755_MFP10, + MAXIM_MAX96755_MFP11, + MAXIM_MAX96755_MFP12, + MAXIM_MAX96755_MFP13, + MAXIM_MAX96755_MFP14, + MAXIM_MAX96755_MFP15, + MAXIM_MAX96755_MFP16, + MAXIM_MAX96755_MFP17, + MAXIM_MAX96755_MFP18, + MAXIM_MAX96755_MFP19, + MAXIM_MAX96755_MFP20, +}; + +enum max96722_gpio_list { + MAXIM_MAX96772_GPIO0 = 0, + MAXIM_MAX96772_GPIO1, + MAXIM_MAX96772_GPIO2, + MAXIM_MAX96772_GPIO3, + MAXIM_MAX96772_GPIO4, + MAXIM_MAX96772_GPIO5, + MAXIM_MAX96772_GPIO6, + MAXIM_MAX96772_GPIO7, + MAXIM_MAX96772_GPIO8, + MAXIM_MAX96772_GPIO9, + MAXIM_MAX96772_GPIO10, + MAXIM_MAX96772_GPIO11, + MAXIM_MAX96772_GPIO12, + MAXIM_MAX96772_GPIO13, + MAXIM_MAX96772_GPIO14, + MAXIM_MAX96772_GPIO15, +}; + +enum max96789_gpio_list { + MAXIM_MAX96789_MFP0 = 0, + MAXIM_MAX96789_MFP1, + MAXIM_MAX96789_MFP2, + MAXIM_MAX96789_MFP3, + MAXIM_MAX96789_MFP4, + MAXIM_MAX96789_MFP5, + MAXIM_MAX96789_MFP6, + MAXIM_MAX96789_MFP7, + MAXIM_MAX96789_MFP8, + MAXIM_MAX96789_MFP9, + MAXIM_MAX96789_MFP10, + MAXIM_MAX96789_MFP11, + MAXIM_MAX96789_MFP12, + MAXIM_MAX96789_MFP13, + MAXIM_MAX96789_MFP14, + MAXIM_MAX96789_MFP15, + MAXIM_MAX96789_MFP16, + MAXIM_MAX96789_MFP17, + MAXIM_MAX96789_MFP18, + MAXIM_MAX96789_MFP19, + MAXIM_MAX96789_MFP20, +}; + +enum rkx111_gpio_list { + ROCKCHIP_RKX111_GPIO0 = 0, + ROCKCHIP_RKX111_GPIO1, + ROCKCHIP_RKX111_GPIO2, + ROCKCHIP_RKX111_GPIO3, + ROCKCHIP_RKX111_GPIO4, + ROCKCHIP_RKX111_GPIO5, + ROCKCHIP_RKX111_GPIO6, + ROCKCHIP_RKX111_GPIO7, +}; + +enum rkx121_gpio_list { + ROCKCHIP_RKX121_GPIO0 = 0, + ROCKCHIP_RKX121_GPIO1, + ROCKCHIP_RKX121_GPIO2, + ROCKCHIP_RKX121_GPIO3, + ROCKCHIP_RKX121_GPIO4, + ROCKCHIP_RKX121_GPIO5, + ROCKCHIP_RKX121_GPIO6, + ROCKCHIP_RKX121_GPIO7, +}; + +enum serdes_gpio_state { + SERDES_GPIO_PULL_NONE = 0, + SERDES_GPIO_PULL_DOWN, + SERDES_GPIO_PULL_UP, + SERDES_GPIO_DIR_IN, + SERDES_GPIO_DIR_OUT, + SERDES_GPIO_LEVEL_HIGH, + SERDES_GPIO_LEVEL_LOW, +}; + +enum nca9539_gpio_list { + NOVO_NCA9539_GPIO0 = 0, + NOVO_NCA9539_GPIO1, + NOVO_NCA9539_GPIO2, + NOVO_NCA9539_GPIO3, + NOVO_NCA9539_GPIO4, + NOVO_NCA9539_GPIO5, + NOVO_NCA9539_GPIO6, + NOVO_NCA9539_GPIO7, + + NOVO_NCA9539_GPIO8, + NOVO_NCA9539_GPIO9, + NOVO_NCA9539_GPIO10, + NOVO_NCA9539_GPIO11, + NOVO_NCA9539_GPIO12, + NOVO_NCA9539_GPIO13, + NOVO_NCA9539_GPIO14, + NOVO_NCA9539_GPIO15, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/Kconfig b/u-boot/drivers/video/drm/display-serdes/maxim/Kconfig new file mode 100644 index 0000000000..3f18c92fab --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/Kconfig @@ -0,0 +1,47 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# maxim display serdes drivers configuration +# + +menuconfig SERDES_DISPLAY_CHIP_MAXIM + tristate "maxim serdes device support" + default y + help + Enable this to be able to choose the drivers for controlling the + maxim serdes. + +if SERDES_DISPLAY_CHIP_MAXIM +config SERDES_DISPLAY_CHIP_MAXIM_MAX96745 + tristate "maxim max96745 serdes" + default y + help + To support maxim max96745 display serdes. + +config SERDES_DISPLAY_CHIP_MAXIM_MAX96752 + tristate "maxim max96752 serdes" + default y + help + To support maxim max96752 display serdes. + +config SERDES_DISPLAY_CHIP_MAXIM_MAX96755 + tristate "maxim max96755 serdes" + default y + help + To support maxim max96755 display serdes. + +config SERDES_DISPLAY_CHIP_MAXIM_MAX96772 + tristate "maxim max96772 serdes" + default y + help + To support maxim max96772 display serdes. + +config SERDES_DISPLAY_CHIP_MAXIM_MAX96789 + tristate "maxim max96789 serdes" + default y + help + To support maxim max96789 display serdes. + +endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/Makefile b/u-boot/drivers/video/drm/display-serdes/maxim/Makefile new file mode 100644 index 0000000000..f6d24a7c18 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/Makefile @@ -0,0 +1,14 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# maxim display serdes drivers configuration +# +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) += maxim-max96745.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) += maxim-max96752.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) += maxim-max96755.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) += maxim-max96772.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789) += maxim-max96789.o +endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.c b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.c new file mode 100644 index 0000000000..febcc3749a --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.c @@ -0,0 +1,813 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-max96745.c -- I2C register interface access for max96745 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ +#include "../core.h" +#include "maxim-max96745.h" +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_io_rx_en:1; + u8 gpio_tx_en_a:1; + u8 gpio_tx_en_b:1; + u8 gpio_rx_en_a:1; + u8 gpio_rx_en_b:1; + u8 gpio_tx_id; + u8 gpio_rx_id; + u16 mdelay; +}; + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96745_MFP0_pins[] = {0}; +static int MAX96745_MFP1_pins[] = {1}; +static int MAX96745_MFP2_pins[] = {2}; +static int MAX96745_MFP3_pins[] = {3}; +static int MAX96745_MFP4_pins[] = {4}; +static int MAX96745_MFP5_pins[] = {5}; +static int MAX96745_MFP6_pins[] = {6}; +static int MAX96745_MFP7_pins[] = {7}; + +static int MAX96745_MFP8_pins[] = {8}; +static int MAX96745_MFP9_pins[] = {9}; +static int MAX96745_MFP10_pins[] = {10}; +static int MAX96745_MFP11_pins[] = {11}; +static int MAX96745_MFP12_pins[] = {12}; +static int MAX96745_MFP13_pins[] = {13}; +static int MAX96745_MFP14_pins[] = {14}; +static int MAX96745_MFP15_pins[] = {15}; + +static int MAX96745_MFP16_pins[] = {16}; +static int MAX96745_MFP17_pins[] = {17}; +static int MAX96745_MFP18_pins[] = {18}; +static int MAX96745_MFP19_pins[] = {19}; +static int MAX96745_MFP20_pins[] = {20}; +static int MAX96745_MFP21_pins[] = {21}; +static int MAX96745_MFP22_pins[] = {22}; +static int MAX96745_MFP23_pins[] = {23}; + +static int MAX96745_MFP24_pins[] = {24}; +static int MAX96745_MFP25_pins[] = {25}; +static int MAX96745_I2C_pins[] = {3, 7}; +static int MAX96745_UART_pins[] = {3, 7}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +static const char *serdes_gpio_groups[] = { + "MAX96745_MFP0", "MAX96745_MFP1", "MAX96745_MFP2", "MAX96745_MFP3", + "MAX96745_MFP4", "MAX96745_MFP5", "MAX96745_MFP6", "MAX96745_MFP7", + + "MAX96745_MFP8", "MAX96745_MFP9", "MAX96745_MFP10", "MAX96745_MFP11", + "MAX96745_MFP12", "MAX96745_MFP13", "MAX96745_MFP14", "MAX96745_MFP15", + + "MAX96745_MFP16", "MAX96745_MFP17", "MAX96745_MFP18", "MAX96745_MFP19", + "MAX96745_MFP20", "MAX96745_MFP21", "MAX96745_MFP22", "MAX96745_MFP23", + + "MAX96745_MFP24", "MAX96745_MFP25", +}; + +static const char *MAX96745_I2C_groups[] = { "MAX96745_I2C" }; +static const char *MAX96745_UART_groups[] = { "MAX96745_UART" }; + +#define FUNCTION_DESC(nm) \ +{ \ + .name = #nm, \ + .group_names = nm##_groups, \ + .num_group_names = ARRAY_SIZE(nm##_groups), \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_A(id) \ +{ \ + .name = "SER_TXID"#id"_TO_DES_LINKA", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en_a = 1, \ + .gpio_io_rx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_B(id) \ +{ \ + .name = "SER_TXID"#id"_TO_DES_LINKB", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en_b = 1, \ + .gpio_io_rx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_INPUT_A(id) \ +{ \ + .name = "DES_RXID"#id"_TO_SER_LINKA", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en_a = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_INPUT_B(id) \ +{ \ + .name = "DES_RXID"#id"_TO_SER_LINKB", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en_b = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO() \ +{ \ + .name = "MAX96745_GPIO", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96745_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96745_MFP0, "MAX96745_MFP0"), + PINCTRL_PIN(MAXIM_MAX96745_MFP1, "MAX96745_MFP1"), + PINCTRL_PIN(MAXIM_MAX96745_MFP2, "MAX96745_MFP2"), + PINCTRL_PIN(MAXIM_MAX96745_MFP3, "MAX96745_MFP3"), + PINCTRL_PIN(MAXIM_MAX96745_MFP4, "MAX96745_MFP4"), + PINCTRL_PIN(MAXIM_MAX96745_MFP5, "MAX96745_MFP5"), + PINCTRL_PIN(MAXIM_MAX96745_MFP6, "MAX96745_MFP6"), + PINCTRL_PIN(MAXIM_MAX96745_MFP7, "MAX96745_MFP7"), + + PINCTRL_PIN(MAXIM_MAX96745_MFP8, "MAX96745_MFP8"), + PINCTRL_PIN(MAXIM_MAX96745_MFP9, "MAX96745_MFP9"), + PINCTRL_PIN(MAXIM_MAX96745_MFP10, "MAX96745_MFP10"), + PINCTRL_PIN(MAXIM_MAX96745_MFP11, "MAX96745_MFP11"), + PINCTRL_PIN(MAXIM_MAX96745_MFP12, "MAX96745_MFP12"), + PINCTRL_PIN(MAXIM_MAX96745_MFP13, "MAX96745_MFP13"), + PINCTRL_PIN(MAXIM_MAX96745_MFP14, "MAX96745_MFP14"), + PINCTRL_PIN(MAXIM_MAX96745_MFP15, "MAX96745_MFP15"), + + PINCTRL_PIN(MAXIM_MAX96745_MFP16, "MAX96745_MFP16"), + PINCTRL_PIN(MAXIM_MAX96745_MFP17, "MAX96745_MFP17"), + PINCTRL_PIN(MAXIM_MAX96745_MFP18, "MAX96745_MFP18"), + PINCTRL_PIN(MAXIM_MAX96745_MFP19, "MAX96745_MFP19"), + PINCTRL_PIN(MAXIM_MAX96745_MFP20, "MAX96745_MFP20"), + PINCTRL_PIN(MAXIM_MAX96745_MFP21, "MAX96745_MFP21"), + PINCTRL_PIN(MAXIM_MAX96745_MFP22, "MAX96745_MFP22"), + PINCTRL_PIN(MAXIM_MAX96745_MFP23, "MAX96745_MFP23"), + + PINCTRL_PIN(MAXIM_MAX96745_MFP24, "MAX96745_MFP24"), + PINCTRL_PIN(MAXIM_MAX96745_MFP25, "MAX96745_MFP25"), +}; + +static struct group_desc max96745_groups_desc[] = { + GROUP_DESC(MAX96745_MFP0), + GROUP_DESC(MAX96745_MFP1), + GROUP_DESC(MAX96745_MFP2), + GROUP_DESC(MAX96745_MFP3), + GROUP_DESC(MAX96745_MFP4), + GROUP_DESC(MAX96745_MFP5), + GROUP_DESC(MAX96745_MFP6), + GROUP_DESC(MAX96745_MFP7), + + GROUP_DESC(MAX96745_MFP8), + GROUP_DESC(MAX96745_MFP9), + GROUP_DESC(MAX96745_MFP10), + GROUP_DESC(MAX96745_MFP11), + GROUP_DESC(MAX96745_MFP12), + GROUP_DESC(MAX96745_MFP13), + GROUP_DESC(MAX96745_MFP14), + GROUP_DESC(MAX96745_MFP15), + + GROUP_DESC(MAX96745_MFP16), + GROUP_DESC(MAX96745_MFP17), + GROUP_DESC(MAX96745_MFP18), + GROUP_DESC(MAX96745_MFP19), + GROUP_DESC(MAX96745_MFP20), + GROUP_DESC(MAX96745_MFP21), + GROUP_DESC(MAX96745_MFP22), + GROUP_DESC(MAX96745_MFP23), + + GROUP_DESC(MAX96745_MFP24), + GROUP_DESC(MAX96745_MFP25), + + GROUP_DESC(MAX96745_I2C), + GROUP_DESC(MAX96745_UART), +}; + +static struct function_desc max96745_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT_A(0), + FUNCTION_DESC_GPIO_INPUT_A(1), + FUNCTION_DESC_GPIO_INPUT_A(2), + FUNCTION_DESC_GPIO_INPUT_A(3), + FUNCTION_DESC_GPIO_INPUT_A(4), + FUNCTION_DESC_GPIO_INPUT_A(5), + FUNCTION_DESC_GPIO_INPUT_A(6), + FUNCTION_DESC_GPIO_INPUT_A(7), + + FUNCTION_DESC_GPIO_INPUT_A(8), + FUNCTION_DESC_GPIO_INPUT_A(9), + FUNCTION_DESC_GPIO_INPUT_A(10), + FUNCTION_DESC_GPIO_INPUT_A(11), + FUNCTION_DESC_GPIO_INPUT_A(12), + FUNCTION_DESC_GPIO_INPUT_A(13), + FUNCTION_DESC_GPIO_INPUT_A(14), + FUNCTION_DESC_GPIO_INPUT_A(15), + + FUNCTION_DESC_GPIO_INPUT_A(16), + FUNCTION_DESC_GPIO_INPUT_A(17), + FUNCTION_DESC_GPIO_INPUT_A(18), + FUNCTION_DESC_GPIO_INPUT_A(19), + FUNCTION_DESC_GPIO_INPUT_A(20), + FUNCTION_DESC_GPIO_INPUT_A(21), + FUNCTION_DESC_GPIO_INPUT_A(22), + FUNCTION_DESC_GPIO_INPUT_A(23), + + FUNCTION_DESC_GPIO_INPUT_A(24), + FUNCTION_DESC_GPIO_INPUT_A(25), + + FUNCTION_DESC_GPIO_OUTPUT_A(0), + FUNCTION_DESC_GPIO_OUTPUT_A(1), + FUNCTION_DESC_GPIO_OUTPUT_A(2), + FUNCTION_DESC_GPIO_OUTPUT_A(3), + FUNCTION_DESC_GPIO_OUTPUT_A(4), + FUNCTION_DESC_GPIO_OUTPUT_A(5), + FUNCTION_DESC_GPIO_OUTPUT_A(6), + FUNCTION_DESC_GPIO_OUTPUT_A(7), + + FUNCTION_DESC_GPIO_OUTPUT_A(8), + FUNCTION_DESC_GPIO_OUTPUT_A(9), + FUNCTION_DESC_GPIO_OUTPUT_A(10), + FUNCTION_DESC_GPIO_OUTPUT_A(11), + FUNCTION_DESC_GPIO_OUTPUT_A(12), + FUNCTION_DESC_GPIO_OUTPUT_A(13), + FUNCTION_DESC_GPIO_OUTPUT_A(14), + FUNCTION_DESC_GPIO_OUTPUT_A(15), + + FUNCTION_DESC_GPIO_OUTPUT_A(16), + FUNCTION_DESC_GPIO_OUTPUT_A(17), + FUNCTION_DESC_GPIO_OUTPUT_A(18), + FUNCTION_DESC_GPIO_OUTPUT_A(19), + FUNCTION_DESC_GPIO_OUTPUT_A(20), + FUNCTION_DESC_GPIO_OUTPUT_A(21), + FUNCTION_DESC_GPIO_OUTPUT_A(22), + FUNCTION_DESC_GPIO_OUTPUT_A(23), + + FUNCTION_DESC_GPIO_OUTPUT_A(24), + FUNCTION_DESC_GPIO_OUTPUT_A(25), + + FUNCTION_DESC_GPIO_INPUT_B(0), + FUNCTION_DESC_GPIO_INPUT_B(1), + FUNCTION_DESC_GPIO_INPUT_B(2), + FUNCTION_DESC_GPIO_INPUT_B(3), + FUNCTION_DESC_GPIO_INPUT_B(4), + FUNCTION_DESC_GPIO_INPUT_B(5), + FUNCTION_DESC_GPIO_INPUT_B(6), + FUNCTION_DESC_GPIO_INPUT_B(7), + + FUNCTION_DESC_GPIO_INPUT_B(8), + FUNCTION_DESC_GPIO_INPUT_B(9), + FUNCTION_DESC_GPIO_INPUT_B(10), + FUNCTION_DESC_GPIO_INPUT_B(11), + FUNCTION_DESC_GPIO_INPUT_B(12), + FUNCTION_DESC_GPIO_INPUT_B(13), + FUNCTION_DESC_GPIO_INPUT_B(14), + FUNCTION_DESC_GPIO_INPUT_B(15), + + FUNCTION_DESC_GPIO_INPUT_B(16), + FUNCTION_DESC_GPIO_INPUT_B(17), + FUNCTION_DESC_GPIO_INPUT_B(18), + FUNCTION_DESC_GPIO_INPUT_B(19), + FUNCTION_DESC_GPIO_INPUT_B(20), + FUNCTION_DESC_GPIO_INPUT_B(21), + FUNCTION_DESC_GPIO_INPUT_B(22), + FUNCTION_DESC_GPIO_INPUT_B(23), + + FUNCTION_DESC_GPIO_INPUT_B(24), + FUNCTION_DESC_GPIO_INPUT_B(25), + + FUNCTION_DESC_GPIO_OUTPUT_B(0), + FUNCTION_DESC_GPIO_OUTPUT_B(1), + FUNCTION_DESC_GPIO_OUTPUT_B(2), + FUNCTION_DESC_GPIO_OUTPUT_B(3), + FUNCTION_DESC_GPIO_OUTPUT_B(4), + FUNCTION_DESC_GPIO_OUTPUT_B(5), + FUNCTION_DESC_GPIO_OUTPUT_B(6), + FUNCTION_DESC_GPIO_OUTPUT_B(7), + + FUNCTION_DESC_GPIO_OUTPUT_B(8), + FUNCTION_DESC_GPIO_OUTPUT_B(9), + FUNCTION_DESC_GPIO_OUTPUT_B(10), + FUNCTION_DESC_GPIO_OUTPUT_B(11), + FUNCTION_DESC_GPIO_OUTPUT_B(12), + FUNCTION_DESC_GPIO_OUTPUT_B(13), + FUNCTION_DESC_GPIO_OUTPUT_B(14), + FUNCTION_DESC_GPIO_OUTPUT_B(15), + + FUNCTION_DESC_GPIO_OUTPUT_B(16), + FUNCTION_DESC_GPIO_OUTPUT_B(17), + FUNCTION_DESC_GPIO_OUTPUT_B(18), + FUNCTION_DESC_GPIO_OUTPUT_B(19), + FUNCTION_DESC_GPIO_OUTPUT_B(20), + FUNCTION_DESC_GPIO_OUTPUT_B(21), + FUNCTION_DESC_GPIO_OUTPUT_B(22), + FUNCTION_DESC_GPIO_OUTPUT_B(23), + + FUNCTION_DESC_GPIO_OUTPUT_B(24), + FUNCTION_DESC_GPIO_OUTPUT_B(25), + + FUNCTION_DESC_GPIO(), + + FUNCTION_DESC(MAX96745_I2C), + FUNCTION_DESC(MAX96745_UART), +}; + +static struct serdes_chip_pinctrl_info max96745_pinctrl_info = { + .pins = max96745_pins_desc, + .num_pins = ARRAY_SIZE(max96745_pins_desc), + .groups = max96745_groups_desc, + .num_groups = ARRAY_SIZE(max96745_groups_desc), + .functions = max96745_functions_desc, + .num_functions = ARRAY_SIZE(max96745_functions_desc), +}; + +static bool max96745_bridge_link_locked(struct serdes *serdes) +{ + u32 val; + + if (dm_gpio_is_valid(&serdes->lock_gpio)) { + val = dm_gpio_get_value(&serdes->lock_gpio); + SERDES_DBG_CHIP("serdes %s:val=%d\n", __func__, val); + return val; + } + + if (serdes_reg_read(serdes, 0x002a, &val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + return true; +} + +static bool max96745_bridge_detect(struct serdes *serdes) +{ + return max96745_bridge_link_locked(serdes); +} + +static int max96745_bridge_enable(struct serdes *serdes) +{ + struct drm_display_mode *mode = + &serdes->serdes_bridge->bridge->state->conn_state.mode; + u8 cxtp, tx_rate; + int ret; + unsigned int value; + + ret = serdes_reg_read(serdes, 0x0011, &value); + if (ret < 0) + return ret; + + cxtp = FIELD_GET(CXTP_A, value); + + ret = serdes_reg_read(serdes, 0x0028, &value); + if (ret < 0) + return ret; + + tx_rate = FIELD_GET(TX_RATE, value); + + if (!cxtp && mode->clock > 95000 && tx_rate == 1) { + ret = serdes_set_bits(serdes, 0x0028, TX_RATE, + FIELD_PREP(TX_RATE, 2)); + if (ret < 0) + return ret; + + ret = serdes_set_bits(serdes, 0x0029, RESET_ONESHOT, + FIELD_PREP(RESET_ONESHOT, 1)); + if (ret < 0) + return ret; + + if (readx_poll_timeout(max96745_bridge_link_locked, serdes, ret, + ret, 200000)) + printf("%s: GMSL link not locked\n", __func__); + } + + return ret; +} + +static int max96745_bridge_disable(struct serdes *serdes) +{ + u8 cxtp, tx_rate; + int ret; + unsigned int value; + + ret = serdes_reg_read(serdes, 0x0011, &value); + if (ret < 0) + return ret; + + cxtp = FIELD_GET(CXTP_A, value); + + ret = serdes_reg_read(serdes, 0x0028, &value); + if (ret < 0) + return ret; + + tx_rate = FIELD_GET(TX_RATE, value); + + if (!cxtp && tx_rate == 2) { + ret = serdes_set_bits(serdes, 0x0028, TX_RATE, + FIELD_PREP(TX_RATE, 1)); + if (ret < 0) + return ret; + + ret = serdes_set_bits(serdes, 0x0029, RESET_ONESHOT, + FIELD_PREP(RESET_ONESHOT, 1)); + if (ret < 0) + return ret; + + if (readx_poll_timeout(max96745_bridge_link_locked, serdes, ret, + ret, 200000)) + printf("%s: GMSL link not locked\n", __func__); + } + + return ret; +} + +static struct serdes_chip_bridge_ops max96745_bridge_ops = { + .detect = max96745_bridge_detect, + .enable = max96745_bridge_enable, + .disable = max96745_bridge_disable, +}; + +static int max96745_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *data = func->data; + + ms = data->mdelay; + offset = pin->number; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + data->gpio_tx_id, data->gpio_rx_id, offset); + if (!ms) { + serdes_set_bits(serdes, + GPIO_A_REG(offset), + GPIO_OUT_DIS, + FIELD_PREP(GPIO_OUT_DIS, data->gpio_out_dis)); + if (data->gpio_tx_en_a || data->gpio_tx_en_b) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, data->gpio_tx_id)); + if (data->gpio_rx_en_a || data->gpio_rx_en_b) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, data->gpio_rx_id)); + serdes_set_bits(serdes, + GPIO_D_REG(offset), + GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN | + GPIO_RX_EN_A | GPIO_RX_EN_B, + FIELD_PREP(GPIO_TX_EN_A, data->gpio_tx_en_a) | + FIELD_PREP(GPIO_TX_EN_B, data->gpio_tx_en_b) | + FIELD_PREP(GPIO_RX_EN_A, data->gpio_rx_en_a) | + FIELD_PREP(GPIO_RX_EN_B, data->gpio_rx_en_b) | + FIELD_PREP(GPIO_IO_RX_EN, data->gpio_io_rx_en)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + + return 0; +} + +static int max96745_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p, num=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, + fdata->gpio_rx_id, offset); + + serdes_set_bits(serdes, + GPIO_A_REG(offset), + GPIO_OUT_DIS, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis)); + if (fdata->gpio_tx_en_a || fdata->gpio_tx_en_b) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en_a || fdata->gpio_rx_en_b) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + serdes_set_bits(serdes, + GPIO_D_REG(offset), + GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN | + GPIO_RX_EN_A | GPIO_RX_EN_B, + FIELD_PREP(GPIO_TX_EN_A, fdata->gpio_tx_en_a) | + FIELD_PREP(GPIO_TX_EN_B, fdata->gpio_tx_en_b) | + FIELD_PREP(GPIO_RX_EN_A, fdata->gpio_rx_en_a) | + FIELD_PREP(GPIO_RX_EN_B, fdata->gpio_rx_en_b) | + FIELD_PREP(GPIO_IO_RX_EN, fdata->gpio_io_rx_en)); + } + } + + return 0; +} + +static int max96745_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, + unsigned int argument) +{ + u8 res_cfg; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, argument)); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops max96745_pinctrl_ops = { + .pinconf_set = max96745_pinctrl_config_set, + .pinmux_set = max96745_pinctrl_set_pin_mux, + .pinmux_group_set = max96745_pinctrl_set_grp_mux, +}; + +static int max96745_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96745_gpio_direction_output(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96745_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96745_gpio_set_level(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96745_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int max96745_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops max96745_gpio_ops = { + .direction_input = max96745_gpio_direction_input, + .direction_output = max96745_gpio_direction_output, + .get_level = max96745_gpio_get_level, + .set_level = max96745_gpio_set_level, + .set_config = max96745_gpio_set_config, + .to_irq = max96745_gpio_to_irq, +}; + +static int max96745_select(struct serdes *serdes, int chan) +{ + /*0076 for linkA and 0086 for linkB*/ + if (chan == DUAL_LINK) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: enable %s remote i2c of linkA/linkB\n", + __func__, + serdes->chip_data->name); + } else if (chan == LINKA) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + SERDES_DBG_CHIP("%s: only enable %s remote i2c of linkA\n", + __func__, + serdes->chip_data->name); + } else if (chan == LINKB) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: only enable %s remote i2c of linkB\n", + __func__, + serdes->chip_data->name); + } else if (chan == SPLITTER_MODE) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: enable %s remote i2c of linkA/B\n", + __func__, + serdes->chip_data->name); + } + + return 0; +} + +static int max96745_deselect(struct serdes *serdes, int chan) +{ + if (chan == DUAL_LINK) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + SERDES_DBG_CHIP("%s: disable %s remote i2c of linkA/B\n", + __func__, + serdes->chip_data->name); + } else if (chan == LINKA) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + SERDES_DBG_CHIP("%s: only disable %s remote i2c of linkA\n", + __func__, + serdes->chip_data->name); + } else if (chan == LINKB) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + SERDES_DBG_CHIP("%s: only disable %s remote i2c of linkB\n", + __func__, + serdes->chip_data->name); + } else if (chan == SPLITTER_MODE) { + serdes_set_bits(serdes, 0x0076, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + serdes_set_bits(serdes, 0x0086, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 1)); + SERDES_DBG_CHIP("%s: disable %s remote i2c of linkA/B\n", + __func__, + serdes->chip_data->name); + } + + return 0; +} + +static struct serdes_chip_split_ops max96745_split_ops = { + .select = max96745_select, + .deselect = max96745_deselect, +}; + +struct serdes_chip_data serdes_max96745_data = { + .name = "max96745", + .serdes_type = TYPE_SER, + .serdes_id = MAXIM_ID_MAX96745, + .connector_type = DRM_MODE_CONNECTOR_eDP, + .pinctrl_info = &max96745_pinctrl_info, + .bridge_ops = &max96745_bridge_ops, + .pinctrl_ops = &max96745_pinctrl_ops, + .gpio_ops = &max96745_gpio_ops, + .split_ops = &max96745_split_ops, +}; +EXPORT_SYMBOL_GPL(serdes_max96745_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.h b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.h new file mode 100644 index 0000000000..5d17fe50c0 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96745.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * maxim-max96745.h -- register define for max96745 chip + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_MAXIM_MAX96745_H__ +#define __MFD_SERDES_MAXIM_MAX96745_H__ + +#include + +#define GPIO_A_REG(gpio) (0x0200 + ((gpio) * 8)) +#define GPIO_B_REG(gpio) (0x0201 + ((gpio) * 8)) +#define GPIO_C_REG(gpio) (0x0202 + ((gpio) * 8)) +#define GPIO_D_REG(gpio) (0x0203 + ((gpio) * 8)) + +/* 0005h */ +#define PU_LF3 BIT(3) +#define PU_LF2 BIT(2) +#define PU_LF1 BIT(1) +#define PU_LF0 BIT(0) + +/* 0010h */ +#define RESET_ALL BIT(7) +#define SLEEP BIT(3) + +/* 0011h */ +#define CXTP_B BIT(2) +#define CXTP_A BIT(0) + +/* 0013h */ +#define LOCKED BIT(3) +#define ERROR BIT(2) + +/* 0026h */ +#define LF_0 GENMASK(2, 0) +#define LF_1 GENMASK(6, 4) + +/* 0027h */ +#define LF_2 GENMASK(2, 0) +#define LF_3 GENMASK(6, 4) + +/* 0028h, 0032h */ +#define LINK_EN BIT(7) +#define TX_RATE GENMASK(3, 2) + +/* 0029h, 0033h */ +#define RESET_LINK BIT(0) +#define RESET_ONESHOT BIT(1) + +/* 002Ah, 0034h */ +#define LINK_LOCKED BIT(0) + +/* 0076h, 0086h */ +#define DIS_REM_CC BIT(7) + +/* 0100h */ +#define VID_LINK_SEL GENMASK(2, 1) +#define VID_TX_EN BIT(0) + +/* 0101h */ +#define BPP GENMASK(5, 0) + +/* 0102h */ +#define PCLKDET_A BIT(7) +#define DRIFT_ERR_A BIT(6) +#define OVERFLOW_A BIT(5) +#define FIFO_WARN_A BIT(4) +#define LIM_HEART BIT(2) + +/* 0107h */ +#define VID_TX_ACTIVE_B BIT(7) +#define VID_TX_ACTIVE_A BIT(6) + +/* 0108h */ +#define PCLKDET_B BIT(7) +#define DRIFT_ERR_B BIT(6) +#define OVERFLOW_B BIT(5) +#define FIFO_WARN_B BIT(4) + +/* 0200h */ +#define RES_CFG BIT(7) +#define TX_COM_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_OUT_DIS BIT(0) + +/* 0201h */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 0202h */ +#define OVR_RES_CFG BIT(7) +#define IO_EDGE_RATE GENMASK(6, 5) +#define GPIO_RX_ID GENMASK(4, 0) + +/* 0203h */ +#define GPIO_IO_RX_EN BIT(5) +#define GPIO_OUT_LGC BIT(4) +#define GPIO_RX_EN_B BIT(3) +#define GPIO_TX_EN_B BIT(2) +#define GPIO_RX_EN_A BIT(1) +#define GPIO_TX_EN_A BIT(0) + +/* 0750h */ +#define FRCZEROPAD GENMASK(7, 6) +#define FRCZPEN BIT(5) +#define FRCSDGAIN BIT(4) +#define FRCSDEN BIT(3) +#define FRCGAIN GENMASK(2, 1) +#define FRCEN BIT(0) + +/* 0751h */ +#define FRCDATAWIDTH BIT(3) +#define FRCASYNCEN BIT(2) +#define FRCHSPOL BIT(1) +#define FRCVSPOL BIT(0) + +/* 0752h */ +#define FRCDCMODE GENMASK(1, 0) + +/* 641Ah */ +#define DPRX_TRAIN_STATE GENMASK(7, 4) + +/* 7000h */ +#define LINK_ENABLE BIT(0) + +/* 7070h */ +#define MAX_LANE_COUNT GENMASK(7, 0) + +/* 7074h */ +#define MAX_LINK_RATE GENMASK(7, 0) + +enum link_mode { + DUAL_LINK, + LINKA, + LINKB, + SPLITTER_MODE, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.c b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.c new file mode 100644 index 0000000000..7d04c87ad9 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-max96752.c -- I2C register interface access for max96752 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ +#include "../core.h" +#include "maxim-max96752.h" + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96752_GPIO0_pins[] = {0}; +static int MAX96752_GPIO1_pins[] = {1}; +static int MAX96752_GPIO2_pins[] = {2}; +static int MAX96752_GPIO3_pins[] = {3}; +static int MAX96752_GPIO4_pins[] = {4}; +static int MAX96752_GPIO5_pins[] = {5}; +static int MAX96752_GPIO6_pins[] = {6}; +static int MAX96752_GPIO7_pins[] = {7}; + +static int MAX96752_GPIO8_pins[] = {8}; +static int MAX96752_GPIO9_pins[] = {9}; +static int MAX96752_GPIO10_pins[] = {10}; +static int MAX96752_GPIO11_pins[] = {11}; +static int MAX96752_GPIO12_pins[] = {12}; +static int MAX96752_GPIO13_pins[] = {13}; +static int MAX96752_GPIO14_pins[] = {14}; +static int MAX96752_GPIO15_pins[] = {15}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_tx_en:1; + u8 gpio_rx_en:1; + u8 gpio_in_level:1; + u8 gpio_out_level:1; + u8 gpio_tx_id; + u8 gpio_rx_id; + u16 mdelay; +}; + +static const char *serdes_gpio_groups[] = { + "MAX96752_GPIO0", "MAX96752_GPIO1", "MAX96752_GPIO2", "MAX96752_GPIO3", + "MAX96752_GPIO4", "MAX96752_GPIO5", "MAX96752_GPIO6", "MAX96752_GPIO7", + + "MAX96752_GPIO8", "MAX96752_GPIO9", "MAX96752_GPIO10", "MAX96752_GPIO11", + "MAX96752_GPIO12", "MAX96752_GPIO13", "MAX96752_GPIO14", "MAX96752_GPIO15", +}; + +#define FUNCTION_DESC_GPIO_INPUT_BYPASS(id) \ +{ \ + .name = "SER_TO_DES_RXID"#id, \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_BYPASS(id) \ +{ \ + .name = "DES_TXID"#id"_TO_SER", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_LOW(id) \ +{ \ + .name = "DES_TXID"#id"_OUTPUT_LOW", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 0, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_HIGH(id) \ +{ \ + .name = "DES_TXID"#id"_OUTPUT_HIGH", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DES_DELAY_MS(ms) \ +{ \ + .name = "DELAY_"#ms"MS", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .mdelay = ms, } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96752_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96752_GPIO0, "MAX96752_GPIO0"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO1, "MAX96752_GPIO1"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO2, "MAX96752_GPIO2"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO3, "MAX96752_GPIO3"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO4, "MAX96752_GPIO4"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO5, "MAX96752_GPIO5"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO6, "MAX96752_GPIO6"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO7, "MAX96752_GPIO7"), + + PINCTRL_PIN(MAXIM_MAX96752_GPIO8, "MAX96752_GPIO8"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO9, "MAX96752_GPIO9"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO10, "MAX96752_GPIO10"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO11, "MAX96752_GPIO11"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO12, "MAX96752_GPIO12"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO13, "MAX96752_GPIO13"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO14, "MAX96752_GPIO14"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO15, "MAX96752_GPIO15"), +}; + +static struct group_desc max96752_groups_desc[] = { + GROUP_DESC(MAX96752_GPIO0), + GROUP_DESC(MAX96752_GPIO1), + GROUP_DESC(MAX96752_GPIO2), + GROUP_DESC(MAX96752_GPIO3), + GROUP_DESC(MAX96752_GPIO4), + GROUP_DESC(MAX96752_GPIO5), + GROUP_DESC(MAX96752_GPIO6), + GROUP_DESC(MAX96752_GPIO7), + + GROUP_DESC(MAX96752_GPIO8), + GROUP_DESC(MAX96752_GPIO9), + GROUP_DESC(MAX96752_GPIO10), + GROUP_DESC(MAX96752_GPIO11), + GROUP_DESC(MAX96752_GPIO12), + GROUP_DESC(MAX96752_GPIO13), + GROUP_DESC(MAX96752_GPIO14), + GROUP_DESC(MAX96752_GPIO15), +}; + +static struct function_desc max96752_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT_BYPASS(0), + FUNCTION_DESC_GPIO_INPUT_BYPASS(1), + FUNCTION_DESC_GPIO_INPUT_BYPASS(2), + FUNCTION_DESC_GPIO_INPUT_BYPASS(3), + FUNCTION_DESC_GPIO_INPUT_BYPASS(4), + FUNCTION_DESC_GPIO_INPUT_BYPASS(5), + FUNCTION_DESC_GPIO_INPUT_BYPASS(6), + FUNCTION_DESC_GPIO_INPUT_BYPASS(7), + + FUNCTION_DESC_GPIO_INPUT_BYPASS(8), + FUNCTION_DESC_GPIO_INPUT_BYPASS(9), + FUNCTION_DESC_GPIO_INPUT_BYPASS(10), + FUNCTION_DESC_GPIO_INPUT_BYPASS(11), + FUNCTION_DESC_GPIO_INPUT_BYPASS(12), + FUNCTION_DESC_GPIO_INPUT_BYPASS(13), + FUNCTION_DESC_GPIO_INPUT_BYPASS(14), + FUNCTION_DESC_GPIO_INPUT_BYPASS(15), + + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(0), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(1), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(2), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(3), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(4), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(5), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(6), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(7), + + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(8), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(9), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(10), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(11), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(12), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(13), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(14), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(15), + + FUNCTION_DESC_GPIO_OUTPUT_LOW(0), + FUNCTION_DESC_GPIO_OUTPUT_LOW(1), + FUNCTION_DESC_GPIO_OUTPUT_LOW(2), + FUNCTION_DESC_GPIO_OUTPUT_LOW(3), + FUNCTION_DESC_GPIO_OUTPUT_LOW(4), + FUNCTION_DESC_GPIO_OUTPUT_LOW(5), + FUNCTION_DESC_GPIO_OUTPUT_LOW(6), + FUNCTION_DESC_GPIO_OUTPUT_LOW(7), + + FUNCTION_DESC_GPIO_OUTPUT_LOW(8), + FUNCTION_DESC_GPIO_OUTPUT_LOW(9), + FUNCTION_DESC_GPIO_OUTPUT_LOW(10), + FUNCTION_DESC_GPIO_OUTPUT_LOW(11), + FUNCTION_DESC_GPIO_OUTPUT_LOW(12), + FUNCTION_DESC_GPIO_OUTPUT_LOW(13), + FUNCTION_DESC_GPIO_OUTPUT_LOW(14), + FUNCTION_DESC_GPIO_OUTPUT_LOW(15), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(0), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(1), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(2), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(3), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(4), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(5), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(6), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(7), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(8), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(9), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(10), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(11), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(12), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(13), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(14), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(15), + + FUNCTION_DES_DELAY_MS(10), + FUNCTION_DES_DELAY_MS(50), + FUNCTION_DES_DELAY_MS(100), + FUNCTION_DES_DELAY_MS(200), + FUNCTION_DES_DELAY_MS(500), +}; + +static struct serdes_chip_pinctrl_info max96752_pinctrl_info = { + .pins = max96752_pins_desc, + .num_pins = ARRAY_SIZE(max96752_pins_desc), + .groups = max96752_groups_desc, + .num_groups = ARRAY_SIZE(max96752_groups_desc), + .functions = max96752_functions_desc, + .num_functions = ARRAY_SIZE(max96752_functions_desc), +}; + +static int max96752_panel_prepare(struct serdes *serdes) +{ + return 0; +} + +static int max96752_panel_unprepare(struct serdes *serdes) +{ + //serdes_reg_write(serdes, 0x0215, 0x80); /* lcd_en */ + + return 0; +} + +static int max96752_panel_enable(struct serdes *serdes) +{ + return 0; +} + +static int max96752_panel_disable(struct serdes *serdes) +{ + return 0; +} + +static int max96752_panel_backlight_enable(struct serdes *serdes) +{ + return 0; +} + +static int max96752_panel_backlight_disable(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_panel_ops max96752_panel_ops = { + .prepare = max96752_panel_prepare, + .unprepare = max96752_panel_unprepare, + .enable = max96752_panel_enable, + .disable = max96752_panel_disable, + .backlight_enable = max96752_panel_backlight_enable, + .backlight_disable = max96752_panel_backlight_disable, +}; + +static int max96752_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + offset = pin->number; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en) | + FIELD_PREP(GPIO_OUT, fdata->gpio_out_level)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + + return 0; +} + +static int max96752_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p, num=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en) | + FIELD_PREP(GPIO_OUT, fdata->gpio_out_level)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96752_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, + unsigned int argument) +{ + u8 res_cfg; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, argument)); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops max96752_pinctrl_ops = { + .pinconf_set = max96752_pinctrl_config_set, + .pinmux_set = max96752_pinctrl_set_pin_mux, + .pinmux_group_set = max96752_pinctrl_set_grp_mux, +}; + +static int max96752_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96752_gpio_direction_output(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int max96752_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96752_gpio_set_level(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96752_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int max96752_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops max96752_gpio_ops = { + .direction_input = max96752_gpio_direction_input, + .direction_output = max96752_gpio_direction_output, + .get_level = max96752_gpio_get_level, + .set_level = max96752_gpio_set_level, + .set_config = max96752_gpio_set_config, + .to_irq = max96752_gpio_to_irq, +}; + +static int max96752_set_i2c_addr(struct serdes *serdes, int address, int link) +{ + int ret; + + if (link == LINKA) { + /* TX_SRC_ID[1] = 0 */ + ret = serdes_reg_write(serdes, 0x73, 0x31); + /* Receive packets with this stream ID = 0 */ + ret = serdes_reg_write(serdes, 0x50, 0x00); + ret = serdes_reg_write(serdes, 0x00, address << 1); + } else if (link == LINKB) { + /* TX_SRC_ID[1] = 1 */ + ret = serdes_reg_write(serdes, 0x73, 0x32); + /* Receive packets with this stream ID = 1 */ + ret = serdes_reg_write(serdes, 0x50, 0x01); + ret = serdes_reg_write(serdes, 0x00, address << 1); + } else { + dev_info(serdes->dev, "link %d is error\n", link); + ret = -1; + } + + SERDES_DBG_CHIP("%s: set serdes chip %s i2c 7bit address to 0x%x\n", __func__, + serdes->chip_data->name, address); + + return ret; +} + +static struct serdes_chip_split_ops max96752_split_ops = { + .set_i2c_addr = max96752_set_i2c_addr, +}; + +struct serdes_chip_data serdes_max96752_data = { + .name = "max96752", + .serdes_type = TYPE_DES, + .serdes_id = MAXIM_ID_MAX96752, + .connector_type = DRM_MODE_CONNECTOR_LVDS, + .pinctrl_info = &max96752_pinctrl_info, + .panel_ops = &max96752_panel_ops, + .pinctrl_ops = &max96752_pinctrl_ops, + .split_ops = &max96752_split_ops, + .gpio_ops = &max96752_gpio_ops, +}; +EXPORT_SYMBOL_GPL(serdes_max96752_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.h b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.h new file mode 100644 index 0000000000..5ff34f2c79 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96752.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * maxim-max96752.h -- register define for max96752 chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_MAXIM_MAX96752_H__ +#define __MFD_SERDES_MAXIM_MAX96752_H__ + +#include + +#define GPIO_A_REG(gpio) (0x0200 + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x0201 + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x0202 + ((gpio) * 3)) + +/* 0200h */ +#define RES_CFG BIT(7) +#define RSVD BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 0201h */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 0202h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + +enum link_mode { + DUAL_LINK, + LINKA, + LINKB, + SPLITTER_MODE, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.c b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.c new file mode 100644 index 0000000000..2fa63d9b3b --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.c @@ -0,0 +1,709 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-max96755.c -- I2C register interface access for max96755 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" +#include "maxim-max96755.h" + +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_tx_en:1; + u8 gpio_rx_en:1; + u8 gpio_tx_id; + u8 gpio_rx_id; + u16 mdelay; +}; + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96755_MFP0_pins[] = {0}; +static int MAX96755_MFP1_pins[] = {1}; +static int MAX96755_MFP2_pins[] = {2}; +static int MAX96755_MFP3_pins[] = {3}; +static int MAX96755_MFP4_pins[] = {4}; +static int MAX96755_MFP5_pins[] = {5}; +static int MAX96755_MFP6_pins[] = {6}; +static int MAX96755_MFP7_pins[] = {7}; + +static int MAX96755_MFP8_pins[] = {8}; +static int MAX96755_MFP9_pins[] = {9}; +static int MAX96755_MFP10_pins[] = {10}; +static int MAX96755_MFP11_pins[] = {11}; +static int MAX96755_MFP12_pins[] = {12}; +static int MAX96755_MFP13_pins[] = {13}; +static int MAX96755_MFP14_pins[] = {14}; +static int MAX96755_MFP15_pins[] = {15}; + +static int MAX96755_MFP16_pins[] = {16}; +static int MAX96755_MFP17_pins[] = {17}; +static int MAX96755_MFP18_pins[] = {18}; +static int MAX96755_MFP19_pins[] = {19}; +static int MAX96755_MFP20_pins[] = {20}; +static int MAX96755_I2C_pins[] = {19, 20}; +static int MAX96755_UART_pins[] = {19, 20}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +#define GROUP_DESC_CONFIG(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ + .data = (void *)(const struct serdes_group_data []) { \ + { \ + .configs = nm ## _configs, \ + .num_configs = ARRAY_SIZE(nm ## _configs), \ + } \ + }, \ +} + +static const struct config_desc MAX96755_MFP0_configs[] = { + { 0x0005, LOCK_EN, 0 }, + { 0x0048, LOC_MS_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP1_configs[] = { + { 0x0005, ERRB_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP4_configs[] = { + { 0x070, SPI_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP5_configs[] = { + { 0x006, RCLKEN, 0 }, +}; + +static const struct config_desc MAX96755_MFP7_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96755_MFP8_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96755_MFP9_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96755_MFP10_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP11_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP12_configs[] = { + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP13_configs[] = { + { 0x0005, PU_LF0, 0 }, +}; + +static const struct config_desc MAX96755_MFP14_configs[] = { + { 0x0005, PU_LF1, 0 }, +}; + +static const struct config_desc MAX96755_MFP15_configs[] = { + { 0x0005, PU_LF2, 0 }, +}; + +static const struct config_desc MAX96755_MFP16_configs[] = { + { 0x0005, PU_LF3, 0 }, +}; + +static const struct config_desc MAX96755_MFP17_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, +}; + +static const struct config_desc MAX96755_MFP18_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, +}; + +static const char *serdes_gpio_groups[] = { + "MAX96755_MFP0", "MAX96755_MFP1", "MAX96755_MFP2", "MAX96755_MFP3", + "MAX96755_MFP4", "MAX96755_MFP5", "MAX96755_MFP6", "MAX96755_MFP7", + + "MAX96755_MFP8", "MAX96755_MFP9", "MAX96755_MFP10", "MAX96755_MFP11", + "MAX96755_MFP12", "MAX96755_MFP13", "MAX96755_MFP14", "MAX96755_MFP15", + + "MAX96755_MFP16", "MAX96755_MFP17", "MAX96755_MFP18", "MAX96755_MFP19", + "MAX96755_MFP20", +}; + +static const char *MAX96755_I2C_groups[] = { "MAX96755_I2C" }; +static const char *MAX96755_UART_groups[] = { "MAX96755_UART" }; + +#define FUNCTION_DESC(nm) \ +{ \ + .name = #nm, \ + .group_names = nm##_groups, \ + .num_group_names = ARRAY_SIZE(nm##_groups), \ +} \ + +#define FUNCTION_DESC_GPIO_INPUT(id) \ +{ \ + .name = "DES_RXID"#id"_TO_SER", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_rx_en = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT(id) \ +{ \ + .name = "SER_TXID"#id"_TO_DES", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96755_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96755_MFP0, "MAX96755_MFP0"), + PINCTRL_PIN(MAXIM_MAX96755_MFP1, "MAX96755_MFP1"), + PINCTRL_PIN(MAXIM_MAX96755_MFP2, "MAX96755_MFP2"), + PINCTRL_PIN(MAXIM_MAX96755_MFP3, "MAX96755_MFP3"), + PINCTRL_PIN(MAXIM_MAX96755_MFP4, "MAX96755_MFP4"), + PINCTRL_PIN(MAXIM_MAX96755_MFP5, "MAX96755_MFP5"), + PINCTRL_PIN(MAXIM_MAX96755_MFP6, "MAX96755_MFP6"), + PINCTRL_PIN(MAXIM_MAX96755_MFP7, "MAX96755_MFP7"), + + PINCTRL_PIN(MAXIM_MAX96755_MFP8, "MAX96755_MFP8"), + PINCTRL_PIN(MAXIM_MAX96755_MFP9, "MAX96755_MFP9"), + PINCTRL_PIN(MAXIM_MAX96755_MFP10, "MAX96755_MFP10"), + PINCTRL_PIN(MAXIM_MAX96755_MFP11, "MAX96755_MFP11"), + PINCTRL_PIN(MAXIM_MAX96755_MFP12, "MAX96755_MFP12"), + PINCTRL_PIN(MAXIM_MAX96755_MFP13, "MAX96755_MFP13"), + PINCTRL_PIN(MAXIM_MAX96755_MFP14, "MAX96755_MFP14"), + PINCTRL_PIN(MAXIM_MAX96755_MFP15, "MAX96755_MFP15"), + + PINCTRL_PIN(MAXIM_MAX96755_MFP16, "MAX96755_MFP16"), + PINCTRL_PIN(MAXIM_MAX96755_MFP17, "MAX96755_MFP17"), + PINCTRL_PIN(MAXIM_MAX96755_MFP18, "MAX96755_MFP18"), + PINCTRL_PIN(MAXIM_MAX96755_MFP19, "MAX96755_MFP19"), + PINCTRL_PIN(MAXIM_MAX96755_MFP20, "MAX96755_MFP20"), +}; + +static struct group_desc max96755_groups_desc[] = { + GROUP_DESC_CONFIG(MAX96755_MFP0), + GROUP_DESC_CONFIG(MAX96755_MFP1), + GROUP_DESC(MAX96755_MFP2), + GROUP_DESC(MAX96755_MFP3), + GROUP_DESC_CONFIG(MAX96755_MFP4), + GROUP_DESC_CONFIG(MAX96755_MFP5), + GROUP_DESC(MAX96755_MFP6), + GROUP_DESC_CONFIG(MAX96755_MFP7), + + GROUP_DESC_CONFIG(MAX96755_MFP8), + GROUP_DESC_CONFIG(MAX96755_MFP9), + GROUP_DESC_CONFIG(MAX96755_MFP10), + GROUP_DESC_CONFIG(MAX96755_MFP11), + GROUP_DESC_CONFIG(MAX96755_MFP12), + GROUP_DESC_CONFIG(MAX96755_MFP13), + GROUP_DESC_CONFIG(MAX96755_MFP14), + GROUP_DESC_CONFIG(MAX96755_MFP15), + + GROUP_DESC_CONFIG(MAX96755_MFP16), + GROUP_DESC_CONFIG(MAX96755_MFP17), + GROUP_DESC_CONFIG(MAX96755_MFP18), + GROUP_DESC(MAX96755_MFP19), + GROUP_DESC(MAX96755_MFP20), + GROUP_DESC(MAX96755_I2C), + GROUP_DESC(MAX96755_UART), +}; + +static struct function_desc max96755_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT(0), + FUNCTION_DESC_GPIO_INPUT(1), + FUNCTION_DESC_GPIO_INPUT(2), + FUNCTION_DESC_GPIO_INPUT(3), + FUNCTION_DESC_GPIO_INPUT(4), + FUNCTION_DESC_GPIO_INPUT(5), + FUNCTION_DESC_GPIO_INPUT(6), + FUNCTION_DESC_GPIO_INPUT(7), + + FUNCTION_DESC_GPIO_INPUT(8), + FUNCTION_DESC_GPIO_INPUT(9), + FUNCTION_DESC_GPIO_INPUT(10), + FUNCTION_DESC_GPIO_INPUT(11), + FUNCTION_DESC_GPIO_INPUT(12), + FUNCTION_DESC_GPIO_INPUT(13), + FUNCTION_DESC_GPIO_INPUT(14), + FUNCTION_DESC_GPIO_INPUT(15), + + FUNCTION_DESC_GPIO_INPUT(16), + FUNCTION_DESC_GPIO_INPUT(17), + FUNCTION_DESC_GPIO_INPUT(18), + FUNCTION_DESC_GPIO_INPUT(19), + FUNCTION_DESC_GPIO_INPUT(20), + + FUNCTION_DESC_GPIO_OUTPUT(0), + FUNCTION_DESC_GPIO_OUTPUT(1), + FUNCTION_DESC_GPIO_OUTPUT(2), + FUNCTION_DESC_GPIO_OUTPUT(3), + FUNCTION_DESC_GPIO_OUTPUT(4), + FUNCTION_DESC_GPIO_OUTPUT(5), + FUNCTION_DESC_GPIO_OUTPUT(6), + FUNCTION_DESC_GPIO_OUTPUT(7), + + FUNCTION_DESC_GPIO_OUTPUT(8), + FUNCTION_DESC_GPIO_OUTPUT(9), + FUNCTION_DESC_GPIO_OUTPUT(10), + FUNCTION_DESC_GPIO_OUTPUT(11), + FUNCTION_DESC_GPIO_OUTPUT(12), + FUNCTION_DESC_GPIO_OUTPUT(13), + FUNCTION_DESC_GPIO_OUTPUT(14), + FUNCTION_DESC_GPIO_OUTPUT(15), + + FUNCTION_DESC_GPIO_OUTPUT(16), + FUNCTION_DESC_GPIO_OUTPUT(17), + FUNCTION_DESC_GPIO_OUTPUT(18), + FUNCTION_DESC_GPIO_OUTPUT(19), + FUNCTION_DESC_GPIO_OUTPUT(20), + + FUNCTION_DESC(MAX96755_I2C), + FUNCTION_DESC(MAX96755_UART), +}; + +static struct serdes_chip_pinctrl_info max96755_pinctrl_info = { + .pins = max96755_pins_desc, + .num_pins = ARRAY_SIZE(max96755_pins_desc), + .groups = max96755_groups_desc, + .num_groups = ARRAY_SIZE(max96755_groups_desc), + .functions = max96755_functions_desc, + .num_functions = ARRAY_SIZE(max96755_functions_desc), +}; + +static bool max96755_bridge_link_locked(struct serdes *serdes) +{ + u32 val; + + if (dm_gpio_is_valid(&serdes->lock_gpio)) { + val = dm_gpio_get_value(&serdes->lock_gpio); + SERDES_DBG_CHIP("serdes %s:val=%d\n", __func__, val); + return val; + } + + if (serdes_reg_read(serdes, 0x0013, &val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + return true; +} + +static bool max96755_bridge_detect(struct serdes *serdes) +{ + return max96755_bridge_link_locked(serdes); +} + +static int max96755_bridge_enable(struct serdes *serdes) +{ + int ret = 0; + + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", + __func__, serdes->chip_data->name, ret); + return ret; +} + +static int max96755_bridge_disable(struct serdes *serdes) +{ + int ret = 0; + + ret = serdes_set_bits(serdes, 0x0002, VID_TX_EN_X, + FIELD_PREP(VID_TX_EN_X, 0)); + + return ret; +} + +static struct serdes_chip_bridge_ops max96755_bridge_ops = { + .detect = max96755_bridge_detect, + .enable = max96755_bridge_enable, + .disable = max96755_bridge_disable, +}; + +static int max96755_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + offset = pin->number; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); + + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + + return 0; +} + +static int max96755_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p, num=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96755_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + u8 res_cfg; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, argument)); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops max96755_pinctrl_ops = { + .pinconf_set = max96755_pinctrl_config_set, + .pinmux_set = max96755_pinctrl_set_pin_mux, + .pinmux_group_set = max96755_pinctrl_set_grp_mux, +}; + +static int max96755_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96755_gpio_direction_output(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int max96755_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96755_gpio_set_level(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96755_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int max96755_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops max96755_gpio_ops = { + .direction_input = max96755_gpio_direction_input, + .direction_output = max96755_gpio_direction_output, + .get_level = max96755_gpio_get_level, + .set_level = max96755_gpio_set_level, + .set_config = max96755_gpio_set_config, + .to_irq = max96755_gpio_to_irq, +}; + +static int max96755_select(struct serdes *serdes, int chan) +{ + u32 link_cfg; + int ret = 0; + + serdes_set_bits(serdes, 0x0001, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + + serdes_reg_read(serdes, 0x0010, &link_cfg); + if ((link_cfg & LINK_CFG) == SPLITTER_MODE) + SERDES_DBG_CHIP("%s: serdes %s is split mode cfg=0x%x\n", + __func__, + serdes->chip_data->name, link_cfg); + + if (chan == 0 && (link_cfg & LINK_CFG) != DUAL_LINK) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 1)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, DUAL_LINK)); + SERDES_DBG_CHIP("%s: change to use dual link\n", __func__); + } else if (chan == 1 && (link_cfg & LINK_CFG) != LINKA) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 0)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, LINKA)); + SERDES_DBG_CHIP("%s: change to use linkA\n", __func__); + } else if (chan == 2 && (link_cfg & LINK_CFG) != LINKB) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 0) | + FIELD_PREP(LINK_EN_B, 1)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, LINKB)); + SERDES_DBG_CHIP("%s: change to use linkB\n", __func__); + } else if (chan == 3 && (link_cfg & LINK_CFG) != SPLITTER_MODE) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 1)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, SPLITTER_MODE)); + SERDES_DBG_CHIP("%s: change to use split mode\n", __func__); + } + + return ret; +} + +static int max96755_deselect(struct serdes *serdes, int chan) +{ + //serdes_set_bits(serdes, 0x0001, DIS_REM_CC, + // FIELD_PREP(DIS_REM_CC, 1)); + + return 0; +} + +static struct serdes_chip_split_ops max96755_split_ops = { + .select = max96755_select, + .deselect = max96755_deselect, +}; + +struct serdes_chip_data serdes_max96755_data = { + .name = "max96755", + .serdes_type = TYPE_SER, + .serdes_id = MAXIM_ID_MAX96755, + .connector_type = DRM_MODE_CONNECTOR_DSI, + .pinctrl_info = &max96755_pinctrl_info, + .bridge_ops = &max96755_bridge_ops, + .pinctrl_ops = &max96755_pinctrl_ops, + .gpio_ops = &max96755_gpio_ops, + .split_ops = &max96755_split_ops, +}; +EXPORT_SYMBOL_GPL(serdes_max96755_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.h b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.h new file mode 100644 index 0000000000..af96a81dd2 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96755.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * maxim-max96755.h -- register define for max96755 chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_MAXIM_MAX96755_H__ +#define __MFD_SERDES_MAXIM_MAX96755_H__ + +#include + +#define GPIO_A_REG(gpio) (0x02be + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x02bf + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x02c0 + ((gpio) * 3)) + +/* 0000h */ +#define DEV_ADDR GENMASK(7, 1) +#define CFG_BLOCK BIT(0) + +/* 0001h */ +#define IIC_2_EN BIT(7) +#define IIC_1_EN BIT(6) +#define DIS_REM_CC BIT(4) +#define TX_RATE GENMASK(3, 2) + +/* 0002h */ +#define VID_TX_EN_U BIT(7) +#define VID_TX_EN_Z BIT(6) +#define VID_TX_EN_Y BIT(5) +#define VID_TX_EN_X BIT(4) +#define AUD_TX_EN_Y BIT(3) +#define AUD_TX_EN_X BIT(2) + +/* 0003h */ +#define UART_2_EN BIT(5) +#define UART_1_EN BIT(4) + +/* 0004h */ +#define GMSL2_B BIT(7) +#define GMSL2_A BIT(6) +#define LINK_EN_B BIT(5) +#define LINK_EN_A BIT(4) +#define AUD_TX_SRC_Y BIT(1) +#define AUD_TX_SRC_X BIT(0) + +/* 0005h */ +#define LOCK_EN BIT(7) +#define ERRB_EN BIT(6) +#define PU_LF3 BIT(3) +#define PU_LF2 BIT(2) +#define PU_LF1 BIT(1) +#define PU_LF0 BIT(0) + +/* 0006h */ +#define RCLKEN BIT(5) + +/* 0010h */ +#define RESET_ALL BIT(7) +#define RESET_LINK BIT(6) +#define RESET_ONESHOT BIT(5) +#define AUTO_LINK BIT(4) +#define SLEEP BIT(3) +#define REG_ENABLE BIT(2) +#define LINK_CFG GENMASK(1, 0) + +/* 0013h */ +#define LINK_MODE GENMASK(5, 4) +#define LOCKED BIT(3) + +/* 0026h */ +#define LF_1 GENMASK(6, 4) +#define LF_0 GENMASK(2, 0) + +/* 0048h */ +#define REM_MS_EN BIT(5) +#define LOC_MS_EN BIT(4) + +/* 0053h */ +#define TX_SPLIT_MASK_B BIT(5) +#define TX_SPLIT_MASK_A BIT(4) +#define TX_STR_SEL GENMASK(1, 0) + +/* 0140h */ +#define AUD_RX_EN BIT(0) + +/* 0170h */ +#define SPI_EN BIT(0) + +/* 01e5h */ +#define PATGEN_MODE GENMASK(1, 0) + +/* 02beh */ +#define RES_CFG BIT(7) +#define TX_PRIO BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 02bfh */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 02c0h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + +/* 0311h */ +#define START_PORTBU BIT(7) +#define START_PORTBZ BIT(6) +#define START_PORTBY BIT(5) +#define START_PORTBX BIT(4) +#define START_PORTAU BIT(3) +#define START_PORTAZ BIT(2) +#define START_PORTAY BIT(1) +#define START_PORTAX BIT(0) + +/* 032ah */ +#define DV_LOCK BIT(7) +#define DV_SWP_AB BIT(6) +#define LINE_ALT BIT(5) +#define DV_CONV BIT(2) +#define DV_SPL BIT(1) +#define DV_EN BIT(0) + +/* 0330h */ +#define PHY_CONFIG GENMASK(2, 0) +#define MIPI_RX_RESET BIT(3) + +/* 0331h */ +#define NUM_LANES GENMASK(1, 0) + +/* 0385h */ +#define DPI_HSYNC_WIDTH_L GENMASK(7, 0) + +/* 0386h */ +#define DPI_VYSNC_WIDTH_L GENMASK(7, 0) + +/* 0387h */ +#define DPI_HSYNC_WIDTH_H GENMASK(3, 0) +#define DPI_VSYNC_WIDTH_H GENMASK(7, 4) + +/* 03a4h */ +#define DPI_DE_SKEW_SEL BIT(1) +#define DPI_DESKEW_EN BIT(0) + +/* 03a5h */ +#define DPI_VFP_L GENMASK(7, 0) + +/* 03a6h */ +#define DPI_VFP_H GENMASK(3, 0) +#define DPI_VBP_L GENMASK(7, 4) + +/* 03a7h */ +#define DPI_VBP_H GENMASK(7, 0) + +/* 03a8h */ +#define DPI_VACT_L GENMASK(7, 0) + +/* 03a9h */ +#define DPI_VACT_H GENMASK(3, 0) + +/* 03aah */ +#define DPI_HFP_L GENMASK(7, 0) + +/* 03abh */ +#define DPI_HFP_H GENMASK(3, 0) +#define DPI_HBP_L GENMASK(7, 4) + +/* 03ach */ +#define DPI_HBP_H GENMASK(7, 0) + +/* 03adh */ +#define DPI_HACT_L GENMASK(7, 0) + +/* 03aeh */ +#define DPI_HACT_H GENMASK(4, 0) + +/* 055dh */ +#define VS_DET BIT(5) +#define HS_DET BIT(4) + +enum link_mode { + DUAL_LINK, + LINKA, + LINKB, + SPLITTER_MODE, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.c b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.c new file mode 100644 index 0000000000..aa24fc5b5e --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.c @@ -0,0 +1,737 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-max96772.c -- I2C register interface access for max96772 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" +#include "maxim-max96772.h" + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96772_GPIO0_pins[] = {0}; +static int MAX96772_GPIO1_pins[] = {1}; +static int MAX96772_GPIO2_pins[] = {2}; +static int MAX96772_GPIO3_pins[] = {3}; +static int MAX96772_GPIO4_pins[] = {4}; +static int MAX96772_GPIO5_pins[] = {5}; +static int MAX96772_GPIO6_pins[] = {6}; +static int MAX96772_GPIO7_pins[] = {7}; + +static int MAX96772_GPIO8_pins[] = {8}; +static int MAX96772_GPIO9_pins[] = {9}; +static int MAX96772_GPIO10_pins[] = {10}; +static int MAX96772_GPIO11_pins[] = {11}; +static int MAX96772_GPIO12_pins[] = {12}; +static int MAX96772_GPIO13_pins[] = {13}; +static int MAX96772_GPIO14_pins[] = {14}; +static int MAX96772_GPIO15_pins[] = {15}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_tx_en:1; + u8 gpio_rx_en:1; + u8 gpio_in_level:1; + u8 gpio_out_level:1; + u8 gpio_tx_id; + u8 gpio_rx_id; + u16 mdelay; +}; + +static const char *serdes_gpio_groups[] = { + "MAX96772_GPIO0", "MAX96772_GPIO1", "MAX96772_GPIO2", "MAX96772_GPIO3", + "MAX96772_GPIO4", "MAX96772_GPIO5", "MAX96772_GPIO6", "MAX96772_GPIO7", + + "MAX96772_GPIO8", "MAX96772_GPIO9", "MAX96772_GPIO10", "MAX96772_GPIO11", + "MAX96772_GPIO12", "MAX96772_GPIO13", "MAX96772_GPIO14", "MAX96772_GPIO15", +}; + +#define FUNCTION_DESC_GPIO_INPUT_BYPASS(id) \ +{ \ + .name = "SER_TO_DES_RXID"#id, \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_BYPASS(id) \ +{ \ + .name = "DES_TXID"#id"_TO_SER", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_LOW(id) \ +{ \ + .name = "DES_TXID"#id"_OUTPUT_LOW", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 0, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_HIGH(id) \ +{ \ + .name = "DES_TXID"#id"_OUTPUT_HIGH", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#define FUNCTION_DES_DELAY_MS(ms) \ +{ \ + .name = "DELAY_"#ms"MS", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .mdelay = ms, } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96772_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96772_GPIO0, "MAX96772_GPIO0"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO1, "MAX96772_GPIO1"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO2, "MAX96772_GPIO2"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO3, "MAX96772_GPIO3"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO4, "MAX96772_GPIO4"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO5, "MAX96772_GPIO5"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO6, "MAX96772_GPIO6"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO7, "MAX96772_GPIO7"), + + PINCTRL_PIN(MAXIM_MAX96772_GPIO8, "MAX96772_GPIO8"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO9, "MAX96772_GPIO9"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO10, "MAX96772_GPIO10"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO11, "MAX96772_GPIO11"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO12, "MAX96772_GPIO12"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO13, "MAX96772_GPIO13"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO14, "MAX96772_GPIO14"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO15, "MAX96772_GPIO15"), +}; + +static struct group_desc max96772_groups_desc[] = { + GROUP_DESC(MAX96772_GPIO0), + GROUP_DESC(MAX96772_GPIO1), + GROUP_DESC(MAX96772_GPIO2), + GROUP_DESC(MAX96772_GPIO3), + GROUP_DESC(MAX96772_GPIO4), + GROUP_DESC(MAX96772_GPIO5), + GROUP_DESC(MAX96772_GPIO6), + GROUP_DESC(MAX96772_GPIO7), + + GROUP_DESC(MAX96772_GPIO8), + GROUP_DESC(MAX96772_GPIO9), + GROUP_DESC(MAX96772_GPIO10), + GROUP_DESC(MAX96772_GPIO11), + GROUP_DESC(MAX96772_GPIO12), + GROUP_DESC(MAX96772_GPIO13), + GROUP_DESC(MAX96772_GPIO14), + GROUP_DESC(MAX96772_GPIO15), +}; + +static struct function_desc max96772_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT_BYPASS(0), + FUNCTION_DESC_GPIO_INPUT_BYPASS(1), + FUNCTION_DESC_GPIO_INPUT_BYPASS(2), + FUNCTION_DESC_GPIO_INPUT_BYPASS(3), + FUNCTION_DESC_GPIO_INPUT_BYPASS(4), + FUNCTION_DESC_GPIO_INPUT_BYPASS(5), + FUNCTION_DESC_GPIO_INPUT_BYPASS(6), + FUNCTION_DESC_GPIO_INPUT_BYPASS(7), + + FUNCTION_DESC_GPIO_INPUT_BYPASS(8), + FUNCTION_DESC_GPIO_INPUT_BYPASS(9), + FUNCTION_DESC_GPIO_INPUT_BYPASS(10), + FUNCTION_DESC_GPIO_INPUT_BYPASS(11), + FUNCTION_DESC_GPIO_INPUT_BYPASS(12), + FUNCTION_DESC_GPIO_INPUT_BYPASS(13), + FUNCTION_DESC_GPIO_INPUT_BYPASS(14), + FUNCTION_DESC_GPIO_INPUT_BYPASS(15), + + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(0), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(1), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(2), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(3), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(4), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(5), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(6), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(7), + + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(8), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(9), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(10), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(11), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(12), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(13), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(14), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(15), + + FUNCTION_DESC_GPIO_OUTPUT_LOW(0), + FUNCTION_DESC_GPIO_OUTPUT_LOW(1), + FUNCTION_DESC_GPIO_OUTPUT_LOW(2), + FUNCTION_DESC_GPIO_OUTPUT_LOW(3), + FUNCTION_DESC_GPIO_OUTPUT_LOW(4), + FUNCTION_DESC_GPIO_OUTPUT_LOW(5), + FUNCTION_DESC_GPIO_OUTPUT_LOW(6), + FUNCTION_DESC_GPIO_OUTPUT_LOW(7), + + FUNCTION_DESC_GPIO_OUTPUT_LOW(8), + FUNCTION_DESC_GPIO_OUTPUT_LOW(9), + FUNCTION_DESC_GPIO_OUTPUT_LOW(10), + FUNCTION_DESC_GPIO_OUTPUT_LOW(11), + FUNCTION_DESC_GPIO_OUTPUT_LOW(12), + FUNCTION_DESC_GPIO_OUTPUT_LOW(13), + FUNCTION_DESC_GPIO_OUTPUT_LOW(14), + FUNCTION_DESC_GPIO_OUTPUT_LOW(15), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(0), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(1), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(2), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(3), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(4), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(5), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(6), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(7), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(8), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(9), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(10), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(11), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(12), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(13), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(14), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(15), + + FUNCTION_DES_DELAY_MS(10), + FUNCTION_DES_DELAY_MS(50), + FUNCTION_DES_DELAY_MS(100), + FUNCTION_DES_DELAY_MS(200), + FUNCTION_DES_DELAY_MS(500), +}; + +static struct serdes_chip_pinctrl_info max96772_pinctrl_info = { + .pins = max96772_pins_desc, + .num_pins = ARRAY_SIZE(max96772_pins_desc), + .groups = max96772_groups_desc, + .num_groups = ARRAY_SIZE(max96772_groups_desc), + .functions = max96772_functions_desc, + .num_functions = ARRAY_SIZE(max96772_functions_desc), +}; + +static const struct reg_sequence max96772_clk_ref[3][14] = { + { + { 0xe7b2, 0x50 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0xcc }, + { 0xe7b5, 0x44 }, + { 0xe7b6, 0x81 }, + { 0xe7b7, 0x30 }, + { 0xe7b8, 0x07 }, + { 0xe7b9, 0x10 }, + { 0xe7ba, 0x01 }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x52 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x50 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0x00 }, + { 0xe7b5, 0x40 }, + { 0xe7b6, 0x6c }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x07 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x01 }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x52 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x30 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0x00 }, + { 0xe7b5, 0x40 }, + { 0xe7b6, 0x6c }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x14 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x2e }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x01 }, + { 0xe7be, 0x32 }, + { 0xe7bf, 0x00 }, + } +}; + +static int max96772_aux_dpcd_read(struct serdes *serdes, + unsigned int reg, + unsigned int *value) +{ + serdes_reg_write(serdes, 0xe778, reg & 0xff); + serdes_reg_write(serdes, 0xe779, (reg >> 8) & 0xff); + serdes_reg_write(serdes, 0xe77c, (reg >> 16) & 0xff); + serdes_reg_write(serdes, 0xe776, 0x10); + serdes_reg_write(serdes, 0xe777, 0x80); + /* FIXME */ + mdelay(50); + serdes_reg_read(serdes, 0xe77a, value); + + return 0; +} + +static int max96772_panel_init(struct serdes *serdes) +{ + return 0; +} + +static int max96772_panel_prepare(struct serdes *serdes) +{ + const struct drm_display_mode *mode = &serdes->serdes_panel->mode; + u32 hfp, hsa, hbp, hact; + u32 vact, vsa, vfp, vbp; + u64 hwords, mvid; + bool hsync_pol, vsync_pol; + + serdes_reg_write(serdes, 0xe790, serdes->serdes_panel->link_rate); + serdes_reg_write(serdes, 0xe792, serdes->serdes_panel->lane_count); + + if (serdes->serdes_panel->ssc) { + serdes_reg_write(serdes, 0xe7b0, 0x01); + serdes_reg_write(serdes, 0xe7b1, 0x10); + } else { + serdes_reg_write(serdes, 0xe7b1, 0x00); + } + + switch (serdes->serdes_panel->link_rate) { + case DP_LINK_BW_5_4: + serdes_multi_reg_write(serdes, max96772_clk_ref[2], + ARRAY_SIZE(max96772_clk_ref[2])); + break; + case DP_LINK_BW_2_7: + serdes_multi_reg_write(serdes, max96772_clk_ref[1], + ARRAY_SIZE(max96772_clk_ref[1])); + break; + case DP_LINK_BW_1_62: + default: + serdes_multi_reg_write(serdes, max96772_clk_ref[0], + ARRAY_SIZE(max96772_clk_ref[0])); + break; + } + + vact = mode->vdisplay; + vsa = mode->vsync_end - mode->vsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + hact = mode->hdisplay; + hsa = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + + serdes_reg_write(serdes, 0xe794, hact & 0xff); + serdes_reg_write(serdes, 0xe795, (hact >> 8) & 0xff); + serdes_reg_write(serdes, 0xe796, hfp & 0xff); + serdes_reg_write(serdes, 0xe797, (hfp >> 8) & 0xff); + serdes_reg_write(serdes, 0xe798, hsa & 0xff); + serdes_reg_write(serdes, 0xe799, (hsa >> 8) & 0xff); + serdes_reg_write(serdes, 0xe79a, hbp & 0xff); + serdes_reg_write(serdes, 0xe79b, (hbp >> 8) & 0xff); + serdes_reg_write(serdes, 0xe79c, vact & 0xff); + serdes_reg_write(serdes, 0xe79d, (vact >> 8) & 0xff); + serdes_reg_write(serdes, 0xe79e, vfp & 0xff); + serdes_reg_write(serdes, 0xe79f, (vfp >> 8) & 0xff); + serdes_reg_write(serdes, 0xe7a0, vsa & 0xff); + serdes_reg_write(serdes, 0xe7a1, (vsa >> 8) & 0xff); + serdes_reg_write(serdes, 0xe7a2, vbp & 0xff); + serdes_reg_write(serdes, 0xe7a3, (vbp >> 8) & 0xff); + + hsync_pol = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + vsync_pol = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + serdes_reg_write(serdes, 0xe7ac, hsync_pol | (vsync_pol << 1)); + + /* NVID should always be set to 0x8000 */ + serdes_reg_write(serdes, 0xe7a8, 0); + serdes_reg_write(serdes, 0xe7a9, 0x80); + + /* HWORDS = ((HRES x bits / pixel) / 16) - LANE_COUNT */ + hwords = DIV_ROUND_UP(hact * 24, 16) - serdes->serdes_panel->lane_count; + serdes_reg_write(serdes, 0xe7a4, hwords); + serdes_reg_write(serdes, 0xe7a5, hwords >> 8); + + /* MVID = (PCLK x NVID) x 10 / Link Rate */ + mvid = DIV_ROUND_UP((u64)mode->clock * 32768, + drm_dp_bw_code_to_link_rate(serdes->serdes_panel->link_rate)); + serdes_reg_write(serdes, 0xe7a6, mvid & 0xff); + serdes_reg_write(serdes, 0xe7a7, (mvid >> 8) & 0xff); + + serdes_reg_write(serdes, 0xe7aa, 0x40); + serdes_reg_write(serdes, 0xe7ab, 0x00); + + return 0; +} + +static int max96772_panel_unprepare(struct serdes *serdes) +{ + return 0; +} + +static int max96772_panel_enable(struct serdes *serdes) +{ + u32 status[2]; + u32 val; + int ret; + int i = 0; + + /* Run link training */ + serdes_reg_write(serdes, 0xe776, 0x02); + serdes_reg_write(serdes, 0xe777, 0x80); + + for (i = 0; i < 100; i++) { + ret = serdes_reg_read(serdes, 0x07f0, &val); + if (val & 0x01) + break; + mdelay(5); + } + + ret = max96772_aux_dpcd_read(serdes, DP_LANE0_1_STATUS, &status[0]); + if (ret) + return ret; + + ret = max96772_aux_dpcd_read(serdes, DP_LANE2_3_STATUS, &status[1]); + if (ret) + return ret; + + dev_err(serdes->dev, "Link Training failed: LANE0_1_STATUS=0x%02x, LANE2_3_STATUS=0x%02x\n", + status[0], status[1]); + + return 0; +} + +static int max96772_panel_disable(struct serdes *serdes) +{ + return 0; +} + +int max96772_panel_backlight_enable(struct serdes *serdes) +{ + return 0; +} + +int max96772_panel_backlight_disable(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_panel_ops max96772_panel_ops = { + .init = max96772_panel_init, + .prepare = max96772_panel_prepare, + .unprepare = max96772_panel_unprepare, + .enable = max96772_panel_enable, + .disable = max96772_panel_disable, + .backlight_enable = max96772_panel_backlight_enable, + .backlight_disable = max96772_panel_backlight_disable, +}; + +static int max96772_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + offset = pin->number; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en) | + FIELD_PREP(GPIO_OUT, fdata->gpio_out_level)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + + return 0; +} + +static int max96772_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p, num=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en) | + FIELD_PREP(GPIO_OUT, fdata->gpio_out_level)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96772_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, + unsigned int argument) +{ + u8 res_cfg; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, argument)); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops max96772_pinctrl_ops = { + .pinconf_set = max96772_pinctrl_config_set, + .pinmux_set = max96772_pinctrl_set_pin_mux, + .pinmux_group_set = max96772_pinctrl_set_grp_mux, +}; + +static int max96772_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96772_gpio_direction_output(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int max96772_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96772_gpio_set_level(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96772_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int max96772_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops max96772_gpio_ops = { + .direction_input = max96772_gpio_direction_input, + .direction_output = max96772_gpio_direction_output, + .get_level = max96772_gpio_get_level, + .set_level = max96772_gpio_set_level, + .set_config = max96772_gpio_set_config, + .to_irq = max96772_gpio_to_irq, +}; + +struct serdes_chip_data serdes_max96772_data = { + .name = "max96772", + .serdes_type = TYPE_DES, + .serdes_id = MAXIM_ID_MAX96772, + .connector_type = DRM_MODE_CONNECTOR_eDP, + .pinctrl_info = &max96772_pinctrl_info, + .panel_ops = &max96772_panel_ops, + .pinctrl_ops = &max96772_pinctrl_ops, + .gpio_ops = &max96772_gpio_ops, +}; +EXPORT_SYMBOL_GPL(serdes_max96772_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.h b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.h new file mode 100644 index 0000000000..a3fa4c377d --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96772.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * include/linux/mfd/serdes/gpio.h -- GPIO for different serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_MAXIM_MAX96772_H__ +#define __MFD_SERDES_MAXIM_MAX96772_H__ + +#define GPIO_A_REG(gpio) (0x02b0 + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x02b1 + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x02b2 + ((gpio) * 3)) + +/* 02b0h */ +#define RES_CFG BIT(7) +#define RSVD BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 02b1h */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 02b2h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.c b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.c new file mode 100644 index 0000000000..00329e98fa --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.c @@ -0,0 +1,726 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-max96789.c -- I2C register interface access for max96789 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" +#include "maxim-max96789.h" + +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_tx_en:1; + u8 gpio_rx_en:1; + u8 gpio_tx_id; + u8 gpio_rx_id; + u16 mdelay; +}; + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96789_MFP0_pins[] = {0}; +static int MAX96789_MFP1_pins[] = {1}; +static int MAX96789_MFP2_pins[] = {2}; +static int MAX96789_MFP3_pins[] = {3}; +static int MAX96789_MFP4_pins[] = {4}; +static int MAX96789_MFP5_pins[] = {5}; +static int MAX96789_MFP6_pins[] = {6}; +static int MAX96789_MFP7_pins[] = {7}; + +static int MAX96789_MFP8_pins[] = {8}; +static int MAX96789_MFP9_pins[] = {9}; +static int MAX96789_MFP10_pins[] = {10}; +static int MAX96789_MFP11_pins[] = {11}; +static int MAX96789_MFP12_pins[] = {12}; +static int MAX96789_MFP13_pins[] = {13}; +static int MAX96789_MFP14_pins[] = {14}; +static int MAX96789_MFP15_pins[] = {15}; + +static int MAX96789_MFP16_pins[] = {16}; +static int MAX96789_MFP17_pins[] = {17}; +static int MAX96789_MFP18_pins[] = {18}; +static int MAX96789_MFP19_pins[] = {19}; +static int MAX96789_MFP20_pins[] = {20}; +static int MAX96789_I2C_pins[] = {19, 20}; +static int MAX96789_UART_pins[] = {19, 20}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +#define GROUP_DESC_CONFIG(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ + .data = (void *)(const struct serdes_group_data []) { \ + { \ + .configs = nm ## _configs, \ + .num_configs = ARRAY_SIZE(nm ## _configs), \ + } \ + }, \ +} + +static const struct config_desc MAX96789_MFP0_configs[] = { + { 0x0005, LOCK_EN, 0 }, + { 0x0048, LOC_MS_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP1_configs[] = { + { 0x0005, ERRB_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP4_configs[] = { + { 0x070, SPI_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP5_configs[] = { + { 0x006, RCLKEN, 0 }, +}; + +static const struct config_desc MAX96789_MFP7_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP8_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP9_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP10_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP11_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP12_configs[] = { + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP13_configs[] = { + { 0x0005, PU_LF0, 0 }, +}; + +static const struct config_desc MAX96789_MFP14_configs[] = { + { 0x0005, PU_LF1, 0 }, +}; + +static const struct config_desc MAX96789_MFP15_configs[] = { + { 0x0005, PU_LF2, 0 }, +}; + +static const struct config_desc MAX96789_MFP16_configs[] = { + { 0x0005, PU_LF3, 0 }, +}; + +static const struct config_desc MAX96789_MFP17_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP18_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, +}; + +static const char *serdes_gpio_groups[] = { + "MAX96789_MFP0", "MAX96789_MFP1", "MAX96789_MFP2", "MAX96789_MFP3", + "MAX96789_MFP4", "MAX96789_MFP5", "MAX96789_MFP6", "MAX96789_MFP7", + + "MAX96789_MFP8", "MAX96789_MFP9", "MAX96789_MFP10", "MAX96789_MFP11", + "MAX96789_MFP12", "MAX96789_MFP13", "MAX96789_MFP14", "MAX96789_MFP15", + + "MAX96789_MFP16", "MAX96789_MFP17", "MAX96789_MFP18", "MAX96789_MFP19", + "MAX96789_MFP20", +}; + +static const char *MAX96789_I2C_groups[] = { "MAX96789_I2C" }; +static const char *MAX96789_UART_groups[] = { "MAX96789_UART" }; + +#define FUNCTION_DESC(nm) \ +{ \ + .name = #nm, \ + .group_names = nm##_groups, \ + .num_group_names = ARRAY_SIZE(nm##_groups), \ +} \ + +#define FUNCTION_DESC_GPIO_INPUT(id) \ +{ \ + .name = "DES_RXID"#id"_TO_SER", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_rx_en = 1, .gpio_rx_id = id } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT(id) \ +{ \ + .name = "SER_TXID"#id"_TO_DES", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 1, .gpio_tx_en = 1, .gpio_tx_id = id } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96789_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96789_MFP0, "MAX96789_MFP0"), + PINCTRL_PIN(MAXIM_MAX96789_MFP1, "MAX96789_MFP1"), + PINCTRL_PIN(MAXIM_MAX96789_MFP2, "MAX96789_MFP2"), + PINCTRL_PIN(MAXIM_MAX96789_MFP3, "MAX96789_MFP3"), + PINCTRL_PIN(MAXIM_MAX96789_MFP4, "MAX96789_MFP4"), + PINCTRL_PIN(MAXIM_MAX96789_MFP5, "MAX96789_MFP5"), + PINCTRL_PIN(MAXIM_MAX96789_MFP6, "MAX96789_MFP6"), + PINCTRL_PIN(MAXIM_MAX96789_MFP7, "MAX96789_MFP7"), + + PINCTRL_PIN(MAXIM_MAX96789_MFP8, "MAX96789_MFP8"), + PINCTRL_PIN(MAXIM_MAX96789_MFP9, "MAX96789_MFP9"), + PINCTRL_PIN(MAXIM_MAX96789_MFP10, "MAX96789_MFP10"), + PINCTRL_PIN(MAXIM_MAX96789_MFP11, "MAX96789_MFP11"), + PINCTRL_PIN(MAXIM_MAX96789_MFP12, "MAX96789_MFP12"), + PINCTRL_PIN(MAXIM_MAX96789_MFP13, "MAX96789_MFP13"), + PINCTRL_PIN(MAXIM_MAX96789_MFP14, "MAX96789_MFP14"), + PINCTRL_PIN(MAXIM_MAX96789_MFP15, "MAX96789_MFP15"), + + PINCTRL_PIN(MAXIM_MAX96789_MFP16, "MAX96789_MFP16"), + PINCTRL_PIN(MAXIM_MAX96789_MFP17, "MAX96789_MFP17"), + PINCTRL_PIN(MAXIM_MAX96789_MFP18, "MAX96789_MFP18"), + PINCTRL_PIN(MAXIM_MAX96789_MFP19, "MAX96789_MFP19"), + PINCTRL_PIN(MAXIM_MAX96789_MFP20, "MAX96789_MFP20"), +}; + +static struct group_desc max96789_groups_desc[] = { + GROUP_DESC_CONFIG(MAX96789_MFP0), + GROUP_DESC_CONFIG(MAX96789_MFP1), + GROUP_DESC(MAX96789_MFP2), + GROUP_DESC(MAX96789_MFP3), + GROUP_DESC_CONFIG(MAX96789_MFP4), + GROUP_DESC_CONFIG(MAX96789_MFP5), + GROUP_DESC(MAX96789_MFP6), + GROUP_DESC_CONFIG(MAX96789_MFP7), + + GROUP_DESC_CONFIG(MAX96789_MFP8), + GROUP_DESC_CONFIG(MAX96789_MFP9), + GROUP_DESC_CONFIG(MAX96789_MFP10), + GROUP_DESC_CONFIG(MAX96789_MFP11), + GROUP_DESC_CONFIG(MAX96789_MFP12), + GROUP_DESC_CONFIG(MAX96789_MFP13), + GROUP_DESC_CONFIG(MAX96789_MFP14), + GROUP_DESC_CONFIG(MAX96789_MFP15), + + GROUP_DESC_CONFIG(MAX96789_MFP16), + GROUP_DESC_CONFIG(MAX96789_MFP17), + GROUP_DESC_CONFIG(MAX96789_MFP18), + GROUP_DESC(MAX96789_MFP19), + GROUP_DESC(MAX96789_MFP20), + GROUP_DESC(MAX96789_I2C), + GROUP_DESC(MAX96789_UART), +}; + +static struct function_desc max96789_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT(0), + FUNCTION_DESC_GPIO_INPUT(1), + FUNCTION_DESC_GPIO_INPUT(2), + FUNCTION_DESC_GPIO_INPUT(3), + FUNCTION_DESC_GPIO_INPUT(4), + FUNCTION_DESC_GPIO_INPUT(5), + FUNCTION_DESC_GPIO_INPUT(6), + FUNCTION_DESC_GPIO_INPUT(7), + + FUNCTION_DESC_GPIO_INPUT(8), + FUNCTION_DESC_GPIO_INPUT(9), + FUNCTION_DESC_GPIO_INPUT(10), + FUNCTION_DESC_GPIO_INPUT(11), + FUNCTION_DESC_GPIO_INPUT(12), + FUNCTION_DESC_GPIO_INPUT(13), + FUNCTION_DESC_GPIO_INPUT(14), + FUNCTION_DESC_GPIO_INPUT(15), + + FUNCTION_DESC_GPIO_INPUT(16), + FUNCTION_DESC_GPIO_INPUT(17), + FUNCTION_DESC_GPIO_INPUT(18), + FUNCTION_DESC_GPIO_INPUT(19), + FUNCTION_DESC_GPIO_INPUT(20), + + FUNCTION_DESC_GPIO_OUTPUT(0), + FUNCTION_DESC_GPIO_OUTPUT(1), + FUNCTION_DESC_GPIO_OUTPUT(2), + FUNCTION_DESC_GPIO_OUTPUT(3), + FUNCTION_DESC_GPIO_OUTPUT(4), + FUNCTION_DESC_GPIO_OUTPUT(5), + FUNCTION_DESC_GPIO_OUTPUT(6), + FUNCTION_DESC_GPIO_OUTPUT(7), + + FUNCTION_DESC_GPIO_OUTPUT(8), + FUNCTION_DESC_GPIO_OUTPUT(9), + FUNCTION_DESC_GPIO_OUTPUT(10), + FUNCTION_DESC_GPIO_OUTPUT(11), + FUNCTION_DESC_GPIO_OUTPUT(12), + FUNCTION_DESC_GPIO_OUTPUT(13), + FUNCTION_DESC_GPIO_OUTPUT(14), + FUNCTION_DESC_GPIO_OUTPUT(15), + + FUNCTION_DESC_GPIO_OUTPUT(16), + FUNCTION_DESC_GPIO_OUTPUT(17), + FUNCTION_DESC_GPIO_OUTPUT(18), + FUNCTION_DESC_GPIO_OUTPUT(19), + FUNCTION_DESC_GPIO_OUTPUT(20), + + FUNCTION_DESC(MAX96789_I2C), + FUNCTION_DESC(MAX96789_UART), +}; + +static struct serdes_chip_pinctrl_info max96789_pinctrl_info = { + .pins = max96789_pins_desc, + .num_pins = ARRAY_SIZE(max96789_pins_desc), + .groups = max96789_groups_desc, + .num_groups = ARRAY_SIZE(max96789_groups_desc), + .functions = max96789_functions_desc, + .num_functions = ARRAY_SIZE(max96789_functions_desc), +}; + +static bool max96789_bridge_link_locked(struct serdes *serdes) +{ + u32 val; + + if (dm_gpio_is_valid(&serdes->lock_gpio)) { + val = dm_gpio_get_value(&serdes->lock_gpio); + SERDES_DBG_CHIP("serdes %s:val=%d\n", __func__, val); + return val; + } + + if (serdes_reg_read(serdes, 0x0013, &val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } + + return true; +} + +static bool max96789_bridge_detect(struct serdes *serdes) +{ + return max96789_bridge_link_locked(serdes); +} + +static int max96789_bridge_enable(struct serdes *serdes) +{ + int ret = 0; + + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", + __func__, serdes->chip_data->name, ret); + return ret; +} + +static int max96789_bridge_disable(struct serdes *serdes) +{ + int ret = 0; + + ret = serdes_set_bits(serdes, 0x0002, VID_TX_EN_X, + FIELD_PREP(VID_TX_EN_X, 0)); + + return ret; +} + +static struct serdes_chip_bridge_ops max96789_bridge_ops = { + .detect = max96789_bridge_detect, + .enable = max96789_bridge_enable, + .disable = max96789_bridge_disable, +}; + +static int max96789_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + offset = pin->number; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); + + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + + return 0; +} + +static int max96789_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p num=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 32) + dev_err(serdes->dev, "%s offset=%d > 32\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s txid=%d rxid=%d off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_tx_id, fdata->gpio_rx_id, offset); + + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(offset), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(offset), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(offset), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96789_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, + unsigned int argument) +{ + u8 res_cfg; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin_selector), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (argument) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin_selector), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin_selector), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, argument)); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops max96789_pinctrl_ops = { + .pinconf_set = max96789_pinctrl_config_set, + .pinmux_set = max96789_pinctrl_set_pin_mux, + .pinmux_group_set = max96789_pinctrl_set_grp_mux, +}; + +static int max96789_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96789_gpio_direction_output(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int max96789_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int max96789_gpio_set_level(struct serdes *serdes, int gpio, int value) +{ + return 0; +} + +static int max96789_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int max96789_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops max96789_gpio_ops = { + .direction_input = max96789_gpio_direction_input, + .direction_output = max96789_gpio_direction_output, + .get_level = max96789_gpio_get_level, + .set_level = max96789_gpio_set_level, + .set_config = max96789_gpio_set_config, + .to_irq = max96789_gpio_to_irq, +}; + +static int max96789_select(struct serdes *serdes, int chan) +{ + u32 link_cfg, link_status; + int ret = 0; + int i = 0; + + serdes_set_bits(serdes, 0x0001, DIS_REM_CC, + FIELD_PREP(DIS_REM_CC, 0)); + + serdes_reg_read(serdes, 0x0010, &link_cfg); + if ((link_cfg & LINK_CFG) == SPLITTER_MODE) + SERDES_DBG_CHIP("%s: serdes %s is split mode cfg=0x%x\n", + __func__, + serdes->chip_data->name, link_cfg); + + if (chan == 0 && (link_cfg & LINK_CFG) != DUAL_LINK) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 1)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, DUAL_LINK)); + SERDES_DBG_CHIP("%s: change to use dual link\n", __func__); + } else if (chan == 1 && (link_cfg & LINK_CFG) != LINKA) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 0)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, LINKA)); + SERDES_DBG_CHIP("%s: change to use linkA\n", __func__); + } else if (chan == 2 && (link_cfg & LINK_CFG) != LINKB) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 0) | + FIELD_PREP(LINK_EN_B, 1)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, LINKB)); + SERDES_DBG_CHIP("%s: change to use linkB\n", __func__); + } else if (chan == 3 && (link_cfg & LINK_CFG) != SPLITTER_MODE) { + ret = serdes_set_bits(serdes, 0x0004, + LINK_EN_B | LINK_EN_A, + FIELD_PREP(LINK_EN_A, 1) | + FIELD_PREP(LINK_EN_B, 1)); + ret = serdes_set_bits(serdes, 0x0010, + RESET_ONESHOT | AUTO_LINK | LINK_CFG, + FIELD_PREP(RESET_ONESHOT, 1) | + FIELD_PREP(AUTO_LINK, 0) | + FIELD_PREP(LINK_CFG, SPLITTER_MODE)); + SERDES_DBG_CHIP("%s: change to use split mode\n", __func__); + } + + for (i = 0; i < 20; i++) { + serdes_reg_read(serdes, 0x0013, &link_status); + if (link_status & LOCKED) + break; + mdelay(5); + } + + if (i > 9) + printf("%s: %s GMSL2 link lock timeout\n", __func__, + serdes->dev->name); + else + printf("%s: %s GMSL2 link locked\n", __func__, + serdes->dev->name); + + return ret; +} + +static int max96789_deselect(struct serdes *serdes, int chan) +{ + //serdes_set_bits(serdes, 0x0001, DIS_REM_CC, + // FIELD_PREP(DIS_REM_CC, 1)); + + return 0; +} + +static struct serdes_chip_split_ops max96789_split_ops = { + .select = max96789_select, + .deselect = max96789_deselect, +}; + +struct serdes_chip_data serdes_max96789_data = { + .name = "max96789", + .serdes_type = TYPE_SER, + .serdes_id = MAXIM_ID_MAX96789, + .connector_type = DRM_MODE_CONNECTOR_DSI, + .pinctrl_info = &max96789_pinctrl_info, + .bridge_ops = &max96789_bridge_ops, + .pinctrl_ops = &max96789_pinctrl_ops, + .gpio_ops = &max96789_gpio_ops, + .split_ops = &max96789_split_ops, +}; +EXPORT_SYMBOL_GPL(serdes_max96789_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.h b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.h new file mode 100644 index 0000000000..35b9ed9118 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/maxim/maxim-max96789.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * maxim-max96789.h -- register define for max96789 chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_MAXIM_MAX96789_H__ +#define __MFD_SERDES_MAXIM_MAX96789_H__ + +#include + +#define GPIO_A_REG(gpio) (0x02be + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x02bf + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x02c0 + ((gpio) * 3)) + +/* 0000h */ +#define DEV_ADDR GENMASK(7, 1) +#define CFG_BLOCK BIT(0) + +/* 0001h */ +#define IIC_2_EN BIT(7) +#define IIC_1_EN BIT(6) +#define DIS_REM_CC BIT(4) +#define TX_RATE GENMASK(3, 2) + +/* 0002h */ +#define VID_TX_EN_U BIT(7) +#define VID_TX_EN_Z BIT(6) +#define VID_TX_EN_Y BIT(5) +#define VID_TX_EN_X BIT(4) +#define AUD_TX_EN_Y BIT(3) +#define AUD_TX_EN_X BIT(2) + +/* 0003h */ +#define UART_2_EN BIT(5) +#define UART_1_EN BIT(4) + +/* 0004h */ +#define GMSL2_B BIT(7) +#define GMSL2_A BIT(6) +#define LINK_EN_B BIT(5) +#define LINK_EN_A BIT(4) +#define AUD_TX_SRC_Y BIT(1) +#define AUD_TX_SRC_X BIT(0) + +/* 0005h */ +#define LOCK_EN BIT(7) +#define ERRB_EN BIT(6) +#define PU_LF3 BIT(3) +#define PU_LF2 BIT(2) +#define PU_LF1 BIT(1) +#define PU_LF0 BIT(0) + +/* 0006h */ +#define RCLKEN BIT(5) + +/* 0010h */ +#define RESET_ALL BIT(7) +#define RESET_LINK BIT(6) +#define RESET_ONESHOT BIT(5) +#define AUTO_LINK BIT(4) +#define SLEEP BIT(3) +#define REG_ENABLE BIT(2) +#define LINK_CFG GENMASK(1, 0) + +/* 0013h */ +#define LINK_MODE GENMASK(5, 4) +#define LOCKED BIT(3) + +/* 0026h */ +#define LF_1 GENMASK(6, 4) +#define LF_0 GENMASK(2, 0) + +/* 0048h */ +#define REM_MS_EN BIT(5) +#define LOC_MS_EN BIT(4) + +/* 0053h */ +#define TX_SPLIT_MASK_B BIT(5) +#define TX_SPLIT_MASK_A BIT(4) +#define TX_STR_SEL GENMASK(1, 0) + +/* 0140h */ +#define AUD_RX_EN BIT(0) + +/* 0170h */ +#define SPI_EN BIT(0) + +/* 01e5h */ +#define PATGEN_MODE GENMASK(1, 0) + +/* 02beh */ +#define RES_CFG BIT(7) +#define TX_PRIO BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 02bfh */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 02c0h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + +/* 0311h */ +#define START_PORTBU BIT(7) +#define START_PORTBZ BIT(6) +#define START_PORTBY BIT(5) +#define START_PORTBX BIT(4) +#define START_PORTAU BIT(3) +#define START_PORTAZ BIT(2) +#define START_PORTAY BIT(1) +#define START_PORTAX BIT(0) + +/* 032ah */ +#define DV_LOCK BIT(7) +#define DV_SWP_AB BIT(6) +#define LINE_ALT BIT(5) +#define DV_CONV BIT(2) +#define DV_SPL BIT(1) +#define DV_EN BIT(0) + +/* 0330h */ +#define PHY_CONFIG GENMASK(2, 0) +#define MIPI_RX_RESET BIT(3) + +/* 0331h */ +#define NUM_LANES GENMASK(1, 0) + +/* 0385h */ +#define DPI_HSYNC_WIDTH_L GENMASK(7, 0) + +/* 0386h */ +#define DPI_VYSNC_WIDTH_L GENMASK(7, 0) + +/* 0387h */ +#define DPI_HSYNC_WIDTH_H GENMASK(3, 0) +#define DPI_VSYNC_WIDTH_H GENMASK(7, 4) + +/* 03a4h */ +#define DPI_DE_SKEW_SEL BIT(1) +#define DPI_DESKEW_EN BIT(0) + +/* 03a5h */ +#define DPI_VFP_L GENMASK(7, 0) + +/* 03a6h */ +#define DPI_VFP_H GENMASK(3, 0) +#define DPI_VBP_L GENMASK(7, 4) + +/* 03a7h */ +#define DPI_VBP_H GENMASK(7, 0) + +/* 03a8h */ +#define DPI_VACT_L GENMASK(7, 0) + +/* 03a9h */ +#define DPI_VACT_H GENMASK(3, 0) + +/* 03aah */ +#define DPI_HFP_L GENMASK(7, 0) + +/* 03abh */ +#define DPI_HFP_H GENMASK(3, 0) +#define DPI_HBP_L GENMASK(7, 4) + +/* 03ach */ +#define DPI_HBP_H GENMASK(7, 0) + +/* 03adh */ +#define DPI_HACT_L GENMASK(7, 0) + +/* 03aeh */ +#define DPI_HACT_H GENMASK(4, 0) + +/* 055dh */ +#define VS_DET BIT(5) +#define HS_DET BIT(4) + +enum link_mode { + DUAL_LINK, + LINKA, + LINKB, + SPLITTER_MODE, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/novo/Kconfig b/u-boot/drivers/video/drm/display-serdes/novo/Kconfig new file mode 100644 index 0000000000..20578a857a --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/novo/Kconfig @@ -0,0 +1,23 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# rohm serdes drivers configuration +# + +menuconfig SERDES_DISPLAY_CHIP_NOVO + tristate "novo expander device support" + default y + help + Enable this to be able to choose the drivers for controlling the + rohm serdes. + +if SERDES_DISPLAY_CHIP_NOVO +config SERDES_DISPLAY_CHIP_NOVO_NCA9539 + tristate "novo nca9539 expander" + default y + help + To support novo nca9539 expander. + +endif diff --git a/u-boot/drivers/video/drm/display-serdes/novo/Makefile b/u-boot/drivers/video/drm/display-serdes/novo/Makefile new file mode 100644 index 0000000000..a5defbfbdb --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/novo/Makefile @@ -0,0 +1,10 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# novo display serdes drivers configuration +# +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SERDES_DISPLAY_CHIP_NOVO) += novo-nca9539.o +endif diff --git a/u-boot/drivers/video/drm/display-serdes/novo/novo-nca9539.c b/u-boot/drivers/video/drm/display-serdes/novo/novo-nca9539.c new file mode 100644 index 0000000000..9dab598a81 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/novo/novo-nca9539.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * maxim-nca9539.c -- I2C register interface access for nca9539 chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" + +struct serdes_chip_data serdes_nca9539_data = { + .name = "nca9539", + .serdes_type = TYPE_OTHER, + .serdes_id = NOVO_ID_NCA9539, + .reg_val_type = REG_8BIT_VAL_8IT, +}; +EXPORT_SYMBOL_GPL(serdes_nca9539_data); diff --git a/u-boot/drivers/video/drm/display-serdes/rockchip/Kconfig b/u-boot/drivers/video/drm/display-serdes/rockchip/Kconfig new file mode 100644 index 0000000000..65c8961d7b --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rockchip/Kconfig @@ -0,0 +1,28 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# rockchip display serdes drivers configuration +# + +menuconfig SERDES_DISPLAY_CHIP_ROCKCHIP + tristate "rockchip serdes device support" + default y + help + Enable this to be able to choose the drivers for controlling the + rockchip serdes. + +if SERDES_DISPLAY_CHIP_ROCKCHIP +config SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111 + tristate "rockchip rkx111 serdes" + default y + help + To support rockchip rkx111 display serdes. + +config SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121 + tristate "rockchip rkx121 serdes" + default y + help + To support rockchip rkx121 display serdes. +endif diff --git a/u-boot/drivers/video/drm/display-serdes/rockchip/Makefile b/u-boot/drivers/video/drm/display-serdes/rockchip/Makefile new file mode 100644 index 0000000000..56b2741ac5 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rockchip/Makefile @@ -0,0 +1,11 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# rockchip display serdes drivers configuration +# +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) += rockchip-rkx111.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121) += rockchip-rkx121.o +endif diff --git a/u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx111.c b/u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx111.c new file mode 100644 index 0000000000..1e70041422 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx111.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * rockchip-rkx111.c -- I2C register interface access for rkx111 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" + +int rkx111_bridge_init(struct serdes *serdes) +{ + return 0; +} + +int rkx111_bridge_enable(struct serdes *serdes) +{ + return 0; +} + +int rkx111_bridge_disable(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_bridge_ops rkx111_bridge_ops = { + .init = rkx111_bridge_init, + .enable = rkx111_bridge_enable, + .disable = rkx111_bridge_disable, +}; + +struct serdes_chip_data serdes_rkx111_data = { + .name = "rkx111", + .serdes_type = TYPE_SER, + .serdes_id = ROCKCHIP_ID_RKX111, + .bridge_ops = &rkx111_bridge_ops, +}; +EXPORT_SYMBOL_GPL(serdes_rkx111_data); diff --git a/u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx121.c b/u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx121.c new file mode 100644 index 0000000000..9682a600f9 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rockchip/rockchip-rkx121.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * rockchip-rkx121.c -- I2C register interface access for rkx121 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" + +int rkx121_bridge_init(struct serdes *serdes) +{ + return 0; +} + +int rkx121_bridge_enable(struct serdes *serdes) +{ + return 0; +} + +int rkx121_bridge_disable(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_panel_ops rkx121_panel_ops = { + .init = rkx121_bridge_init, + .enable = rkx121_bridge_enable, + .disable = rkx121_bridge_disable, +}; + +struct serdes_chip_data serdes_rkx121_data = { + .name = "rkx121", + .serdes_type = TYPE_DES, + .serdes_id = ROCKCHIP_ID_RKX121, + .panel_ops = &rkx121_panel_ops, +}; +EXPORT_SYMBOL_GPL(serdes_rkx121_data); diff --git a/u-boot/drivers/video/drm/display-serdes/rohm/Kconfig b/u-boot/drivers/video/drm/display-serdes/rohm/Kconfig new file mode 100644 index 0000000000..23eec7a21c --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rohm/Kconfig @@ -0,0 +1,28 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# rohm serdes drivers configuration +# + +menuconfig SERDES_DISPLAY_CHIP_ROHM + tristate "rohm serdes device support" + default y + help + Enable this to be able to choose the drivers for controlling the + rohm serdes. + +if SERDES_DISPLAY_CHIP_ROHM +config SERDES_DISPLAY_CHIP_ROHM_BU18TL82 + tristate "rohm bu18tl82 serdes" + default y + help + To support rohm bu18tl82 display serdes. + +config SERDES_DISPLAY_CHIP_ROHM_BU18RL82 + tristate "rohm bu18rl82 serdes" + default y + help + To support rohm bu18rl82 display serdes. +endif diff --git a/u-boot/drivers/video/drm/display-serdes/rohm/Makefile b/u-boot/drivers/video/drm/display-serdes/rohm/Makefile new file mode 100644 index 0000000000..54c459d2ed --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rohm/Makefile @@ -0,0 +1,11 @@ +# +#(C) Copyright 2023-2025 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0 +# +# rohm display serdes drivers configuration +# +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) += rohm-bu18tl82.o +obj-$(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) += rohm-bu18rl82.o +endif diff --git a/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.c b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.c new file mode 100644 index 0000000000..f7bf500980 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.c @@ -0,0 +1,458 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * rohm-bu18rl82.c -- I2C register interface access for bu18rl82 serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" +#include "rohm-bu18rl82.h" + +static int BU18RL82_GPIO0_pins[] = {0}; +static int BU18RL82_GPIO1_pins[] = {1}; +static int BU18RL82_GPIO2_pins[] = {2}; +static int BU18RL82_GPIO3_pins[] = {3}; +static int BU18RL82_GPIO4_pins[] = {4}; +static int BU18RL82_GPIO5_pins[] = {5}; +static int BU18RL82_GPIO6_pins[] = {6}; +static int BU18RL82_GPIO7_pins[] = {7}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +struct serdes_function_data { + u8 gpio_rx_en:1; + u16 gpio_id; + u16 mdelay; +}; + +static const char *serdes_gpio_groups[] = { + "BU18RL82_GPIO0", "BU18RL82_GPIO1", "BU18RL82_GPIO2", "BU18RL82_GPIO3", + "BU18RL82_GPIO4", "BU18RL82_GPIO5", "BU18RL82_GPIO6", "BU18RL82_GPIO7", +}; + +/*des -> ser -> soc*/ +#define FUNCTION_DESC_GPIO_INPUT(id) \ +{ \ + .name = "DES_TO_SER_GPIO"#id, \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 1, .gpio_id = id + 2 } \ + }, \ +} \ + +/*soc -> ser -> des*/ +#define FUNCTION_DESC_GPIO_OUTPUT(id) \ +{ \ + .name = "SER_GPIO"#id"_TO_DES", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 0, .gpio_id = id + 2 } \ + }, \ +} \ + +#define FUNCTION_DES_DELAY_MS(ms) \ +{ \ + .name = "DELAY_"#ms"MS", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .mdelay = ms, } \ + }, \ +} \ + +/*des -> device*/ +#define FUNCTION_DESC_GPIO_OUTPUT_HIGH() \ +{ \ + .name = "DES_GPIO_OUTPUT_HIGH", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 0, .gpio_id = 1 } \ + }, \ +} \ + +#define FUNCTION_DESC_GPIO_OUTPUT_LOW() \ +{ \ + .name = "DES_GPIO_OUTPUT_LOW", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 0, .gpio_id = 0 } \ + }, \ +} \ + +static struct pinctrl_pin_desc bu18rl82_pins_desc[] = { + PINCTRL_PIN(ROHM_BU18RL82_GPIO0, "BU18RL82_GPIO0"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO1, "BU18RL82_GPIO1"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO2, "BU18RL82_GPIO2"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO3, "BU18RL82_GPIO3"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO4, "BU18RL82_GPIO4"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO5, "BU18RL82_GPIO5"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO6, "BU18RL82_GPIO6"), + PINCTRL_PIN(ROHM_BU18RL82_GPIO7, "BU18RL82_GPIO7"), +}; + +static struct group_desc bu18rl82_groups_desc[] = { + GROUP_DESC(BU18RL82_GPIO0), + GROUP_DESC(BU18RL82_GPIO1), + GROUP_DESC(BU18RL82_GPIO2), + GROUP_DESC(BU18RL82_GPIO3), + GROUP_DESC(BU18RL82_GPIO4), + GROUP_DESC(BU18RL82_GPIO5), + GROUP_DESC(BU18RL82_GPIO6), + GROUP_DESC(BU18RL82_GPIO7), +}; + +static struct function_desc bu18rl82_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT(0), + FUNCTION_DESC_GPIO_INPUT(1), + FUNCTION_DESC_GPIO_INPUT(2), + FUNCTION_DESC_GPIO_INPUT(3), + FUNCTION_DESC_GPIO_INPUT(4), + FUNCTION_DESC_GPIO_INPUT(5), + FUNCTION_DESC_GPIO_INPUT(6), + FUNCTION_DESC_GPIO_INPUT(7), + FUNCTION_DESC_GPIO_INPUT(8), + FUNCTION_DESC_GPIO_INPUT(9), + FUNCTION_DESC_GPIO_INPUT(10), + FUNCTION_DESC_GPIO_INPUT(11), + FUNCTION_DESC_GPIO_INPUT(12), + FUNCTION_DESC_GPIO_INPUT(13), + FUNCTION_DESC_GPIO_INPUT(14), + FUNCTION_DESC_GPIO_INPUT(15), + + FUNCTION_DESC_GPIO_OUTPUT(0), + FUNCTION_DESC_GPIO_OUTPUT(1), + FUNCTION_DESC_GPIO_OUTPUT(2), + FUNCTION_DESC_GPIO_OUTPUT(3), + FUNCTION_DESC_GPIO_OUTPUT(4), + FUNCTION_DESC_GPIO_OUTPUT(5), + FUNCTION_DESC_GPIO_OUTPUT(6), + FUNCTION_DESC_GPIO_OUTPUT(7), + FUNCTION_DESC_GPIO_OUTPUT(8), + FUNCTION_DESC_GPIO_OUTPUT(9), + FUNCTION_DESC_GPIO_OUTPUT(10), + FUNCTION_DESC_GPIO_OUTPUT(11), + FUNCTION_DESC_GPIO_OUTPUT(12), + FUNCTION_DESC_GPIO_OUTPUT(13), + FUNCTION_DESC_GPIO_OUTPUT(14), + FUNCTION_DESC_GPIO_OUTPUT(15), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(), + FUNCTION_DESC_GPIO_OUTPUT_LOW(), + + FUNCTION_DES_DELAY_MS(10), + FUNCTION_DES_DELAY_MS(50), + FUNCTION_DES_DELAY_MS(100), + FUNCTION_DES_DELAY_MS(200), + FUNCTION_DES_DELAY_MS(500), +}; + +static struct serdes_chip_pinctrl_info bu18rl82_pinctrl_info = { + .pins = bu18rl82_pins_desc, + .num_pins = ARRAY_SIZE(bu18rl82_pins_desc), + .groups = bu18rl82_groups_desc, + .num_groups = ARRAY_SIZE(bu18rl82_groups_desc), + .functions = bu18rl82_functions_desc, + .num_functions = ARRAY_SIZE(bu18rl82_functions_desc), +}; + +void bu18rl82_bridge_swrst(struct serdes *serdes) +{ + int ret; + + ret = serdes_reg_write(serdes, BU18RL82_REG_RESET, + BIT(0) | BIT(1) | BIT(7)); + if (ret < 0) + printf("%s: failed to reset bu18rl82 0x11 ret=%d\n", + __func__, ret); + + mdelay(20); + + SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", + __func__, serdes->dev->name, ret); +} + +void bu18rl82_enable_hwint(struct serdes *serdes, int enable) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(bu18rl82_reg_ien); i++) { + if (enable) { + ret = serdes_reg_write(serdes, bu18rl82_reg_ien[i].reg, + bu18rl82_reg_ien[i].ien); + if (ret) + printf("reg 0x%04x write error\n", + bu18rl82_reg_ien[i].reg); + } else { + ret = serdes_reg_write(serdes, bu18rl82_reg_ien[i].reg, 0); + if (ret) + printf("reg 0x%04x write error\n", + bu18rl82_reg_ien[i].reg); + } + } + + SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", + __func__, + serdes->dev->name, enable); +} + +int bu18rl82_bridge_init(struct serdes *serdes) +{ + if (!dm_gpio_is_valid(&serdes->reset_gpio)) { + bu18rl82_bridge_swrst(serdes); + SERDES_DBG_CHIP("%s: serdes %s\n", __func__, + serdes->dev->name); + } + + return 0; +} + +int bu18rl82_bridge_enable(struct serdes *serdes) +{ + int ret = 0; + + /* 1:enable 0:dsiable*/ + bu18rl82_enable_hwint(serdes, 0); + + SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", __func__, + serdes->dev->name, ret); + return ret; +} + +int bu18rl82_bridge_disable(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_bridge_ops bu18rl82_bridge_ops = { + .init = bu18rl82_bridge_init, + .enable = bu18rl82_bridge_enable, + .disable = bu18rl82_bridge_disable, +}; + +static int bu18rl82_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + switch (param) { + case PIN_CONFIG_DRIVE_STRENGTH: + serdes_set_bits(serdes, bu18rl82_gpio_sw[pin_selector].reg, + bu18rl82_gpio_sw[pin_selector].mask, + FIELD_PREP(BIT(2) | BIT(1), argument)); + SERDES_DBG_CHIP("%s: serdes %s pin=%d drive arg=0x%x\n", + __func__, + serdes->dev->name, pin_selector, argument); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + serdes_set_bits(serdes, bu18rl82_gpio_pden[pin_selector].reg, + bu18rl82_gpio_pden[pin_selector].mask, + FIELD_PREP(BIT(4), argument)); + SERDES_DBG_CHIP("%s: serdes %s pin=%d pull-down arg=0x%x\n", + __func__, + serdes->dev->name, pin_selector, argument); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, bu18rl82_gpio_oen[pin_selector].reg, + bu18rl82_gpio_oen[pin_selector].mask, + FIELD_PREP(BIT(3), argument)); + SERDES_DBG_CHIP("%s: serdes %s pin=%d output arg=0x%x\n", + __func__, + serdes->dev->name, pin_selector, argument); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int bu18rl82_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + u16 ms; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + ms = fdata->mdelay; + + offset = pin->number; + if (offset > 7) + dev_err(serdes->dev, "%s offset=%d > 7\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s id=0x%x off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_id, offset); + if (!ms) { + serdes_set_bits(serdes, bu18rl82_gpio_oen[offset].reg, + bu18rl82_gpio_oen[offset].mask, + FIELD_PREP(BIT(3), fdata->gpio_rx_en)); + serdes_set_bits(serdes, bu18rl82_gpio_id_low[offset].reg, + bu18rl82_gpio_id_low[offset].mask, + FIELD_PREP(GENMASK(7, 0), + (fdata->gpio_id & 0xff))); + serdes_set_bits(serdes, bu18rl82_gpio_id_high[offset].reg, + bu18rl82_gpio_id_high[offset].mask, + FIELD_PREP(GENMASK(2, 0), + ((fdata->gpio_id >> 8) & 0x7))); + serdes_set_bits(serdes, bu18rl82_gpio_pden[offset].reg, + bu18rl82_gpio_pden[offset].mask, + FIELD_PREP(BIT(4), 0)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %dms\n", __func__, ms); + } + } + + return 0; +} + +static int bu18rl82_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p, num=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 7) + dev_err(serdes->dev, "%s offset=%d > 7\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s id=0x%x, offset=%d\n", + __func__, + serdes->dev->name, fdata->gpio_id, offset); + serdes_set_bits(serdes, bu18rl82_gpio_oen[offset].reg, + bu18rl82_gpio_oen[offset].mask, + FIELD_PREP(BIT(3), fdata->gpio_rx_en)); + serdes_set_bits(serdes, bu18rl82_gpio_id_low[offset].reg, + bu18rl82_gpio_id_low[offset].mask, + FIELD_PREP(GENMASK(7, 0), + (fdata->gpio_id & 0xff))); + serdes_set_bits(serdes, bu18rl82_gpio_id_high[offset].reg, + bu18rl82_gpio_id_high[offset].mask, + FIELD_PREP(GENMASK(2, 0), + ((fdata->gpio_id >> 8) & 0x7))); + serdes_set_bits(serdes, bu18rl82_gpio_pden[offset].reg, + bu18rl82_gpio_pden[offset].mask, + FIELD_PREP(BIT(4), 0)); + } + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops bu18rl82_pinctrl_ops = { + .pinconf_set = bu18rl82_pinctrl_config_set, + .pinmux_set = bu18rl82_pinctrl_set_pin_mux, + .pinmux_group_set = bu18rl82_pinctrl_set_grp_mux, +}; + +static int bu18rl82_gpio_direction_input(struct serdes *serdes, + int gpio) +{ + return 0; +} + +static int bu18rl82_gpio_direction_output(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int bu18rl82_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +int bu18rl82_gpio_set_level(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int bu18rl82_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int bu18rl82_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops bu18rl82_gpio_ops = { + .direction_input = bu18rl82_gpio_direction_input, + .direction_output = bu18rl82_gpio_direction_output, + .get_level = bu18rl82_gpio_get_level, + .set_level = bu18rl82_gpio_set_level, + .set_config = bu18rl82_gpio_set_config, + .to_irq = bu18rl82_gpio_to_irq, +}; + +struct serdes_chip_data serdes_bu18rl82_data = { + .name = "bu18rl82", + .serdes_type = TYPE_DES, + .serdes_id = ROHM_ID_BU18RL82, + .pinctrl_info = &bu18rl82_pinctrl_info, + .pinctrl_ops = &bu18rl82_pinctrl_ops, + .gpio_ops = &bu18rl82_gpio_ops, + .bridge_ops = &bu18rl82_bridge_ops, +}; +EXPORT_SYMBOL_GPL(serdes_bu18rl82_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.h b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.h new file mode 100644 index 0000000000..77a8d045e8 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18rl82.h @@ -0,0 +1,395 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * include/linux/mfd/serdes/gpio.h -- GPIO for different serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_ROHM_BU18RL82_H__ +#define __MFD_SERDES_ROHM_BU18RL82_H__ +#define BU18RL82_REG_RESET 0X000E + +#define BU18RL82_BLOCK_EN_CLLRX0 0x0011 //h [0] 1’b1 +#define BU18RL82_BLOCK_EN_LVDSTX0 0x0011 //h [1] 1’b0 +#define BU18RL82_BLOCK_EN_VPLL0 0x0011 //h [3] 1’b0 +#define BU18RL82_BLOCK_EN_SSCG0 0x0011 //h [4] 1’b0 +#define BU18RL82_BLOCK_EN_CLLRX1 0x0012 //h [0] 1’b1 +#define BU18RL82_BLOCK_EN_LVDSTX1 0x0012 //h [1] 1’b0 +#define BU18RL82_BLOCK_EN_VPLL1 0x0012 //h [3] 1’b0 +#define BU18RL82_BLOCK_EN_SSCG1 0x0012 //h [4] 1’b0 +#define BU18RL82_BLOCK_EN_CLLTX 0x0013 //h [0] 1’b0 +#define BU18RL82_BLOCK_EN_FSAFETY 0x0013 //h [1] 1’b0 + +#define BU18RL82_IO_SW_GPIO0 0x0057 //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO0 0x0057 //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO0 0x0057 //h [4] 1’b1 +#define BU18RL82_IO_SW_GPIO1 0x005A //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO1 0x005A //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO1 0x005A //h [4] 1’b1 +#define BU18RL82_IO_SW_GPIO2 0x005D //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO2 0x005D //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO2 0x005D //h [4] 1’b1 +#define BU18RL82_IO_SW_GPIO3 0x0060 //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO3 0x0060 //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO3 0x0060 //h [4] 1’b1 +#define BU18RL82_IO_SW_GPIO4 0x0063 //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO4 0x0063 //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO4 0x0063 //h [4] 1’b1 +#define BU18RL82_IO_SW_GPIO5 0x0066 //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO5 0x0066 //h [2:1] 2’b00 +#define BU18RL82_IO_PDEN_GPIO5 0x0066 //h [3] 1’b1 +#define BU18RL82_IO_SW_GPIO6 0x0069 //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO6 0x0069 //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO6 0x0069 //h [4] 1’b1 +#define BU18RL82_IO_SW_GPIO7 0x006C //h [2:1] 2’b00 +#define BU18RL82_IO_OEN_GPIO7 0x006C //h [3] 1’b1 +#define BU18RL82_IO_PDEN_GPIO7 0x006C //h [4] 1’b1 + +/* + * gpio register for define connection with des gpiox, + * 11bits such as 0x002c:002b=[b2..b0 b7...b0] + * default value: + * ser gpio0-->des gpio0 + * ser gpio1-->des gpio1 + * ser gpio2-->des gpio2 + * ser gpio3-->des gpio3 + */ +#define BU18RL82_GPIO_SEL0_HIGH 0x0059 //h [2:0], +#define BU18RL82_GPIO_SEL0_LOW 0x0058 //h [7:0]} 11’h002 +#define BU18RL82_GPIO_SEL1_HIGH 0x005C //h [2:0], +#define BU18RL82_GPIO_SEL1_LOW 0x005B //h [7:0]} 11’h003 +#define BU18RL82_GPIO_SEL2_HIGH 0x005F //h [2:0], +#define BU18RL82_GPIO_SEL2_LOW 0x005E //h [7:0]} 11’h012 +#define BU18RL82_GPIO_SEL3_HIGH 0x0062 //h [2:0], +#define BU18RL82_GPIO_SEL3_LOW 0x0061 //h [7:0]} 11’h013 +#define BU18RL82_GPIO_SEL4_HIGH 0x0065 //h [2:0], +#define BU18RL82_GPIO_SEL4_LOW 0x0064 //h [7:0]} 11’h006 +#define BU18RL82_GPIO_SEL5_HIGH 0x0068 //h [2:0], +#define BU18RL82_GPIO_SEL5_LOW 0x0067 //h [7:0]} 11’h007 +#define BU18RL82_GPIO_SEL6_HIGH 0x006B //h [2:0], +#define BU18RL82_GPIO_SEL6_LOW 0x006A //h [7:0]} 11’h008 +#define BU18RL82_GPIO_SEL7_HIGH 0x006E //h [2:0], +#define BU18RL82_GPIO_SEL7_LOW 0x006D //h [7:0]} 11’h009 + +/*gpio register for define bu18rl82 gpio pin, and gpio0 to gpio0 default*/ +#define BU18RL82_BCCTX0__SEL_GPI0 0x042B //h [5:0] 6’h02 +#define BU18RL82_BCCTX0__SEL_GPI1 0x042C //h [5:0] 6’h03 +#define BU18RL82_BCCTX0__SEL_GPI2 0x042D //h [5:0] 6’h04 +#define BU18RL82_BCCTX0__SEL_GPI3 0x042E //h [5:0] 6’h05 +#define BU18RL82_BCCTX0__SEL_GPI4 0x042F //h [5:0] 6’h06 +#define BU18RL82_BCCTX0__SEL_GPI5 0x0430 //h [5:0] 6’h07 +#define BU18RL82_BCCTX0__SEL_GPI6 0x0431 //h [5:0] 6’h08 +#define BU18RL82_BCCTX0__SEL_GPI7 0x0432 //h [5:0] 6’h09 +#define BU18RL82_BCCTX1__SEL_GPI0 0x052B //h [5:0] 6’h02 +#define BU18RL82_BCCTX1__SEL_GPI1 0x052C //h [5:0] 6’h03 +#define BU18RL82_BCCTX1__SEL_GPI2 0x052D //h [5:0] 6’h04 +#define BU18RL82_BCCTX1__SEL_GPI3 0x052E //h [5:0] 6’h05 +#define BU18RL82_BCCTX1__SEL_GPI4 0x052F //h [5:0] 6’h06 +#define BU18RL82_BCCTX1__SEL_GPI5 0x0530 //h [5:0] 6’h07 +#define BU18RL82_BCCTX1__SEL_GPI6 0x0531 //h [5:0] 6’h08 +#define BU18RL82_BCCTX1__SEL_GPI7 0x0532 //h [5:0] 6’h09 + +#define BU18RL82_IEN_CLLRX0_LINK_UNLOCK 0x0109 //h [1] 1’b0 +#define BU18RL82_IEN_CLLRX0_BIT_ERR 0x0109 //h [3] 1’b0 +#define BU18RL82_IEN_CLLRX0_ERR_CNT_OVF 0x0109 //h [4] 1’b0 +#define BU18RL82_IEN_CLLRX1_LINK_UNLOCK 0x010B //h [1] 1’b0 +#define BU18RL82_IEN_CLLRX1_BIT_ERR 0x010B //h [3] 1’b0 +#define BU18RL82_IEN_CLLRX1_ERR_CNT_OVF 0x010B //h [4] 1’b0 +#define BU18RL82_IEN_FCCRX0_CRCERR 0x010D //h [0] 1’b0 +#define BU18RL82_IEN_FCCRX1_CRCERR 0x010E //h [0] 1’b0 +#define BU18RL82_IEN_BCCDES0_ERR_CRC 0x010F //h [3] 1’b0 +#define BU18RL82_IEN_CLLRX0_CRCERR_R 0x0110 //h [0] 1’b0 +#define BU18RL82_IEN_CLLRX0_CRCERR_G 0x0110 //h [1] 1’b0 +#define BU18RL82_IEN_CLLRX0_CRCERR_B 0x0110 //h [2] 1’b0 +#define BU18RL82_IEN_CLLRX1_CRCERR_R 0x0111 //h [0] 1’b0 +#define BU18RL82_IEN_CLLRX1_CRCERR_G 0x0111 //h [1] 1’b0 +#define BU18RL82_IEN_CLLRX1_CRCERR_B 0x0111 //h [2] 1’b0 +#define BU18RL82_IEN_FS_IMG_STATUS0 0x0112 //h [0] 1’b0 +#define BU18RL82_IEN_FS_IMG_STATUS1 0x0112 //h [1] 1’b0 +#define BU18RL82_IEN_FS_IMG_STATUS2 0x0112 //h [2] 1’b0 +#define BU18RL82_IEN_FS_IMG_STATUS3 0x0112 //h [3] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION0 0x0113 //h [0] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION1 0x0113 //h [1] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION2 0x0113 //h [2] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION3 0x0113 //h [3] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION4 0x0113 //h [4] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION5 0x0113 //h [5] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION6 0x0113 //h [6] 1’b0 +#define BU18RL82_IEN_FS_IMG_ERR_REGION7 0x0113 //h [7] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO0 0x0114 //h [0] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO1 0x0114 //h [1] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO2 0x0114 //h [2] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO3 0x0114 //h [3] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO4 0x0114 //h [4] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO5 0x0114 //h [5] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO6 0x0114 //h [6] 1’b0 +#define BU18RL82_IEN_IO_STUCK_GPIO7 0x0114 //h [7] 1’b0 +#define BU18RL82_IEN_IO_STUCK_IRQ 0x0115 //h [1] 1’b0 +#define BU18RL82_IEN_IDS_UNSTABLE 0x0115 //h [7] 1’b0 +#define BU18RL82_IEN_I2C_A_TIMEOUT 0x0116 //h [0] 1’b0 +#define BU18RL82_IEN_I2C_A_XMIT_ERR 0x0116 //h [1] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE0 0x0117 //h [0] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE1 0x0117 //h [1] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE2 0x0117 //h [2] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE3 0x0117 //h [3] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE4 0x0117 //h [4] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE5 0x0117 //h [5] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE6 0x0117 //h [6] 1’b0 +#define BU18RL82_IEN_REGCRC_ERR_PAGE7 0x0117 //h [7] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLKIN_STOP 0x0118 //h [0] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLKIN_UNLOCK 0x0118 //h [1] 1’b0 +#define BU18RL82_IEN_CLKDETECT_OSC_STOP 0x0118 //h [4] 1’b0 +#define BU18RL82_IEN_CLKDETECT_OSC_UNLOCK 0x0118 //h [5] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLRX0_PCLK_STOP 0x0119 //h [0] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLRX0_PCLK_UNLOCK 0x0119 //h [1] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX0_CLK_STOP 0x0119 //h [4] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX0_CLK_UNLOCK 0x0119 //h [5] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLRX1_PCLK_STOP 0x011A //h [0] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLRX1_PCLK_UNLOCK 0x011A //h [1] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX1_CLK_STOP 0x011A //h [4] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX1_CLK_UNLOCK 0x011A //h [5] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLTX0_SCLK_STOP 0x011B //h [0] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLTX0_SCLK_UNLOCK 0x011B //h [1] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLTX0_PLLREF_STOP 0x011B //h [4] 1’b0 +#define BU18RL82_IEN_CLKDETECT_CLLTX0_PLLREF_UNLOCK 0x011B //h [5] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX0_PLLREF_STOP 0x011C //h [0] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX0_PLLREF_UNLOCK0x011C //h [1] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX1_PLLREF_STOP 0x011C //h [4] 1’b0 +#define BU18RL82_IEN_CLKDETECT_LVDSTX1_PLLREF_UNLOCK 0x011C //h [5] 1’b0 + +#define BU18RL82_ISR_CLEAR_ALL 0x0105 //h [0] 1’b0 +#define BU18RL82_ISR_CLLRX0_LINK_UNLOCK 0x0129 //h [1] 1’b0 +#define BU18RL82_ISR_CLLRX0_BIT_ERR 0x0129 //h [3] 1’b0 +#define BU18RL82_ISR_CLLRX0_ERR_CNT_OVF 0x0129 //h [4] 1’b0 +#define BU18RL82_ISR_CLLRX1_ERR_CNT_OVF 0x012B //h [4] 1’b0 +#define BU18RL82_ISR_CLLRX1_LINK_UNLOCK 0x012B //h [1] 1’b0 +#define BU18RL82_ISR_CLLRX1_BIT_ERR 0x012B //h [3] 1’b0 +#define BU18RL82_ISR_FCCRX0_CRCERR 0x012D //h [0] 1’b0 +#define BU18RL82_ISR_FCCRX1_CRCERR 0x012E //h [0] 1’b0 +#define BU18RL82_ISR_BCCDES0_ERR_CRC 0x012F //h [3] 1’b0 +#define BU18RL82_ISR_CLLRX0_CRCERR_R 0x0130 //h [0] 1’b0 +#define BU18RL82_ISR_CLLRX0_CRCERR_G 0x0130 //h [1] 1’b0 +#define BU18RL82_ISR_CLLRX0_CRCERR_B 0x0130 //h [2] 1’b0 +#define BU18RL82_ISR_CLLRX1_CRCERR_R 0x0131 //h [0] 1’b0 +#define BU18RL82_ISR_CLLRX1_CRCERR_G 0x0131 //h [1] 1’b0 +#define BU18RL82_ISR_CLLRX1_CRCERR_B 0x0131 //h [2] 1’b0 +#define BU18RL82_ISR_FS_IMG_STATUS0 0x0132 //h [0] 1’b0 +#define BU18RL82_ISR_FS_IMG_STATUS1 0x0132 //h [1] 1’b0 +#define BU18RL82_ISR_FS_IMG_STATUS2 0x0132 //h [2] 1’b0 +#define BU18RL82_ISR_FS_IMG_STATUS3 0x0132 //h [3] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION0 0x0133 //h [0] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION1 0x0133 //h [1] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION2 0x0133 //h [2] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION3 0x0133 //h [3] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION4 0x0133 //h [4] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION5 0x0133 //h [5] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION6 0x0133 //h [6] 1’b0 +#define BU18RL82_ISR_FS_IMG_ERR_REGION7 0x0133 //h [7] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO0 0x0134 //h [0] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO1 0x0134 //h [1] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO2 0x0134 //h [2] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO3 0x0134 //h [3] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO4 0x0134 //h [4] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO5 0x0134 //h [5] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO6 0x0134 //h [6] 1’b0 +#define BU18RL82_ISR_IO_STUCK_GPIO7 0x0134 //h [7] 1’b0 +#define BU18RL82_ISR_IO_STUCK_IRQ 0x0135 //h [1] 1’b0 +#define BU18RL82_ISR_IDS_UNSTABLE 0x0135 //h [7] 1’b0 +#define BU18RL82_ISR_I2C_A_TIMEOUT 0x0136 //h [0] 1’b0 +#define BU18RL82_ISR_I2C_A_XMIT_ERR 0x0136 //h [1] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE0 0x0137 //h [0] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE1 0x0137 //h [1] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE2 0x0137 //h [2] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE3 0x0137 //h [3] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE4 0x0137 //h [4] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE5 0x0137 //h [5] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE6 0x0137 //h [6] 1’b0 +#define BU18RL82_ISR_REGCRC_ERR_PAGE7 0x0137 //h [7] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLKIN_STOP 0x0138 //h [0] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLKIN_UNLOCK 0x0138 //h [1] 1’b0 +#define BU18RL82_ISR_CLKDETECT_OSC_STOP 0x0138 //h [4] 1’b0 +#define BU18RL82_ISR_CLKDETECT_OSC_UNLOCK 0x0138 //h [5] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLRX0_PCLK_STOP 0x0139 //h [0] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLRX0_PCLK_UNLOCK 0x0139 //h [1] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX0_CLK_STOP 0x0139 //h [4] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX0_CLK_UNLOCK 0x0139 //h [5] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLRX1_PCLK_STOP 0x013A //h [0] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLRX1_PCLK_UNLOCK 0x013A //h [1] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX1_CLK_STOP 0x013A //h [4] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX1_CLK_UNLOCK 0x013A //h [5] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLTX0_SCLK_STOP 0x013B //h [0] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLTX0_SCLK_UNLOCK 0x013B //h [1] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLTX0_PLLREF_STOP 0x013B //h [4] 1’b0 +#define BU18RL82_ISR_CLKDETECT_CLLTX0_PLLREF_UNLOCK 0x013B //h [5] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX0_PLLREF_STOP 0x013C //h [0] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX0_PLLREF_UNLOCK0x013C //h [1] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX1_PLLREF_STOP 0x013C //h [4] 1’b0 +#define BU18RL82_ISR_CLKDETECT_LVDSTX1_PLLREF_UNLOCK 0x013C //h [5] 1’b0 + +struct bu18rl82_gpio_sw_reg { + unsigned int reg; + unsigned int mask; //2/4/6/8ma +}; + +struct bu18rl82_gpio_oen_reg { + unsigned int reg; + unsigned int mask; //0:output 1:input +}; + +struct bu18rl82_gpio_pden_reg { + unsigned int reg; + unsigned int mask; //0:no pulldown 1:connect pulldown +}; + +struct bu18rl82_gpio_id_low_reg { + unsigned int reg; + unsigned int mask; //b2b1b0 +}; + +struct bu18rl82_gpio_id_high_reg { + unsigned int reg; + unsigned int mask; //b11b10b9b8b7b6b5b4b3 +}; + +static const struct bu18rl82_gpio_sw_reg bu18rl82_gpio_sw[8] = { + {BU18RL82_IO_SW_GPIO0, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO1, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO2, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO3, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO4, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO5, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO6, BIT(2) | BIT(1)}, + {BU18RL82_IO_SW_GPIO7, BIT(2) | BIT(1)}, +}; + +static const struct bu18rl82_gpio_oen_reg bu18rl82_gpio_oen[8] = { + {BU18RL82_IO_OEN_GPIO0, BIT(3)}, + {BU18RL82_IO_OEN_GPIO1, BIT(3)}, + {BU18RL82_IO_OEN_GPIO2, BIT(3)}, + {BU18RL82_IO_OEN_GPIO3, BIT(3)}, + {BU18RL82_IO_OEN_GPIO4, BIT(3)}, + {BU18RL82_IO_OEN_GPIO5, BIT(3)}, + {BU18RL82_IO_OEN_GPIO6, BIT(3)}, + {BU18RL82_IO_OEN_GPIO7, BIT(3)}, +}; + +static const struct bu18rl82_gpio_pden_reg bu18rl82_gpio_pden[8] = { + {BU18RL82_IO_PDEN_GPIO0, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO1, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO2, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO3, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO4, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO5, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO6, BIT(4)}, + {BU18RL82_IO_PDEN_GPIO7, BIT(4)}, +}; + +static const struct bu18rl82_gpio_id_low_reg bu18rl82_gpio_id_low[8] = { + {BU18RL82_GPIO_SEL0_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL1_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL2_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL3_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL4_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL5_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL6_LOW, GENMASK(7, 0)}, + {BU18RL82_GPIO_SEL7_LOW, GENMASK(7, 0)}, +}; + +static const struct bu18rl82_gpio_id_high_reg bu18rl82_gpio_id_high[8] = { + {BU18RL82_GPIO_SEL0_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL1_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL2_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL3_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL4_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL5_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL6_HIGH, GENMASK(2, 0)}, + {BU18RL82_GPIO_SEL7_HIGH, GENMASK(2, 0)}, +}; + +struct bu18rl82_ien_reg { + unsigned int reg; + unsigned int ien; +}; + +struct bu18rl82_isr_reg { + unsigned int reg; + unsigned int isr; +}; + +struct bu18rl82_gpio_reg { + unsigned int reg; + unsigned int val; +}; + +static const struct bu18rl82_ien_reg bu18rl82_reg_ien[18] = { + {BU18RL82_IEN_CLLRX0_LINK_UNLOCK, + BIT(1) | BIT(3) | BIT(4)}, + {BU18RL82_IEN_CLLRX1_LINK_UNLOCK, + BIT(1) | BIT(3) | BIT(4)}, + {BU18RL82_IEN_FCCRX0_CRCERR, BIT(0)}, + {BU18RL82_IEN_FCCRX1_CRCERR, BIT(0)}, + + {BU18RL82_IEN_BCCDES0_ERR_CRC, BIT(3)}, + {BU18RL82_IEN_CLLRX0_CRCERR_R, + BIT(0) | BIT(1) | BIT(2)}, + {BU18RL82_IEN_CLLRX1_CRCERR_R, + BIT(0) | BIT(1) | BIT(2)}, + + {BU18RL82_IEN_FS_IMG_STATUS0, + BIT(0) | BIT(1) | BIT(2) | BIT(3)}, + {BU18RL82_IEN_FS_IMG_ERR_REGION0, 0xff}, + {BU18RL82_IEN_IO_STUCK_GPIO0, 0xff}, + {BU18RL82_IEN_IO_STUCK_IRQ, BIT(1) | BIT(7)}, + {BU18RL82_IEN_I2C_A_TIMEOUT, BIT(0) | BIT(1)}, + + {BU18RL82_IEN_REGCRC_ERR_PAGE0, 0xff}, + {BU18RL82_IEN_CLKDETECT_CLKIN_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_IEN_CLKDETECT_CLLRX0_PCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_IEN_CLKDETECT_CLLRX1_PCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_IEN_CLKDETECT_CLLTX0_SCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_IEN_CLKDETECT_LVDSTX0_PLLREF_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, +}; + +static const struct bu18rl82_isr_reg bu18rl82_reg_isr[18] = { + {BU18RL82_ISR_CLLRX0_LINK_UNLOCK, + BIT(1) | BIT(3) | BIT(4)}, + {BU18RL82_ISR_CLLRX1_LINK_UNLOCK, + BIT(1) | BIT(3) | BIT(4)}, + {BU18RL82_ISR_FCCRX0_CRCERR, BIT(0)}, + {BU18RL82_ISR_FCCRX1_CRCERR, BIT(0)}, + + {BU18RL82_ISR_BCCDES0_ERR_CRC, BIT(3)}, + {BU18RL82_ISR_CLLRX0_CRCERR_R, + BIT(0) | BIT(1) | BIT(2)}, + {BU18RL82_ISR_CLLRX1_CRCERR_R, + BIT(0) | BIT(1) | BIT(2)}, + + {BU18RL82_ISR_FS_IMG_STATUS0, + BIT(0) | BIT(1) | BIT(2) | BIT(3)}, + {BU18RL82_ISR_FS_IMG_ERR_REGION0, 0xff}, + {BU18RL82_ISR_IO_STUCK_GPIO0, 0xff}, + {BU18RL82_ISR_IO_STUCK_IRQ, BIT(1) | BIT(7)}, + {BU18RL82_ISR_I2C_A_TIMEOUT, BIT(0) | BIT(1)}, + + {BU18RL82_ISR_REGCRC_ERR_PAGE0, 0xff}, + {BU18RL82_ISR_CLKDETECT_CLKIN_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_ISR_CLKDETECT_CLLRX0_PCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_ISR_CLKDETECT_CLLRX1_PCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_ISR_CLKDETECT_CLLTX0_SCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18RL82_ISR_CLKDETECT_LVDSTX0_PLLREF_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.c b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.c new file mode 100644 index 0000000000..36f63b92d2 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * rohm-bu18tl82.c -- I2C register interface access for bu18tl82 serdes chip + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "../core.h" +#include "rohm-bu18tl82.h" + +#define PINCTRL_GROUP(a, b, c) { .name = a, .pins = b, .num_pins = c} + +static int BU18TL82_GPIO0_pins[] = {0}; +static int BU18TL82_GPIO1_pins[] = {1}; +static int BU18TL82_GPIO2_pins[] = {2}; +static int BU18TL82_GPIO3_pins[] = {3}; +static int BU18TL82_GPIO4_pins[] = {4}; +static int BU18TL82_GPIO5_pins[] = {5}; +static int BU18TL82_GPIO6_pins[] = {6}; +static int BU18TL82_GPIO7_pins[] = {7}; + +#define GROUP_DESC(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ +} + +struct serdes_function_data { + u8 gpio_rx_en:1; + u16 gpio_id; +}; + +static const char *serdes_gpio_groups[] = { + "BU18TL82_GPIO0", "BU18TL82_GPIO1", "BU18TL82_GPIO2", "BU18TL82_GPIO3", + "BU18TL82_GPIO4", "BU18TL82_GPIO5", "BU18TL82_GPIO6", "BU18TL82_GPIO7", +}; + +/*des -> ser -> soc*/ +#define FUNCTION_DESC_GPIO_INPUT(id) \ +{ \ + .name = "DES_GPIO"#id"_TO_SER", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 0, .gpio_id = (id < 8) ? (id + 2) : (id + 3) } \ + }, \ +} \ + +/*soc -> ser -> des*/ +#define FUNCTION_DESC_GPIO_OUTPUT(id) \ +{ \ + .name = "SER_TO_DES_GPIO"#id, \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_rx_en = 1, .gpio_id = (id < 8) ? (id + 2) : (id + 3) } \ + }, \ +} \ + +static struct pinctrl_pin_desc bu18tl82_pins_desc[] = { + PINCTRL_PIN(ROHM_BU18TL82_GPIO0, "BU18TL82_GPIO0"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO1, "BU18TL82_GPIO1"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO2, "BU18TL82_GPIO2"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO3, "BU18TL82_GPIO3"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO4, "BU18TL82_GPIO4"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO5, "BU18TL82_GPIO5"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO6, "BU18TL82_GPIO6"), + PINCTRL_PIN(ROHM_BU18TL82_GPIO7, "BU18TL82_GPIO7"), +}; + +static struct group_desc bu18tl82_groups_desc[] = { + GROUP_DESC(BU18TL82_GPIO0), + GROUP_DESC(BU18TL82_GPIO1), + GROUP_DESC(BU18TL82_GPIO2), + GROUP_DESC(BU18TL82_GPIO3), + GROUP_DESC(BU18TL82_GPIO4), + GROUP_DESC(BU18TL82_GPIO5), + GROUP_DESC(BU18TL82_GPIO6), + GROUP_DESC(BU18TL82_GPIO7), +}; + +static struct function_desc bu18tl82_functions_desc[] = { + FUNCTION_DESC_GPIO_INPUT(0), + FUNCTION_DESC_GPIO_INPUT(1), + FUNCTION_DESC_GPIO_INPUT(2), + FUNCTION_DESC_GPIO_INPUT(3), + FUNCTION_DESC_GPIO_INPUT(4), + FUNCTION_DESC_GPIO_INPUT(5), + FUNCTION_DESC_GPIO_INPUT(6), + FUNCTION_DESC_GPIO_INPUT(7), + FUNCTION_DESC_GPIO_INPUT(8), + FUNCTION_DESC_GPIO_INPUT(9), + FUNCTION_DESC_GPIO_INPUT(10), + FUNCTION_DESC_GPIO_INPUT(11), + FUNCTION_DESC_GPIO_INPUT(12), + FUNCTION_DESC_GPIO_INPUT(13), + FUNCTION_DESC_GPIO_INPUT(14), + FUNCTION_DESC_GPIO_INPUT(15), + + FUNCTION_DESC_GPIO_OUTPUT(0), + FUNCTION_DESC_GPIO_OUTPUT(1), + FUNCTION_DESC_GPIO_OUTPUT(2), + FUNCTION_DESC_GPIO_OUTPUT(3), + FUNCTION_DESC_GPIO_OUTPUT(4), + FUNCTION_DESC_GPIO_OUTPUT(5), + FUNCTION_DESC_GPIO_OUTPUT(6), + FUNCTION_DESC_GPIO_OUTPUT(7), + FUNCTION_DESC_GPIO_OUTPUT(8), + FUNCTION_DESC_GPIO_OUTPUT(9), + FUNCTION_DESC_GPIO_OUTPUT(10), + FUNCTION_DESC_GPIO_OUTPUT(11), + FUNCTION_DESC_GPIO_OUTPUT(12), + FUNCTION_DESC_GPIO_OUTPUT(13), + FUNCTION_DESC_GPIO_OUTPUT(14), + FUNCTION_DESC_GPIO_OUTPUT(15), +}; + +static struct serdes_chip_pinctrl_info bu18tl82_pinctrl_info = { + .pins = bu18tl82_pins_desc, + .num_pins = ARRAY_SIZE(bu18tl82_pins_desc), + .groups = bu18tl82_groups_desc, + .num_groups = ARRAY_SIZE(bu18tl82_groups_desc), + .functions = bu18tl82_functions_desc, + .num_functions = ARRAY_SIZE(bu18tl82_functions_desc), +}; + +void bu18tl82_bridge_swrst(struct serdes *serdes) +{ + int ret; + + ret = serdes_reg_write(serdes, BU18TL82_REG_SWRST_INTERNAL, 0x00ef); + if (ret < 0) + dev_err(serdes->dev, + "%s: failed to reset serdes 0x11 ret=%d\n", + __func__, ret); + + ret = serdes_reg_write(serdes, BU18TL82_REG_SWRST_MIPIRX, 0x0003); + if (ret < 0) + dev_err(serdes->dev, + "%s: failed to reset serdes 0x12 ret=%d\n", + __func__, ret); + + mdelay(20); + + SERDES_DBG_CHIP("%s: %s ret=%d\n", + __func__, serdes->dev->name, ret); +} + +void bu18tl82_enable_hwint(struct serdes *serdes, int enable) +{ + int i, ret; + + for (i = 0; i < ARRAY_SIZE(bu18tl82_reg_ien); i++) { + if (enable) { + ret = serdes_reg_write(serdes, bu18tl82_reg_ien[i].reg, + bu18tl82_reg_ien[i].ien); + if (ret) + printf("%s %s reg 0x%04x write error\n", + __func__, + serdes->dev->name, bu18tl82_reg_ien[i].reg); + } else { + ret = serdes_reg_write(serdes, bu18tl82_reg_ien[i].reg, 0); + if (ret) + printf("%s %s reg 0x%04x write error\n", + __func__, + serdes->dev->name, bu18tl82_reg_ien[i].reg); + } + } + + SERDES_DBG_CHIP("%s: %s enable=%d\n", __func__, + serdes->dev->name, enable); +} + +int bu18tl82_bridge_init(struct serdes *serdes) +{ + if (!dm_gpio_is_valid(&serdes->reset_gpio)) + bu18tl82_bridge_swrst(serdes); + + SERDES_DBG_CHIP("%s: %s\n", __func__, + serdes->dev->name); + + return 0; +} + +int bu18tl82_bridge_enable(struct serdes *serdes) +{ + return 0; +} + +int bu18tl82_bridge_disable(struct serdes *serdes) +{ + return 0; +} + +int bu18tl82_bridge_get_modes(struct serdes *serdes) +{ + return 0; +} + +int bu18tl82_bridge_pre_enable(struct serdes *serdes) +{ + int ret = 0; + + /* 1:enable 0:dsiable*/ + bu18tl82_enable_hwint(serdes, 0); + + mdelay(160); + + SERDES_DBG_CHIP("%s: %s ret=%d\n", __func__, + serdes->dev->name, ret); + + return ret; +} + +bool bu18tl82_bridge_detect(struct serdes *serdes) +{ + return true; +} + +static struct serdes_chip_bridge_ops bu18tl82_bridge_ops = { + .init = bu18tl82_bridge_init, + .get_modes = bu18tl82_bridge_get_modes, + .pre_enable = bu18tl82_bridge_pre_enable, + .enable = bu18tl82_bridge_enable, + .disable = bu18tl82_bridge_disable, + .detect = bu18tl82_bridge_detect, +}; + +static int bu18tl82_pinctrl_config_set(struct serdes *serdes, + unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + switch (param) { + case PIN_CONFIG_DRIVE_STRENGTH: + serdes_set_bits(serdes, bu18tl82_gpio_sw[pin_selector].reg, + bu18tl82_gpio_sw[pin_selector].mask, + FIELD_PREP(BIT(2) | BIT(1), argument)); + SERDES_DBG_CHIP("%s: serdes %s pin=%d drv arg=0x%x\n", + __func__, + serdes->dev->name, pin_selector, argument); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + serdes_set_bits(serdes, bu18tl82_gpio_pden[pin_selector].reg, + bu18tl82_gpio_pden[pin_selector].mask, + FIELD_PREP(BIT(4), argument)); + SERDES_DBG_CHIP("%s: serdes %s pin=%d pull-down arg=0x%x\n", + __func__, + serdes->dev->name, pin_selector, argument); + break; + + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, bu18tl82_gpio_oen[pin_selector].reg, + bu18tl82_gpio_oen[pin_selector].mask, + FIELD_PREP(BIT(3), argument)); + SERDES_DBG_CHIP("%s: serdes %s pin=%d output arg=0x%x\n", + __func__, + serdes->dev->name, pin_selector, argument); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int bu18tl82_pinctrl_set_pin_mux(struct serdes *serdes, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct function_desc *func; + struct pinctrl_pin_desc *pin; + int offset; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + pin = &serdes->chip_data->pinctrl_info->pins[pin_selector]; + if (!pin) { + printf("%s: pin is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p pin=%s num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + pin->name, pin->number); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + offset = pin->number; + if (offset > 7) + dev_err(serdes->dev, "%s gpio offset=%d > 7\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s: serdes %s gpio=0x%x, off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_id, offset); + serdes_set_bits(serdes, bu18tl82_gpio_oen[offset].reg, + bu18tl82_gpio_oen[offset].mask, + FIELD_PREP(BIT(3), fdata->gpio_rx_en)); + serdes_set_bits(serdes, bu18tl82_gpio_id_low[offset].reg, + bu18tl82_gpio_id_low[offset].mask, + FIELD_PREP(GENMASK(7, 0), + (fdata->gpio_id & 0xff))); + serdes_set_bits(serdes, bu18tl82_gpio_id_high[offset].reg, + bu18tl82_gpio_id_high[offset].mask, + FIELD_PREP(GENMASK(2, 0), + ((fdata->gpio_id >> 8) & 0x7))); + serdes_set_bits(serdes, bu18tl82_gpio_pden[offset].reg, + bu18tl82_gpio_pden[offset].mask, + FIELD_PREP(BIT(4), 0)); + } + + return 0; +} + +static int bu18tl82_pinctrl_set_grp_mux(struct serdes *serdes, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes_pinctrl *pinctrl = serdes->serdes_pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i, offset; + + func = &serdes->chip_data->pinctrl_info->functions[func_selector]; + if (!func) { + printf("%s: func is null\n", __func__); + return -EINVAL; + } + + grp = &serdes->chip_data->pinctrl_info->groups[group_selector]; + if (!grp) { + printf("%s: grp is null\n", __func__); + return -EINVAL; + } + + SERDES_DBG_CHIP("%s: serdes %s func=%s data=%p grp=%s data=%p, num=%d\n", + __func__, serdes->dev->name, + func->name, func->data, + grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + for (i = 0; i < grp->num_pins; i++) { + offset = grp->pins[i] - pinctrl->pin_base; + if (offset > 7) + dev_err(serdes->dev, "%s gpio offset=%d > 7\n", + serdes->dev->name, offset); + else + SERDES_DBG_CHIP("%s serdes %s io=0x%x off=%d\n", + __func__, serdes->dev->name, + fdata->gpio_id, offset); + serdes_set_bits(serdes, bu18tl82_gpio_oen[offset].reg, + bu18tl82_gpio_oen[offset].mask, + FIELD_PREP(BIT(3), fdata->gpio_rx_en)); + serdes_set_bits(serdes, bu18tl82_gpio_id_low[offset].reg, + bu18tl82_gpio_id_low[offset].mask, + FIELD_PREP(GENMASK(7, 0), + (fdata->gpio_id & 0xff))); + serdes_set_bits(serdes, bu18tl82_gpio_id_high[offset].reg, + bu18tl82_gpio_id_high[offset].mask, + FIELD_PREP(GENMASK(2, 0), + ((fdata->gpio_id >> 8) & 0x7))); + serdes_set_bits(serdes, bu18tl82_gpio_pden[offset].reg, + bu18tl82_gpio_pden[offset].mask, + FIELD_PREP(BIT(4), 0)); + } + } + + return 0; +} + +static struct serdes_chip_pinctrl_ops bu18tl82_pinctrl_ops = { + .pinconf_set = bu18tl82_pinctrl_config_set, + .pinmux_set = bu18tl82_pinctrl_set_pin_mux, + .pinmux_group_set = bu18tl82_pinctrl_set_grp_mux, +}; + +static int bu18tl82_gpio_direction_input(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int bu18tl82_gpio_direction_output(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int bu18tl82_gpio_get_level(struct serdes *serdes, int gpio) +{ + return 0; +} + +static int bu18tl82_gpio_set_level(struct serdes *serdes, + int gpio, int value) +{ + return 0; +} + +static int bu18tl82_gpio_set_config(struct serdes *serdes, + int gpio, unsigned long config) +{ + return 0; +} + +static int bu18tl82_gpio_to_irq(struct serdes *serdes, int gpio) +{ + return 0; +} + +static struct serdes_chip_gpio_ops bu18tl82_gpio_ops = { + .direction_input = bu18tl82_gpio_direction_input, + .direction_output = bu18tl82_gpio_direction_output, + .get_level = bu18tl82_gpio_get_level, + .set_level = bu18tl82_gpio_set_level, + .set_config = bu18tl82_gpio_set_config, + .to_irq = bu18tl82_gpio_to_irq, +}; + +struct serdes_chip_data serdes_bu18tl82_data = { + .name = "bu18tl82", + .serdes_type = TYPE_SER, + .serdes_id = ROHM_ID_BU18TL82, + .pinctrl_info = &bu18tl82_pinctrl_info, + .bridge_ops = &bu18tl82_bridge_ops, + .pinctrl_ops = &bu18tl82_pinctrl_ops, + .gpio_ops = &bu18tl82_gpio_ops, +}; +EXPORT_SYMBOL_GPL(serdes_bu18tl82_data); + +MODULE_LICENSE("GPL"); diff --git a/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.h b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.h new file mode 100644 index 0000000000..6e991cef43 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/rohm/rohm-bu18tl82.h @@ -0,0 +1,452 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * include/linux/mfd/serdes/gpio.h -- GPIO for different serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#ifndef __MFD_SERDES_ROHM_BU18TL82_H__ +#define __MFD_SERDES_ROHM_BU18TL82_H__ + +#define BU18TL82_REG_SWRST_INTERNAL 0x0011 +#define BU18TL82_REG_SWRST_MIPIRX 0x0012 + +#define BU18TL82_REG_SWRST_INTERNAL 0x0011 +#define BU18TL82_REG_SWRST_MIPIRX 0x0012 + +#define BU18TL82_BLOCK_EN_MIPIRX0 0x0013 //h [0] 1’b0 +#define BU18TL82_BLOCK_EN_LVDSRX0 0x0013 //h [1] 1’b0 +#define BU18TL82_BLOCK_EN_CLLTX0 0x0013 //h [3] 1’b0 +#define BU18TL82_BLOCK_EN_VPLL0 0x0013 //h [4] 1’b0 +#define BU18TL82_BLOCK_EN_SSCG0 0x0013 //h [5] 1’b0 +#define BU18TL82_BLOCK_EN_MIPIRX1 0x0014 //h [0] 1’b0 +#define BU18TL82_BLOCK_EN_LVDSRX1 0x0014 //h [1] 1’b0 +#define BU18TL82_BLOCK_EN_CLLTX1 0x0014 //h [3] 1’b0 +#define BU18TL82_BLOCK_EN_VPLL1 0x0014 //h [4] 1’b0 +#define BU18TL82_BLOCK_EN_SSCG1 0x0014 //h [5] 1’b0 + +/*gpio register for driver/direction/pull-down*/ +#define BU18TL82_IO_SW_GPIO0 0x002A //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO0 0x002A //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO0 0x002A //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO1 0x002D //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO1 0x002D //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO1 0x002D //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO2 0x0030 //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO2 0x0030 //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO2 0x0030 //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO3 0x0033 //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO3 0x0033 //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO3 0x0033 //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO4 0x0036 //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO4 0x0036 //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO4 0x0036 //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO5 0x0039 //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO5 0x0039 //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO5 0x0039 //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO6 0x003C //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO6 0x003C //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO6 0x003C //h [4] 1’b1 +#define BU18TL82_IO_SW_GPIO7 0x003F //h [2:1] 2’b00 +#define BU18TL82_IO_OEN_GPIO7 0x003F //h [3] 1’b1 +#define BU18TL82_IO_PDEN_GPIO7 0x003F //h [4] 1’b1 + +/* + * gpio register for define connection with des gpiox, + * 11bits such as 0x002c:002b=[b2..b0 b7...b0] + * default value: + * ser gpio0-->des gpio0 + * ser gpio1-->des gpio1 + * ser gpio2-->des gpio2 + * ser gpio3-->des gpio3 + */ +#define BU18TL82_GPIO_SEL0_HIGH 0x002C //h [2:0], +#define BU18TL82_GPIO_SEL0_LOW 0x002B //h [7:0] 11’h002 +#define BU18TL82_GPIO_SEL1_HIGH 0x002F //h [2:0], +#define BU18TL82_GPIO_SEL1_LOW 0x002E //h [7:0] 11’h003 +#define BU18TL82_GPIO_SEL2_HIGH 0x0032 //h [2:0], +#define BU18TL82_GPIO_SEL2_LOW 0x0031 //h [7:0] 11’h004 +#define BU18TL82_GPIO_SEL3_HIGH 0x0035 //h [2:0], +#define BU18TL82_GPIO_SEL3_LOW 0x0034 //h [7:0] 11’h005 +#define BU18TL82_GPIO_SEL4_HIGH 0x0038 //h [2:0], +#define BU18TL82_GPIO_SEL4_LOW 0x0037 //h [7:0] 11’h006 +#define BU18TL82_GPIO_SEL5_HIGH 0x003B //h [2:0], +#define BU18TL82_GPIO_SEL5_LOW 0x003A //h [7:0] 11’h007 +/*datasheet about gpio6/7 need modify*/ +#define BU18TL82_GPIO_SEL6_LOW 0x003E //h [2:0], +#define BU18TL82_GPIO_SEL6_HIGH 0x003D //h [7:0] 11’h008 +#define BU18TL82_GPIO_SEL7_LOW 0x0041 //h [2:0], +#define BU18TL82_GPIO_SEL7_HIGH 0x0040 //h [7:0] 11’h009 + +/*gpio register for define bu18tl82 gpio pin, and gpio0 to gpio0 default*/ +#define BU18TL82_FCCTX0_SEL_GPI0 0x02A7 //h [4:0] 5’h02 +#define BU18TL82_FCCTX0_SEL_GPI1 0x02A8 //h [4:0] 5’h03 +#define BU18TL82_FCCTX0_SEL_GPI2 0x02A9 //h [4:0] 5’h04 +#define BU18TL82_FCCTX0_SEL_GPI3 0x02AA //h [4:0] 5’h05 +#define BU18TL82_FCCTX0_SEL_GPI4 0x02AB //h [4:0] 5’h06 +#define BU18TL82_FCCTX0_SEL_GPI5 0x02AC //h [4:0] 5’h07 +#define BU18TL82_FCCTX0_SEL_GPI6 0x02AD //h [4:0] 5’h08 +#define BU18TL82_FCCTX0_SEL_GPI7 0x02AE //h [4:0] 5’h09 +#define BU18TL82_CLLTX0_SEL_GPI0 0x02AF //h [4:0] 5’h04 +#define BU18TL82_CLLTX0_SEL_GPI1 0x02B0 //h [4:0] 5’h05 + +#define BU18TL82_FCCTX1_SEL_GPI0 0x03A7 //h [4:0] 5’h02 +#define BU18TL82_FCCTX1_SEL_GPI1 0x03A8 //h [4:0] 5’h03 +#define BU18TL82_FCCTX1_SEL_GPI2 0x03A9 //h [4:0] 5’h04 +#define BU18TL82_FCCTX1_SEL_GPI3 0x03AA //h [4:0] 5’h05 +#define BU18TL82_FCCTX1_SEL_GPI4 0x03AB //h [4:0] 5’h06 +#define BU18TL82_FCCTX1_SEL_GPI5 0x03AC //h [4:0] 5’h07 +#define BU18TL82_FCCTX1_SEL_GPI6 0x03AD //h [4:0] 5’h08 +#define BU18TL82_FCCTX1_SEL_GPI7 0x03AE //h [4:0] 5’h09 +#define BU18TL82_CLLTX1_SEL_GPI0 0x03AF //h [4:0] 5’h04 +#define BU18TL82_CLLTX1_SEL_GPI1 0x03B0 //h [4:0] 5’h05 + +/*write 1'b0 to this register to clear all isr register value8*/ +#define BU18TL82_ISR_CLEAR_ALL 0x0105 //h[0] + +#define BU18TL82_ISR_BCCDES0_ERR_CRC 0x0131 //h [3] 1’b0 +#define BU18TL82_ISR_BCCRX0_STATUS_NEAR_LOST 0x0131 //h[7] +#define BU18TL82_ISR_BCCDES1_ERR_CRC 0x0132 //h [3] 1’b0 +#define BU18TL82_ISR_BCCRX1_STATUS_NEAR_LOST 0x0132 //h[7] +#define BU18TL82_ISR_MIPIRX0_SOT_ERR 0x0133 //h[0] +#define BU18TL82_ISR_MIPIRX0_SOT_SYNC_ERR 0x0133 //h[1] +#define BU18TL82_ISR_MIPIRX0_EOT_SYNC_ERR 0x0133 //h[2] +#define BU18TL82_ISR_MIPIRX0_ECC1BIT_ERR 0x0134 //h[0] +#define BU18TL82_ISR_MIPIRX0_ECCMULT_ERR 0x0134 //h[1] +#define BU18TL82_ISR_MIPIRX0_CRC_ERR 0x0134 //h[2] +#define BU18TL82_ISR_MIPIRX1_SOT_ERR 0x0135 //h[0] +#define BU18TL82_ISR_MIPIRX1_SOT_SYNC_ERR 0x0135 //h[1] +#define BU18TL82_ISR_MIPIRX1_EOT_SYNC_ERR 0x0135 //h[2] +#define BU18TL82_ISR_MIPIRX1_ECC1BIT_ERR 0x0136 //h[0] +#define BU18TL82_ISR_MIPIRX1_ECCMULT_ERR 0x0136 //h[1] +#define BU18TL82_ISR_MIPIRX1_CRC_ERR 0x0136 //h[2] +#define BU18TL82_ISR_LVDSRX0_V_TOTAL_MAX_ERR 0x0137 //h[0] +#define BU18TL82_ISR_LVDSRX0_V_TOTAL_MIN_ERR 0x0137 //h[1] +#define BU18TL82_ISR_LVDSRX0_V_ACTIVE_MAX_ERR 0x0137 //h[2] +#define BU18TL82_ISR_LVDSRX0_V_ACTIVE_MIN_ERR 0x0137 //h[3] +#define BU18TL82_ISR_LVDSRX0_H_TOTAL_MAX_ERR 0x0137 //h[4] +#define BU18TL82_ISR_LVDSRX0_H_TOTAL_MIN_ERR 0x0137 //h[5] +#define BU18TL82_ISR_LVDSRX0_H_ACTIVE_MAX_ERR 0x0137 //h[6] +#define BU18TL82_ISR_LVDSRX0_H_ACTIVE_MIN_ERR 0x0137 //h[7] +#define BU18TL82_ISR_LVDSRX1_V_TOTAL_MAX_ERR 0x0138 //h[0] +#define BU18TL82_ISR_LVDSRX1_V_TOTAL_MIN_ERR 0x0138 //h[1] +#define BU18TL82_ISR_LVDSRX1_V_ACTIVE_MAX_ERR 0x0138 //h[2] +#define BU18TL82_ISR_LVDSRX1_V_ACTIVE_MIN_ERR 0x0138 //h[3] +#define BU18TL82_ISR_LVDSRX1_H_TOTAL_MAX_ERR 0x0138 //h[4] +#define BU18TL82_ISR_LVDSRX1_H_TOTAL_MIN_ERR 0x0138 //h[5] +#define BU18TL82_ISR_LVDSRX1_H_ACTIVE_MAX_ERR 0x0138 //h[6] +#define BU18TL82_ISR_LVDSRX1_H_ACTIVE_MIN_ERR 0x0138 //h[7] +#define BU18TL82_ISR_IO_STUCK_GPIO0 0x0139 //h[0] +#define BU18TL82_ISR_IO_STUCK_GPIO1 0x0139 //h[1] +#define BU18TL82_ISR_IO_STUCK_GPIO2 0x0139 //h[2] +#define BU18TL82_ISR_IO_STUCK_GPIO3 0x0139 //h[3] +#define BU18TL82_ISR_IO_STUCK_GPIO4 0x0139 //h[4] +#define BU18TL82_ISR_IO_STUCK_GPIO5 0x0139 //h[5] +#define BU18TL82_ISR_IO_STUCK_GPIO6 0x0139 //h[6] +#define BU18TL82_ISR_IO_STUCK_GPIO7 0x0139 //h[7] +#define BU18TL82_ISR_IO_STUCK_IRQ 0x013a //h[1] +#define BU18TL82_ISR_IDS_UNSTABLE 0x013a //h [7] 1’b0 +#define BU18TL82_ISR_I2C_A_TIMEOUT 0x013b //h [0] 1’b0 +#define BU18TL82_ISR_I2C_A_XMIT_ERR 0x013b //h [1] 1’b0 +#define BU18TL82_ISR_I2C_B_TIMEOUT 0x013c //h [0] 1’b0 +#define BU18TL82_ISR_I2C_B_XMIT_ERR 0x013c //h [1] 1’b0 +#define BU18TL82_ISR_REGCRC_ERR_PAGE0 0x013d //h[0] +#define BU18TL82_ISR_REGCRC_ERR_PAGE1 0x013d //h[1] +#define BU18TL82_ISR_REGCRC_ERR_PAGE2 0x013d //h[2] +#define BU18TL82_ISR_REGCRC_ERR_PAGE3 0x013d //h[3] +#define BU18TL82_ISR_REGCRC_ERR_PAGE4 0x013d //h[4] +#define BU18TL82_ISR_REGCRC_ERR_PAGE5 0x013d //h[5] +#define BU18TL82_ISR_CLKDETECT_CLKIN0_STOP 0x013e //h [0] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLKIN0_UNLOCK 0x013e //h [1] 1’b0 +#define BU18TL82_ISR_CLKDETECT_OSC_STOP 0x013e //h [4] 1’b0 +#define BU18TL82_ISR_CLKDETECT_OSC_UNLOCK 0x013e //h [5] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLKIN1_STOP 0x013f //h [0] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLKIN1_UNLOCK 0x013f //h [1] 1’b0 +#define BU18TL82_ISR_CLKDETECT_LVDSRX0_STOP 0x0140 //h [0] 1’b0 +#define BU18TL82_ISR_CLKDETECT_LVDSRX0_UNLOCK 0x0140 //h [1] 1’b0 +#define BU18TL82_ISR_CLKDETECT_MIPIRX0_STOP 0x0140 //h [4] 1’b0 +#define BU18TL82_ISR_CLKDETECT_MIPIRX0_UNLOCK 0x0140 //h [5] 1’b0 +#define BU18TL82_ISR_CLKDETECT_LVDSRX1_STOP 0x0141 //h [0] 1’b0 +#define BU18TL82_ISR_CLKDETECT_LVDSRX1_UNLOCK 0x0141 //h [1] 1’b0 +#define BU18TL82_ISR_CLKDETECT_MIPIRX1_STOP 0x0141 //h [4] 1’b0 +#define BU18TL82_ISR_CLKDETECT_MIPIRX1_UNLOCK 0x0141 //h [5] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX0_SCLK_STOP 0x0142 //h [0] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX0_SCLK_UNLOCK 0x0142 //h [1] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX0_PLLREF_STOP 0x0142 //h [4] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX0_PLLREF_UNLOCK 0x0142 //h [5] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX1_SCLK_STOP 0x0143 //h [0] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX1_SCLK_UNLOCK 0x0143 //h [1] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX1_PLLREF_STOP 0x0143 //h [4] 1’b0 +#define BU18TL82_ISR_CLKDETECT_CLLTX1_PLLREF_UNLOCK 0x0143 //h [5] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR00 0x0149 //h [0] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR01 0x0149 //h [1] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR02 0x0149 //h [2] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR03 0x0149 //h [3] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR04 0x0149 //h [4] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR05 0x0149 //h [5] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR06 0x0149 //h [6] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR07 0x0149 //h [7] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR08 0x014a //h [0] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR09 0x014a //h [1] 1’b0 +#define BU18TL82_ISR_STATUS_RX0_ISR10 0x014a //h [2] 1’b0 + +#define BU18TL82_IEN_BCCDES0_ERR_CRC 0x0109 //h [3] 1’b0 +#define BU18TL82_IEN_BCCRX0_STATUS_NEAR_LOST 0x0109 //h[7] +#define BU18TL82_IEN_BCCDES1_ERR_CRC 0x010A //h [3] 1’b0 +#define BU18TL82_IEN_BCCRX1_STATUS_NEAR_LOST 0x010A //h[7] +#define BU18TL82_IEN_MIPIRX0_SOT_ERR 0x010B //h[0] +#define BU18TL82_IEN_MIPIRX0_SOT_SYNC_ERR 0x010B //h[1] +#define BU18TL82_IEN_MIPIRX0_EOT_SYNC_ERR 0x010B //h[2] +#define BU18TL82_IEN_MIPIRX0_ECC1BIT_ERR 0x010C //h[0] +#define BU18TL82_IEN_MIPIRX0_ECCMULT_ERR 0x010C //h[1] +#define BU18TL82_IEN_MIPIRX0_CRC_ERR 0x010C //h[2] +#define BU18TL82_IEN_MIPIRX1_SOT_ERR 0x010D //h[0] +#define BU18TL82_IEN_MIPIRX1_SOT_SYNC_ERR 0x010D //h[1] +#define BU18TL82_IEN_MIPIRX1_EOT_SYNC_ERR 0x010D //h[2] +#define BU18TL82_IEN_MIPIRX1_ECC1BIT_ERR 0x010E //h[0] +#define BU18TL82_IEN_MIPIRX1_ECCMULT_ERR 0x010E //h[1] +#define BU18TL82_IEN_MIPIRX1_CRC_ERR 0x010E //h[2] +#define BU18TL82_IEN_LVDSRX0_V_TOTAL_MAX_ERR 0x010F //h[0] +#define BU18TL82_IEN_LVDSRX0_V_TOTAL_MIN_ERR 0x010F //h[1] +#define BU18TL82_IEN_LVDSRX0_V_ACTIVE_MAX_ERR 0x010F //h[2] +#define BU18TL82_IEN_LVDSRX0_V_ACTIVE_MIN_ERR 0x010F //h[3] +#define BU18TL82_IEN_LVDSRX0_H_TOTAL_MAX_ERR 0x010F //h[4] +#define BU18TL82_IEN_LVDSRX0_H_TOTAL_MIN_ERR 0x010F //h[5] +#define BU18TL82_IEN_LVDSRX0_H_ACTIVE_MAX_ERR 0x010F //h[6] +#define BU18TL82_IEN_LVDSRX0_H_ACTIVE_MIN_ERR 0x010F //h[7] +#define BU18TL82_IEN_LVDSRX1_V_TOTAL_MAX_ERR 0x0110 //h[0] +#define BU18TL82_IEN_LVDSRX1_V_TOTAL_MIN_ERR 0x0110 //h[1] +#define BU18TL82_IEN_LVDSRX1_V_ACTIVE_MAX_ERR 0x0110 //h[2] +#define BU18TL82_IEN_LVDSRX1_V_ACTIVE_MIN_ERR 0x0110 //h[3] +#define BU18TL82_IEN_LVDSRX1_H_TOTAL_MAX_ERR 0x0110 //h[4] +#define BU18TL82_IEN_LVDSRX1_H_TOTAL_MIN_ERR 0x0110 //h[5] +#define BU18TL82_IEN_LVDSRX1_H_ACTIVE_MAX_ERR 0x0110 //h[6] +#define BU18TL82_IEN_LVDSRX1_H_ACTIVE_MIN_ERR 0x0110 //h[7] +#define BU18TL82_IEN_IO_STUCK_GPIO0 0x0111 //h[0] +#define BU18TL82_IEN_IO_STUCK_GPIO1 0x0111 //h[1] +#define BU18TL82_IEN_IO_STUCK_GPIO2 0x0111 //h[2] +#define BU18TL82_IEN_IO_STUCK_GPIO3 0x0111 //h[3] +#define BU18TL82_IEN_IO_STUCK_GPIO4 0x0111 //h[4] +#define BU18TL82_IEN_IO_STUCK_GPIO5 0x0111 //h[5] +#define BU18TL82_IEN_IO_STUCK_GPIO6 0x0111 //h[6] +#define BU18TL82_IEN_IO_STUCK_GPIO7 0x0111 //h[7] +#define BU18TL82_IEN_IO_STUCK_IRQ 0x0112 //h[1] +#define BU18TL82_IEN_IDS_UNSTABLE 0x0112 //h [7] 1’b0 +#define BU18TL82_IEN_I2C_A_TIMEOUT 0x0113 //h [0] 1’b0 +#define BU18TL82_IEN_I2C_A_XMIT_ERR 0x0113 //h [1] 1’b0 +#define BU18TL82_IEN_I2C_B_TIMEOUT 0x0114 //h [0] 1’b0 +#define BU18TL82_IEN_I2C_B_XMIT_ERR 0x0114 //h [1] 1’b0 +#define BU18TL82_IEN_REGCRC_ERR_PAGE0 0x0115 //h[0] +#define BU18TL82_IEN_REGCRC_ERR_PAGE1 0x0115 //h[1] +#define BU18TL82_IEN_REGCRC_ERR_PAGE2 0x0115 //h[2] +#define BU18TL82_IEN_REGCRC_ERR_PAGE3 0x0115 //h[3] +#define BU18TL82_IEN_REGCRC_ERR_PAGE4 0x0115 //h[4] +#define BU18TL82_IEN_REGCRC_ERR_PAGE5 0x0115 //h[5] +#define BU18TL82_IEN_CLKDETECT_CLKIN0_STOP 0x0116 //h [0] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLKIN0_UNLOCK 0x0116 //h [1] 1’b0 +#define BU18TL82_IEN_CLKDETECT_OSC_STOP 0x0116 //h [4] 1’b0 +#define BU18TL82_IEN_CLKDETECT_OSC_UNLOCK 0x0116 //h [5] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLKIN1_STOP 0x0117 //h [0] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLKIN1_UNLOCK 0x0117 //h [1] 1’b0 +#define BU18TL82_IEN_CLKDETECT_LVDSRX0_STOP 0x0118 //h [0] 1’b0 +#define BU18TL82_IEN_CLKDETECT_LVDSRX0_UNLOCK 0x0118 //h [1] 1’b0 +#define BU18TL82_IEN_CLKDETECT_MIPIRX0_STOP 0x0118 //h [4] 1’b0 +#define BU18TL82_IEN_CLKDETECT_MIPIRX0_UNLOCK 0x0118 //h [5] 1’b0 +#define BU18TL82_IEN_CLKDETECT_LVDSRX1_STOP 0x0119 //h [0] 1’b0 +#define BU18TL82_IEN_CLKDETECT_LVDSRX1_UNLOCK 0x0119 //h [1] 1’b0 +#define BU18TL82_IEN_CLKDETECT_MIPIRX1_STOP 0x0119 //h [4] 1’b0 +#define BU18TL82_IEN_CLKDETECT_MIPIRX1_UNLOCK 0x0119 //h [5] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX0_SCLK_STOP 0x011A //h [0] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX0_SCLK_UNLOCK 0x011A //h [1] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX0_PLLREF_STOP 0x011A //h [4] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX0_PLLREF_UNLOCK 0x011A //h [5] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX1_SCLK_STOP 0x011B //h [0] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX1_SCLK_UNLOCK 0x011B //h [1] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX1_PLLREF_STOP 0x011B //h [4] 1’b0 +#define BU18TL82_IEN_CLKDETECT_CLLTX1_PLLREF_UNLOCK 0x011B //h [5] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR00 0x0121 //h [0] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR01 0x0121 //h [1] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR02 0x0121 //h [2] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR03 0x0121 //h [3] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR04 0x0121 //h [4] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR05 0x0121 //h [5] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR06 0x0121 //h [6] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR07 0x0121 //h [7] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR08 0x0122 //h [0] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR09 0x0122 //h [1] 1’b0 +#define BU18TL82_IEN_STATUS_RX0_ISR10 0x0122 //h [2] 1’b0 + +struct bu18tl82_gpio_sw_reg { + unsigned int reg; + unsigned int mask; //2/4/6/8ma +}; + +struct bu18tl82_gpio_oen_reg { + unsigned int reg; + unsigned int mask; //0:output 1:input +}; + +struct bu18tl82_gpio_pden_reg { + unsigned int reg; + unsigned int mask; //0:no pulldown 1:connect pulldown +}; + +struct bu18tl82_gpio_id_low_reg { + unsigned int reg; + unsigned int mask; //b2b1b0 +}; + +struct bu18tl82_gpio_id_high_reg { + unsigned int reg; + unsigned int mask; //b11b10b9b8b7b6b5b4b3 +}; + +static const struct bu18tl82_gpio_sw_reg bu18tl82_gpio_sw[8] = { + {BU18TL82_IO_SW_GPIO0, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO1, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO2, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO3, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO4, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO5, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO6, BIT(2) | BIT(1)}, + {BU18TL82_IO_SW_GPIO7, BIT(2) | BIT(1)}, +}; + +static const struct bu18tl82_gpio_oen_reg bu18tl82_gpio_oen[8] = { + {BU18TL82_IO_OEN_GPIO0, BIT(3)}, + {BU18TL82_IO_OEN_GPIO1, BIT(3)}, + {BU18TL82_IO_OEN_GPIO2, BIT(3)}, + {BU18TL82_IO_OEN_GPIO3, BIT(3)}, + {BU18TL82_IO_OEN_GPIO4, BIT(3)}, + {BU18TL82_IO_OEN_GPIO5, BIT(3)}, + {BU18TL82_IO_OEN_GPIO6, BIT(3)}, + {BU18TL82_IO_OEN_GPIO7, BIT(3)}, +}; + +static const struct bu18tl82_gpio_pden_reg bu18tl82_gpio_pden[8] = { + {BU18TL82_IO_PDEN_GPIO0, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO1, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO2, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO3, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO4, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO5, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO6, BIT(4)}, + {BU18TL82_IO_PDEN_GPIO7, BIT(4)}, +}; + +static const struct bu18tl82_gpio_id_low_reg bu18tl82_gpio_id_low[8] = { + {BU18TL82_GPIO_SEL0_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL1_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL2_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL3_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL4_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL5_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL6_LOW, GENMASK(7, 0)}, + {BU18TL82_GPIO_SEL7_LOW, GENMASK(7, 0)}, +}; + +static const struct bu18tl82_gpio_id_high_reg bu18tl82_gpio_id_high[8] = { + {BU18TL82_GPIO_SEL0_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL1_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL2_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL3_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL4_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL5_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL6_HIGH, GENMASK(2, 0)}, + {BU18TL82_GPIO_SEL7_HIGH, GENMASK(2, 0)}, +}; + +struct bu18tl82_ien_reg { + unsigned int reg; + unsigned int ien; +}; + +struct bu18tl82_isr_reg { + unsigned int reg; + unsigned int isr; +}; + +static const struct bu18tl82_ien_reg bu18tl82_reg_ien[21] = { + {BU18TL82_IEN_BCCRX0_STATUS_NEAR_LOST, BIT(3) | BIT(7)}, + {BU18TL82_IEN_BCCRX1_STATUS_NEAR_LOST, BIT(3) | BIT(7)}, + + {BU18TL82_IEN_MIPIRX0_SOT_ERR, + BIT(0) | BIT(0) | BIT(2)}, + {BU18TL82_IEN_MIPIRX0_ECC1BIT_ERR, + BIT(0) | BIT(0) | BIT(2)}, + + {BU18TL82_IEN_MIPIRX1_SOT_ERR, + BIT(0) | BIT(0) | BIT(2)}, + {BU18TL82_IEN_MIPIRX1_ECC1BIT_ERR, + BIT(0) | BIT(0) | BIT(2)}, + + {BU18TL82_IEN_LVDSRX0_V_TOTAL_MAX_ERR, 0XFF}, + {BU18TL82_IEN_LVDSRX1_V_TOTAL_MAX_ERR, 0XFF}, + + {BU18TL82_IEN_IO_STUCK_GPIO0, 0XFF}, + {BU18TL82_IEN_IO_STUCK_IRQ, BIT(1) | BIT(7)}, + {BU18TL82_IEN_I2C_A_TIMEOUT, BIT(0) | BIT(1)}, + {BU18TL82_IEN_I2C_B_TIMEOUT, BIT(0) | BIT(1)}, + + {BU18TL82_IEN_REGCRC_ERR_PAGE0, 0x3F}, + + {BU18TL82_IEN_CLKDETECT_CLKIN0_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_IEN_CLKDETECT_CLKIN1_STOP, + BIT(0) | BIT(1)}, + + {BU18TL82_IEN_CLKDETECT_LVDSRX0_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_IEN_CLKDETECT_LVDSRX1_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_IEN_CLKDETECT_CLLTX0_SCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_IEN_CLKDETECT_CLLTX1_SCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + + {BU18TL82_IEN_STATUS_RX0_ISR00, 0xff}, + {BU18TL82_IEN_STATUS_RX0_ISR08, BIT(0) | BIT(1) | BIT(2)}, +}; + +static const struct bu18tl82_isr_reg bu18tl82_reg_isr[21] = { + {BU18TL82_ISR_BCCRX0_STATUS_NEAR_LOST, BIT(3) | BIT(7)}, + {BU18TL82_ISR_BCCRX1_STATUS_NEAR_LOST, BIT(3) | BIT(7)}, + + {BU18TL82_ISR_MIPIRX0_SOT_ERR, BIT(0) | BIT(0) | BIT(2)}, + {BU18TL82_ISR_MIPIRX0_ECC1BIT_ERR, BIT(0) | BIT(0) | BIT(2)}, + + {BU18TL82_ISR_MIPIRX1_SOT_ERR, BIT(0) | BIT(0) | BIT(2)}, + {BU18TL82_ISR_MIPIRX1_ECC1BIT_ERR, BIT(0) | BIT(0) | BIT(2)}, + + {BU18TL82_ISR_LVDSRX0_V_TOTAL_MAX_ERR, 0XFF}, + {BU18TL82_ISR_LVDSRX1_V_TOTAL_MAX_ERR, 0XFF}, + + {BU18TL82_ISR_IO_STUCK_GPIO0, 0XFF}, + {BU18TL82_ISR_IO_STUCK_IRQ, BIT(1) | BIT(7)}, + {BU18TL82_ISR_I2C_A_TIMEOUT, BIT(0) | BIT(1)}, + {BU18TL82_ISR_I2C_B_TIMEOUT, BIT(0) | BIT(1)}, + + {BU18TL82_ISR_REGCRC_ERR_PAGE0, 0x3F}, + + {BU18TL82_ISR_CLKDETECT_CLKIN0_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_ISR_CLKDETECT_CLKIN1_STOP, + BIT(0) | BIT(1)}, + + {BU18TL82_ISR_CLKDETECT_LVDSRX0_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_ISR_CLKDETECT_LVDSRX1_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_ISR_CLKDETECT_CLLTX0_SCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + {BU18TL82_ISR_CLKDETECT_CLLTX1_SCLK_STOP, + BIT(0) | BIT(1) | BIT(4) | BIT(5)}, + + {BU18TL82_ISR_STATUS_RX0_ISR00, 0xff}, + {BU18TL82_ISR_STATUS_RX0_ISR08, BIT(0) | BIT(1) | BIT(2)}, +}; + +#endif diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-bridge-split.c b/u-boot/drivers/video/drm/display-serdes/serdes-bridge-split.c new file mode 100644 index 0000000000..707aa8a9be --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-bridge-split.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-bridge_split.c -- display bridge_split for different serdes chips + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static void serdes_bridge_split_init(struct serdes *serdes) +{ + if (serdes->vpower_supply) + regulator_set_enable(serdes->vpower_supply, true); + + if (dm_gpio_is_valid(&serdes->enable_gpio)) + dm_gpio_set_value(&serdes->enable_gpio, 1); + + mdelay(5); + + //video_bridge_set_active(serdes->dev, true); + + if (serdes->chip_data->bridge_ops->init) + serdes->chip_data->bridge_ops->init(serdes); + + serdes_i2c_set_sequence(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_split_pre_enable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + //serdes_bridge_split_split_init(serdes); + + if (serdes->chip_data->bridge_ops->pre_enable) + serdes->chip_data->bridge_ops->pre_enable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_split_post_disable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->bridge_ops->post_disable) + serdes->chip_data->bridge_ops->post_disable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_split_enable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->serdes_type == TYPE_DES) + serdes_bridge_split_init(serdes); + + if (serdes->chip_data->bridge_ops->enable) + serdes->chip_data->bridge_ops->enable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_split_disable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->bridge_ops->disable) + serdes->chip_data->bridge_ops->disable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_split_mode_set(struct rockchip_bridge *bridge, + const struct drm_display_mode *mode) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + memcpy(&serdes->serdes_bridge_split->mode, mode, + sizeof(struct drm_display_mode)); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static bool serdes_bridge_split_detect(struct rockchip_bridge *bridge) +{ + bool ret = true; + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->bridge_ops->detect) + ret = serdes->chip_data->bridge_ops->detect(serdes); + + SERDES_DBG_MFD("%s: %s %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name, ret ? "detected" : "no detected"); + + return ret; +} + +struct rockchip_bridge_funcs serdes_bridge_split_ops = { + .pre_enable = serdes_bridge_split_pre_enable, + .post_disable = serdes_bridge_split_post_disable, + .enable = serdes_bridge_split_enable, + .disable = serdes_bridge_split_disable, + .mode_set = serdes_bridge_split_mode_set, + .detect = serdes_bridge_split_detect, +}; + +static int serdes_bridge_split_probe(struct udevice *dev) +{ + struct rockchip_bridge *bridge; + struct serdes *serdes = dev_get_priv(dev->parent); + struct mipi_dsi_device *device = dev_get_platdata(dev); + + serdes->sel_mipi = dev_read_bool(dev->parent, "sel-mipi"); + if (serdes->sel_mipi) { + device->dev = dev; + device->lanes = dev_read_u32_default(dev->parent, "dsi,lanes", 4); + device->format = dev_read_u32_default(dev->parent, "dsi,format", + MIPI_DSI_FMT_RGB888); + device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + device->channel = dev_read_u32_default(dev->parent, "reg", 0); + } + + bridge = calloc(1, sizeof(*bridge)); + if (!bridge) + return -ENOMEM; + + dev->driver_data = (ulong)bridge; + bridge->dev = dev; + bridge->funcs = &serdes_bridge_split_ops; + + serdes->serdes_bridge_split->bridge = bridge; + + SERDES_DBG_MFD("%s: %s %s bridge=%p name=%s device=%p\n", + __func__, serdes->dev->name, + serdes->chip_data->name, + bridge, bridge->dev->name, device); + + return 0; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) + { .compatible = "maxim,max96745-bridge-split", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) + { .compatible = "maxim,max96755-bridge-split", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789) + { .compatible = "maxim,max96789-bridge-split", }, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_bridge_split) = { + .name = "serdes-bridge-split", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = serdes_of_match, + .probe = serdes_bridge_split_probe, + .priv_auto_alloc_size = sizeof(struct serdes_bridge_split), + .platdata_auto_alloc_size = sizeof(struct mipi_dsi_device), +}; diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-bridge.c b/u-boot/drivers/video/drm/display-serdes/serdes-bridge.c new file mode 100644 index 0000000000..ebac665dd7 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-bridge.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-bridge.c -- display bridge for different serdes chips + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static void serdes_bridge_init(struct serdes *serdes) +{ + if (serdes->vpower_supply) + regulator_set_enable(serdes->vpower_supply, true); + + if (dm_gpio_is_valid(&serdes->enable_gpio)) + dm_gpio_set_value(&serdes->enable_gpio, 1); + + mdelay(5); + + //video_bridge_set_active(serdes->dev, true); + + if (serdes->chip_data->bridge_ops->init) + serdes->chip_data->bridge_ops->init(serdes); + + serdes_i2c_set_sequence(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_pre_enable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + //serdes_bridge_init(serdes); + + if (serdes->chip_data->bridge_ops->pre_enable) + serdes->chip_data->bridge_ops->pre_enable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_post_disable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->bridge_ops->post_disable) + serdes->chip_data->bridge_ops->post_disable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_enable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->serdes_type == TYPE_DES) + serdes_bridge_init(serdes); + + if (serdes->chip_data->bridge_ops->enable) + serdes->chip_data->bridge_ops->enable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_disable(struct rockchip_bridge *bridge) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->bridge_ops->disable) + serdes->chip_data->bridge_ops->disable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_bridge_mode_set(struct rockchip_bridge *bridge, + const struct drm_display_mode *mode) +{ + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + memcpy(&serdes->serdes_bridge->mode, mode, + sizeof(struct drm_display_mode)); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static bool serdes_bridge_detect(struct rockchip_bridge *bridge) +{ + bool ret = true; + struct udevice *dev = bridge->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->bridge_ops->detect) + ret = serdes->chip_data->bridge_ops->detect(serdes); + + SERDES_DBG_MFD("%s: %s %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name, (ret == true) ? "detected" : "no detected"); + + return ret; +} + +struct rockchip_bridge_funcs serdes_bridge_ops = { + .pre_enable = serdes_bridge_pre_enable, + .post_disable = serdes_bridge_post_disable, + .enable = serdes_bridge_enable, + .disable = serdes_bridge_disable, + .mode_set = serdes_bridge_mode_set, + .detect = serdes_bridge_detect, +}; + +static int serdes_bridge_probe(struct udevice *dev) +{ + struct rockchip_bridge *bridge; + struct serdes *serdes = dev_get_priv(dev->parent); + struct mipi_dsi_device *device = dev_get_platdata(dev); + + if (!serdes->chip_data->bridge_ops) { + SERDES_DBG_MFD("%s %s no bridge ops\n", + __func__, serdes->chip_data->name); + return 0; + } + + serdes->sel_mipi = dev_read_bool(dev->parent, "sel-mipi"); + if (serdes->sel_mipi) { + device->dev = dev; + device->lanes = dev_read_u32_default(dev->parent, "dsi,lanes", 4); + device->format = dev_read_u32_default(dev->parent, "dsi,format", + MIPI_DSI_FMT_RGB888); + device->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + device->channel = dev_read_u32_default(dev->parent, "reg", 0); + } + + bridge = calloc(1, sizeof(*bridge)); + if (!bridge) + return -ENOMEM; + + dev->driver_data = (ulong)bridge; + bridge->dev = dev; + bridge->funcs = &serdes_bridge_ops; + + serdes->serdes_bridge->bridge = bridge; + + SERDES_DBG_MFD("%s: %s %s bridge=%p name=%s device=%p\n", + __func__, serdes->dev->name, + serdes->chip_data->name, + bridge, bridge->dev->name, device); + + return 0; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) + { .compatible = "rohm,bu18tl82-bridge", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) + { .compatible = "rohm,bu18rl82-bridge", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) + { .compatible = "maxim,max96745-bridge", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) + { .compatible = "maxim,max96755-bridge", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) + { .compatible = "maxim,max96789-bridge", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) + { .compatible = "rockchip,rkx111-bridge", }, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_bridge) = { + .name = "serdes-bridge", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = serdes_of_match, + .probe = serdes_bridge_probe, + .priv_auto_alloc_size = sizeof(struct serdes_bridge), + .platdata_auto_alloc_size = sizeof(struct mipi_dsi_device), +}; diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-core.c b/u-boot/drivers/video/drm/display-serdes/serdes-core.c new file mode 100644 index 0000000000..075220ae77 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-core.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-i2c.c -- display i2c for different serdes chips + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static int dm_i2c_reg_write_u8(struct udevice *dev, u8 reg, u8 val) +{ + int ret; + u8 buf[2]; + struct i2c_msg msg; + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + + buf[0] = reg; + buf[1] = val; + msg.addr = chip->chip_addr; + msg.flags = 0; + msg.len = 2; + msg.buf = buf; + + ret = dm_i2c_xfer(dev, &msg, 1); + if (ret) { + printf("dm i2c write failed: %d\n", ret); + return ret; + } + + return 0; +} + +static uint8_t dm_i2c_reg_read_u8(struct udevice *dev, u8 reg) +{ + int ret; + u8 data; + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + struct i2c_msg msg[] = { + { + .addr = chip->chip_addr, + .flags = 0, + .buf = (u8 *)®, + .len = 1, + }, { + .addr = chip->chip_addr, + .flags = I2C_M_RD, + .buf = (u8 *)&data, + .len = 1, + } + }; + + ret = dm_i2c_xfer(dev, msg, 2); + if (ret) { + printf("dm i2c read failed: %d\n", ret); + return ret; + } + + return data; +} + +static int dm_i2c_reg_clrset_u8(struct udevice *dev, + u8 offset, + u8 clr, u8 set) +{ + u8 val; + + val = dm_i2c_reg_read_u8(dev, offset); + if (val < 0) + return val; + + val &= ~clr; + val |= set; + + return dm_i2c_reg_write_u8(dev, offset, val); +} + +/** + * serdes_reg_read: Read a single serdes register. + * + * @serdes: Device to read from. + * @reg: Register to read. + * @val: Date read from register. + */ +int serdes_reg_read(struct serdes *serdes, + unsigned int reg, unsigned int *val) +{ + unsigned int value; + + if (serdes->chip_data->reg_val_type == REG_8BIT_VAL_8IT) + value = dm_i2c_reg_read_u8(serdes->dev, reg); + else + value = dm_i2c_reg_read(serdes->dev, reg); + + *val = value; + SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x\n", + __func__, serdes->dev->name, + serdes->dev->name, reg, *val); + return 0; +} +EXPORT_SYMBOL_GPL(serdes_reg_read); + +/** + * serdes_reg_write: Write a single serdes register. + * + * @serdes: Device to write to. + * @reg: Register to write to. + * @val: Value to write. + */ +int serdes_reg_write(struct serdes *serdes, unsigned int reg, + unsigned int val) +{ + int ret = 0; + + SERDES_DBG_I2C("%s %s Write Reg%04x %04x) type=%d\n", + __func__, serdes->dev->name, + reg, val, serdes->chip_data->reg_val_type); + if (serdes->chip_data->reg_val_type == REG_8BIT_VAL_8IT) { + ret = dm_i2c_reg_write_u8(serdes->dev, reg, val); + if (ret != 0) + return ret; + } else { + ret = dm_i2c_reg_write(serdes->dev, reg, val); + if (ret != 0) + return ret; + } + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_reg_write); + +/** + * serdes_multi_reg_write: Write many serdes register. + * + * @serdes: Device to write to. + * @regs: Registers to write to. + * @num_regs: Number of registers to write. + */ +int serdes_multi_reg_write(struct serdes *serdes, + const struct reg_sequence *regs, + int num_regs) +{ + int i, ret = 0; + + SERDES_DBG_I2C("%s %s %s num=%d\n", __func__, serdes->dev->name, + serdes->chip_data->name, num_regs); + + for (i = 0; i < num_regs; i++) { + ret = serdes_reg_write(serdes, regs[i].reg, regs[i].def); + SERDES_DBG_I2C("serdes %s Write Reg%04x %04x ret=%d\n", + serdes->chip_data->name, + regs[i].reg, regs[i].def, ret); + } + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_multi_reg_write); + +/** + * serdes_set_bits: Set the value of a bitfield in a serdes register + * + * @serdes: Device to write to. + * @reg: Register to write to. + * @mask: Mask of bits to set. + * @val: Value to set (unshifted) + */ +int serdes_set_bits(struct serdes *serdes, unsigned int reg, + unsigned int mask, unsigned int val) +{ + int ret = 0; + + SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x) mask=%04x\n", + __func__, + serdes->dev->name, + serdes->dev->name, reg, val, mask); + + if (serdes->chip_data->reg_val_type == REG_8BIT_VAL_8IT) + ret = dm_i2c_reg_clrset_u8(serdes->dev, reg, mask, val); + else + ret = dm_i2c_reg_clrset(serdes->dev, reg, mask, val); + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_set_bits); + +int serdes_i2c_set_sequence(struct serdes *serdes) +{ + int i, ret = 0; + unsigned int def = 0; + + for (i = 0; i < serdes->serdes_init_seq->reg_seq_cnt; i++) { + if (serdes->serdes_init_seq->reg_sequence[i].reg == 0xffff) { + SERDES_DBG_MFD("%s: delay 0x%04x us\n", __func__, + serdes->serdes_init_seq->reg_sequence[i].def); + udelay(serdes->serdes_init_seq->reg_sequence[i].def); + continue; + } + + ret = serdes_reg_write(serdes, + serdes->serdes_init_seq->reg_sequence[i].reg, + serdes->serdes_init_seq->reg_sequence[i].def); + + if (ret < 0) { + SERDES_DBG_MFD("failed to write reg %04x, ret %d\n", + serdes->serdes_init_seq->reg_sequence[i].reg, ret); + ret = serdes_reg_write(serdes, + serdes->serdes_init_seq->reg_sequence[i].reg, + serdes->serdes_init_seq->reg_sequence[i].def); + } + serdes_reg_read(serdes, serdes->serdes_init_seq->reg_sequence[i].reg, &def); + if ((def != serdes->serdes_init_seq->reg_sequence[i].def) || (ret < 0)) { + /*if read value != write value then write again*/ + printf("%s read %04x %04x != %04x\n", serdes->dev->name, + serdes->serdes_init_seq->reg_sequence[i].reg, + def, serdes->serdes_init_seq->reg_sequence[i].def); + ret = serdes_reg_write(serdes, + serdes->serdes_init_seq->reg_sequence[i].reg, + serdes->serdes_init_seq->reg_sequence[i].def); + } + } + + SERDES_DBG_MFD("serdes %s sequence_init\n", serdes->dev->name); + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_i2c_set_sequence); + +int serdes_parse_init_seq(struct udevice *dev, const u16 *data, + int length, struct serdes_init_seq *seq) +{ + struct reg_sequence *reg_sequence; + u16 *buf, *d; + unsigned int i, cnt; + int ret; + + if (!seq) + return -EINVAL; + + buf = calloc(1, length); + if (!buf) + return -ENOMEM; + + memcpy(buf, data, length); + + d = buf; + cnt = length / 4; + seq->reg_seq_cnt = cnt; + + seq->reg_sequence = calloc(cnt, sizeof(struct reg_sequence)); + if (!seq->reg_sequence) { + ret = -ENOMEM; + goto free_buf; + } + + for (i = 0; i < cnt; i++) { + reg_sequence = &seq->reg_sequence[i]; + reg_sequence->reg = get_unaligned_be16(&d[0]); + reg_sequence->def = get_unaligned_be16(&d[1]); + d += 2; + } + + return 0; + +free_buf: + free(buf); + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_parse_init_seq); + +int serdes_get_init_seq(struct serdes *serdes) +{ + const void *data = NULL; + int len, err; + + data = dev_read_prop(serdes->dev, "serdes-init-sequence", &len); + if (!data) { + printf("failed to get serdes-init-sequence\n"); + return -EINVAL; + } + + serdes->serdes_init_seq = calloc(1, sizeof(*serdes->serdes_init_seq)); + if (!serdes->serdes_init_seq) + return -ENOMEM; + + err = serdes_parse_init_seq(serdes->dev, + data, len, serdes->serdes_init_seq); + if (err) { + printf("failed to parse serdes-init-sequence\n"); + goto free_init_seq; + } + + return 0; + +free_init_seq: + free(serdes->serdes_init_seq); + + return err; +} +EXPORT_SYMBOL_GPL(serdes_get_init_seq); + +int serdes_gpio_register(struct udevice *dev, + struct serdes *serdes) +{ + bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC); + struct uclass_driver *drv; + int ret = -ENODEV; + const char *name; + ofnode subnode; + struct udevice *subdev; + struct udevice *gpio_dev; + + SERDES_DBG_MFD("%s node=%s\n", + __func__, ofnode_get_name(dev->node)); + + /* Lookup GPIO driver */ + drv = lists_uclass_lookup(UCLASS_GPIO); + if (!drv) { + printf("Cannot find GPIO driver\n"); + return -ENOENT; + } + + dev_for_each_subnode(subnode, dev) { + if (pre_reloc_only && + !ofnode_pre_reloc(subnode)) + continue; + + name = ofnode_get_name(subnode); + if (!name) + continue; + + if (strstr(name, "gpio")) { + ret = device_bind_driver_to_node(dev, + "serdes-gpio", name, + subnode, &subdev); + if (ret) + return ret; + + ret = uclass_get_device_by_ofnode(UCLASS_GPIO, + subnode, + &gpio_dev); + if (ret) { + printf("%s failed to get gpio dev\n", __func__); + return ret; + } + + SERDES_DBG_MFD("%s select %s gpio_dev=%s\n", + __func__, name, gpio_dev->name); + return 0; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_gpio_register); + +int serdes_pinctrl_register(struct udevice *dev, + struct serdes *serdes) +{ + bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC); + struct uclass_driver *drv; + int ret = -ENODEV; + const char *name; + ofnode subnode; + struct udevice *subdev; + struct udevice *pinctrl_dev; + + SERDES_DBG_MFD("%s node=%s\n", + __func__, ofnode_get_name(dev->node)); + + /* Lookup PINCTRL driver */ + drv = lists_uclass_lookup(UCLASS_PINCTRL); + if (!drv) { + printf("Cannot find PINCTRL driver\n"); + return -ENOENT; + } + + dev_for_each_subnode(subnode, dev) { + if (pre_reloc_only && + !ofnode_pre_reloc(subnode)) + continue; + + name = ofnode_get_name(subnode); + if (!name) + continue; + + if (strstr(name, "pinctrl")) { + ret = device_bind_driver_to_node(dev, + "serdes-pinctrl", name, + subnode, &subdev); + if (ret) + return ret; + + ret = uclass_get_device_by_ofnode(UCLASS_PINCTRL, + subnode, + &pinctrl_dev); + if (ret) { + printf("%s failed to get pinctrl\n", __func__); + return ret; + } + + SERDES_DBG_MFD("%s select %s pinctrl_dev=%s\n", + __func__, name, pinctrl_dev->name); + return 0; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(serdes_pinctrl_register); + +static int serdes_i2c_init(struct serdes *serdes) +{ + int ret = 0; + int i = 0; + + if (serdes->vpower_supply) + regulator_set_enable(serdes->vpower_supply, true); + + if (dm_gpio_is_valid(&serdes->enable_gpio)) + dm_gpio_set_value(&serdes->enable_gpio, 1); + + mdelay(5); + + for (i = 0; i < 3; i++) { + ret = serdes_i2c_set_sequence(serdes); + if (!ret) + break; + mdelay(20); + } + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); + + return ret; +} + +static int serdes_i2c_probe(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev); + int ret; + + ret = i2c_set_chip_offset_len(dev, 2); + if (ret) + return ret; + + serdes->dev = dev; + serdes->chip_data = (struct serdes_chip_data *)dev_get_driver_data(dev); + serdes->type = serdes->chip_data->serdes_type; + + SERDES_DBG_MFD("serdes %s %s probe start\n", + serdes->dev->name, serdes->chip_data->name); + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vpower-supply", + &serdes->vpower_supply); + if (ret && ret != -ENOENT) + SERDES_DBG_MFD("%s: Cannot get power supply: %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "enable-gpios", 0, + &serdes->enable_gpio, GPIOD_IS_OUT); + if (ret) + SERDES_DBG_MFD("%s: failed to get enable gpio: %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "lock-gpios", 0, + &serdes->lock_gpio, + GPIOD_IS_IN); + if (ret) + SERDES_DBG_MFD("%s: failed to get lock gpio: %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "err-gpios", 0, + &serdes->err_gpio, + GPIOD_IS_IN); + if (ret) + SERDES_DBG_MFD("%s: failed to err gpio: %d\n", + __func__, ret); + + ret = serdes_get_init_seq(serdes); + if (ret) + return ret; + + serdes_i2c_init(serdes); + + printf("%s %s successful, version %s\n", + __func__, + serdes->dev->name, + SERDES_UBOOT_DISPLAY_VERSION); + + return 0; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_NOVO_NCA9539) + { .compatible = "novo,nca9539", .data = (ulong)&serdes_nca9539_data }, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_misc) = { + .name = "serdes-misc", + .id = UCLASS_MISC, + .of_match = serdes_of_match, + .probe = serdes_i2c_probe, + .priv_auto_alloc_size = sizeof(struct serdes), +}; + +int serdes_power_init(void) +{ + struct udevice *dev; + int ret = 0; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(serdes_misc), + &dev); + if (ret) + printf("%s failed to get misc device ret=%d\n", __func__, ret); + + return ret; +} diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-gpio.c b/u-boot/drivers/video/drm/display-serdes/serdes-gpio.c new file mode 100644 index 0000000000..f35454561d --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-gpio.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * gpiolib support for different serdes chip + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + * + */ + +#include "core.h" + +static int serdes_gpio_get(struct udevice *dev, unsigned int offset) +{ + struct serdes_pinctrl *serdes_pinctrl = dev_get_priv(dev->parent); + struct serdes *serdes = serdes_pinctrl->parent; + int ret = 0; + + if (serdes->chip_data->gpio_ops->get_level) + ret = serdes->chip_data->gpio_ops->get_level(serdes, offset); + + SERDES_DBG_MFD("%s: %s %s gpio=%d\n", __func__, + serdes->dev->name, + serdes->chip_data->name, offset); + return ret; +} + +static int serdes_gpio_set(struct udevice *dev, + unsigned int offset, int value) +{ + struct serdes_pinctrl *serdes_pinctrl = dev_get_priv(dev->parent); + struct serdes *serdes = serdes_pinctrl->parent; + int ret = 0; + + if (serdes->chip_data->gpio_ops->set_level) + ret = serdes->chip_data->gpio_ops->set_level(serdes, offset, value); + + SERDES_DBG_MFD("%s: %s %s gpio=%d,val=%d\n", __func__, + serdes->dev->name, + serdes->chip_data->name, offset, value); + return ret; +} + +static int serdes_gpio_direction_input(struct udevice *dev, + unsigned int offset) +{ + struct serdes_pinctrl *serdes_pinctrl = dev_get_priv(dev->parent); + struct serdes *serdes = serdes_pinctrl->parent; + int ret = 0; + + if (serdes->chip_data->gpio_ops->direction_input) + ret = serdes->chip_data->gpio_ops->direction_input(serdes, offset); + + SERDES_DBG_MFD("%s: %s %s gpio=%d\n", __func__, + serdes->dev->name, + serdes->chip_data->name, offset); + return ret; +} + +static int serdes_gpio_direction_output(struct udevice *dev, + unsigned int offset, int value) +{ + struct serdes_pinctrl *serdes_pinctrl = dev_get_priv(dev->parent); + struct serdes *serdes = serdes_pinctrl->parent; + int ret = 0; + + if (serdes->chip_data->gpio_ops->direction_output) + ret = serdes->chip_data->gpio_ops->direction_output(serdes, offset, value); + + SERDES_DBG_MFD("%s: %s %s gpio=%d,val=%d\n", __func__, + serdes->dev->name, + serdes->chip_data->name, offset, value); + return ret; +} + +static int serdes_gpio_probe(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent->parent); + struct serdes_pinctrl *serdes_pinctrl = serdes->serdes_pinctrl; + struct serdes_gpio *serdes_gpio; + + serdes_gpio = calloc(1, sizeof(*serdes_gpio)); + if (!serdes_gpio) + return -ENOMEM; + + serdes_pinctrl->serdes_gpio = serdes_gpio; + + serdes_gpio->parent = serdes_pinctrl; + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + dev->name, serdes->chip_data->name); + return 0; +} + +static struct dm_gpio_ops serdes_gpio_ops = { + .set_value = serdes_gpio_set, + .get_value = serdes_gpio_get, + .direction_input = serdes_gpio_direction_input, + .direction_output = serdes_gpio_direction_output, +}; + +U_BOOT_DRIVER(serdes_gpio) = { + .name = "serdes-gpio", + .id = UCLASS_GPIO, + .probe = serdes_gpio_probe, + .ops = &serdes_gpio_ops, + .priv_auto_alloc_size = sizeof(struct serdes_gpio), +}; + diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-i2c.c b/u-boot/drivers/video/drm/display-serdes/serdes-i2c.c new file mode 100644 index 0000000000..933bca96f0 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-i2c.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-bridge.c -- display bridge for different serdes chips + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static struct serdes *g_serdes_ser_split[MAX_NUM_SERDES_SPLIT]; + +static void serdes_i2c_init(struct serdes *serdes) +{ + if (serdes->vpower_supply) + regulator_set_enable(serdes->vpower_supply, true); + + if (dm_gpio_is_valid(&serdes->enable_gpio)) + dm_gpio_set_value(&serdes->enable_gpio, 1); + + //mdelay(5); + + //video_bridge_set_active(serdes->dev, true); + + if (serdes->chip_data->bridge_ops->init) + serdes->chip_data->bridge_ops->init(serdes); + + serdes_i2c_set_sequence(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, + serdes->dev->name, + serdes->chip_data->name); +} + +static int serdes_set_i2c_address(struct serdes *serdes, + u32 reg_hw, u32 reg_use, int link) +{ + int ret = 0; + struct dm_i2c_chip *chip_split; + struct serdes *serdes_split = serdes->g_serdes_bridge_split; + + if (!serdes_split) { + pr_info("%s: serdes_split is null\n", __func__); + return -1; + } + + chip_split = dev_get_parent_platdata(serdes->dev); + SERDES_DBG_MFD("%s: %s addr=0x%x reg_hw=0x%x, reg_use=0x%x split=0x%p\n", + __func__, serdes_split->dev->name, + chip_split->chip_addr, serdes->reg_hw, + serdes->reg_use, serdes_split); + + chip_split->chip_addr = serdes->reg_hw; + + if (serdes_split && serdes_split->chip_data->split_ops && + serdes_split->chip_data->split_ops->select) + ret = serdes_split->chip_data->split_ops->select(serdes_split, link); + + if (serdes->chip_data->split_ops && + serdes->chip_data->split_ops->set_i2c_addr) + serdes->chip_data->split_ops->set_i2c_addr(serdes, + reg_use, link); + + if (serdes_split && serdes_split->chip_data->split_ops && + serdes_split->chip_data->split_ops->select) + ret = serdes_split->chip_data->split_ops->select(serdes_split, + SER_SPLITTER_MODE); + + chip_split->chip_addr = serdes->reg_use; + + serdes_i2c_set_sequence(serdes); + + return ret; +} + +static int serdes_i2c_probe(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev); + struct serdes_bridge *serdes_bridge = NULL; + struct serdes_bridge_split *serdes_bridge_split = NULL; + struct serdes_pinctrl *serdes_pinctrl = NULL; + int ret; + + ret = i2c_set_chip_offset_len(dev, 2); + if (ret) + return ret; + + serdes->dev = dev; + serdes->chip_data = (struct serdes_chip_data *)dev_get_driver_data(dev); + serdes->type = serdes->chip_data->serdes_type; + + SERDES_DBG_MFD("serdes %s %s probe start serdes=%p\n", + serdes->dev->name, serdes->chip_data->name, serdes); + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vpower-supply", + &serdes->vpower_supply); + if (ret && ret != -ENOENT) + SERDES_DBG_MFD("%s: Cannot get power supply: %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "enable-gpios", 0, + &serdes->enable_gpio, GPIOD_IS_OUT); + if (ret) + SERDES_DBG_MFD("%s: failed to get enable gpio: %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "lock-gpios", 0, &serdes->lock_gpio, + GPIOD_IS_IN); + if (ret) + SERDES_DBG_MFD("%s: failed to get lock gpio: %d\n", + __func__, ret); + + ret = gpio_request_by_name(dev, "err-gpios", 0, &serdes->err_gpio, + GPIOD_IS_IN); + if (ret) + SERDES_DBG_MFD("%s: failed to err gpio: %d\n", + __func__, ret); + + if (serdes->chip_data->serdes_type == TYPE_OTHER) { + SERDES_DBG_MFD("TYPE_OTHER just need only init i2c\n"); + serdes_i2c_init(serdes); + return 0; + } + + ret = serdes_get_init_seq(serdes); + if (ret) + return ret; + + if (serdes->chip_data->serdes_type == TYPE_SER) + serdes_i2c_init(serdes); + + if (serdes->chip_data->bridge_ops) { + serdes_bridge = calloc(1, sizeof(*serdes_bridge)); + if (!serdes_bridge) + return -ENOMEM; + serdes->serdes_bridge = serdes_bridge; + + serdes_bridge_split = calloc(1, sizeof(*serdes_bridge_split)); + if (!serdes_bridge_split) + return -ENOMEM; + serdes->serdes_bridge_split = serdes_bridge_split; + } + + serdes_pinctrl = calloc(1, sizeof(*serdes_pinctrl)); + if (!serdes_pinctrl) + return -ENOMEM; + + serdes->serdes_pinctrl = serdes_pinctrl; + ret = serdes_pinctrl_register(dev, serdes); + if (ret) + return ret; + + serdes->id_serdes_bridge_split = dev_read_u32_default(dev, "id-serdes-bridge-split", 0); + if ((serdes->id_serdes_bridge_split < MAX_NUM_SERDES_SPLIT) && (serdes->type == TYPE_SER)) { + g_serdes_ser_split[serdes->id_serdes_bridge_split] = serdes; + SERDES_DBG_MFD("%s: %s-%s g_serdes_split[%d]=0x%p\n", __func__, + serdes->dev->name, serdes->chip_data->name, + serdes->id_serdes_bridge_split, serdes); + } + + serdes->reg_hw = dev_read_u32_default(dev, "reg-hw", 0); + serdes->reg_use = dev_read_u32_default(dev, "reg", 0); + serdes->link_use = dev_read_u32_default(dev, "link", 0); + serdes->id_serdes_panel_split = dev_read_u32_default(dev, "id-serdes-panel-split", 0); + + if ((serdes->id_serdes_panel_split) && (serdes->type == TYPE_DES)) { + serdes->g_serdes_bridge_split = g_serdes_ser_split[serdes->id_serdes_panel_split]; + SERDES_DBG_MFD("%s: id=%d p=0x%p\n", __func__, + serdes->id_serdes_panel_split, + serdes->g_serdes_bridge_split); + } + + if (serdes->reg_hw) { + SERDES_DBG_MFD("%s: %s change i2c addr from 0x%x to 0x%x\n", + __func__, dev->name, + serdes->reg_hw, serdes->reg_use); + serdes_set_i2c_address(serdes, serdes->reg_hw, + serdes->reg_use, serdes->link_use); + } + + printf("%s %s %s successful\n", + __func__, + serdes->dev->name, + serdes->chip_data->name); + + return 0; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) + { .compatible = "rohm,bu18tl82", + .data = (ulong)&serdes_bu18tl82_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) + { .compatible = "rohm,bu18rl82", + .data = (ulong)&serdes_bu18rl82_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) + { .compatible = "maxim,max96745", + .data = (ulong)&serdes_max96745_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) + { .compatible = "maxim,max96755", + .data = (ulong)&serdes_max96755_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789) + { .compatible = "maxim,max96789", + .data = (ulong)&serdes_max96789_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) + { .compatible = "rockchip,rkx111", + .data = (ulong)&serdes_rkx111_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) + { .compatible = "maxim,max96752", + .data = (ulong)&serdes_max96752_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) + { .compatible = "maxim,max96772", + .data = (ulong)&serdes_max96772_data }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121) + { .compatible = "rockchip,rkx121", + .data = (ulong)&serdes_rkx121_data }, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_i2c) = { + .name = "serdes-i2c", + .id = UCLASS_MISC, + .of_match = serdes_of_match, + .probe = serdes_i2c_probe, + .bind = dm_scan_fdt_dev, + .priv_auto_alloc_size = sizeof(struct serdes), +}; diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-panel-split.c b/u-boot/drivers/video/drm/display-serdes/serdes-panel-split.c new file mode 100644 index 0000000000..34891c0b58 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-panel-split.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-panel.c -- display panel for different serdes chips + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static void serdes_panel_split_init(struct serdes *serdes) +{ + if (serdes->vpower_supply) + regulator_set_enable(serdes->vpower_supply, true); + + if (dm_gpio_is_valid(&serdes->enable_gpio)) + dm_gpio_set_value(&serdes->enable_gpio, 1); + + mdelay(5); + + if (serdes->chip_data->panel_ops->init) + serdes->chip_data->panel_ops->init(serdes); + + if (serdes->chip_data->serdes_type == TYPE_DES) + serdes_i2c_set_sequence(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_split_prepare(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->prepare) + serdes->chip_data->panel_ops->prepare(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_split_unprepare(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->unprepare) + serdes->chip_data->panel_ops->unprepare(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_split_enable(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->enable) + serdes->chip_data->panel_ops->enable(serdes); + + serdes_panel_split_init(serdes); + + if (serdes->serdes_panel_split->backlight) + backlight_enable(serdes->serdes_panel_split->backlight); + + if (serdes->chip_data->panel_ops->backlight_enable) + serdes->chip_data->panel_ops->backlight_enable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_split_disable(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->backlight_disable) + serdes->chip_data->panel_ops->backlight_disable(serdes); + + if (serdes->serdes_panel_split->backlight) + backlight_disable(serdes->serdes_panel_split->backlight); + + if (serdes->chip_data->panel_ops->disable) + serdes->chip_data->panel_ops->disable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static struct rockchip_panel_funcs serdes_panel_split_ops = { + .prepare = serdes_panel_split_prepare, + .unprepare = serdes_panel_split_unprepare, + .enable = serdes_panel_split_enable, + .disable = serdes_panel_split_disable, +}; + +static int serdes_panel_split_probe(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + struct serdes_panel_split *serdes_panel_split = NULL; + struct rockchip_panel *panel; + int ret; + + SERDES_DBG_MFD("%s: %s %s start\n", __func__, serdes->dev->name, + serdes->chip_data->name); + + if (!serdes->chip_data->panel_ops) { + printf("%s %s no panel ops\n", + __func__, serdes->chip_data->name); + return -1; + } + + if (serdes->chip_data->serdes_type != TYPE_DES) + printf("%s warning: this chip is not des type\n", __func__); + + serdes_panel_split = calloc(1, sizeof(*serdes_panel_split)); + if (!serdes_panel_split) + return -ENOMEM; + + serdes->serdes_panel_split = serdes_panel_split; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", + &serdes->serdes_panel_split->backlight); + if (ret && ret != -ENOENT) + printf("%s: Cannot get backlight: %d\n", __func__, ret); + + panel = calloc(1, sizeof(*panel)); + if (!panel) + return -ENOMEM; + + ret = serdes_get_init_seq(serdes); + if (ret) + goto free_panel; + + dev->driver_data = (ulong)panel; + panel->dev = dev; + panel->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + panel->funcs = &serdes_panel_split_ops; + + serdes->serdes_panel_split->panel = panel; + + printf("%s %s successful, version %s\n", + __func__, + serdes->dev->name, + SERDES_UBOOT_DISPLAY_VERSION); + + return 0; + +free_panel: + free(panel); + + return ret; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) + { .compatible = "maxim,max96752-panel-split",}, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) + { .compatible = "maxim,max96772-panel-split",}, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121) + { .compatible = "rockchip,rkx121-panel-split",}, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_panel_split) = { + .name = "serdes-panel-split", + .id = UCLASS_PANEL, + .of_match = serdes_of_match, + .probe = serdes_panel_split_probe, + .priv_auto_alloc_size = sizeof(struct serdes_panel_split), +}; diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-panel.c b/u-boot/drivers/video/drm/display-serdes/serdes-panel.c new file mode 100644 index 0000000000..4fea21bb48 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-panel.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-panel.c -- display panel for different serdes chips + * + * Copyright (c) 2023 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static void serdes_panel_init(struct serdes *serdes) +{ + if (serdes->vpower_supply) + regulator_set_enable(serdes->vpower_supply, true); + + if (dm_gpio_is_valid(&serdes->enable_gpio)) + dm_gpio_set_value(&serdes->enable_gpio, 1); + + mdelay(5); + + if (serdes->chip_data->panel_ops->init) + serdes->chip_data->panel_ops->init(serdes); + + if (serdes->chip_data->serdes_type == TYPE_DES) + serdes_i2c_set_sequence(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_prepare(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->prepare) + serdes->chip_data->panel_ops->prepare(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_unprepare(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->unprepare) + serdes->chip_data->panel_ops->unprepare(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_enable(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->enable) + serdes->chip_data->panel_ops->enable(serdes); + + serdes_panel_init(serdes); + + if (serdes->serdes_panel->backlight) + backlight_enable(serdes->serdes_panel->backlight); + + if (serdes->chip_data->panel_ops->backlight_enable) + serdes->chip_data->panel_ops->backlight_enable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static void serdes_panel_disable(struct rockchip_panel *panel) +{ + struct udevice *dev = panel->dev; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->panel_ops->backlight_disable) + serdes->chip_data->panel_ops->backlight_disable(serdes); + + if (serdes->serdes_panel->backlight) + backlight_disable(serdes->serdes_panel->backlight); + + if (serdes->chip_data->panel_ops->disable) + serdes->chip_data->panel_ops->disable(serdes); + + SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, + serdes->chip_data->name); +} + +static struct rockchip_panel_funcs serdes_panel_ops = { + .prepare = serdes_panel_prepare, + .unprepare = serdes_panel_unprepare, + .enable = serdes_panel_enable, + .disable = serdes_panel_disable, +}; + +static int serdes_panel_probe(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + struct serdes_panel *serdes_panel = NULL; + struct rockchip_panel *panel; + int ret; + + SERDES_DBG_MFD("%s: %s %s start\n", __func__, serdes->dev->name, + serdes->chip_data->name); + + if (!serdes->chip_data->panel_ops) { + printf("%s %s no panel ops\n", + __func__, serdes->chip_data->name); + return -1; + } + + if (serdes->chip_data->serdes_type != TYPE_DES) + printf("warning: this chip is not des type\n"); + + serdes_panel = calloc(1, sizeof(*serdes_panel)); + if (!serdes_panel) + return -ENOMEM; + + serdes->serdes_panel = serdes_panel; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", + &serdes->serdes_panel->backlight); + if (ret && ret != -ENOENT) + printf("%s: Cannot get backlight: %d\n", __func__, ret); + + panel = calloc(1, sizeof(*panel)); + if (!panel) + return -ENOMEM; + + ret = serdes_get_init_seq(serdes); + if (ret) + goto free_panel; + + dev->driver_data = (ulong)panel; + panel->dev = dev; + panel->bus_format = MEDIA_BUS_FMT_RGB888_1X24; + panel->funcs = &serdes_panel_ops; + + serdes->serdes_panel->panel = panel; + + printf("%s %s successful, version %s\n", + __func__, + serdes->dev->name, + SERDES_UBOOT_DISPLAY_VERSION); + + return 0; + +free_panel: + free(panel); + + return ret; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96752) + { .compatible = "maxim,max96752-panel",}, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) + { .compatible = "maxim,max96772-panel",}, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX121) + { .compatible = "rockchip,rkx121-panel",}, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_panel) = { + .name = "serdes-panel", + .id = UCLASS_PANEL, + .of_match = serdes_of_match, + .probe = serdes_panel_probe, + .priv_auto_alloc_size = sizeof(struct serdes_panel), +}; diff --git a/u-boot/drivers/video/drm/display-serdes/serdes-pinctrl.c b/u-boot/drivers/video/drm/display-serdes/serdes-pinctrl.c new file mode 100644 index 0000000000..5fe1537029 --- /dev/null +++ b/u-boot/drivers/video/drm/display-serdes/serdes-pinctrl.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * serdes-pinctrl.c -- serdes pin control driver. + * + * Copyright (c) 2023-2028 Rockchip Electronics Co. Ltd. + * + * Author: luowei + */ + +#include "core.h" + +static const struct pinconf_param serdes_conf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 }, + { "bias-bus-hold", PIN_CONFIG_BIAS_BUS_HOLD, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, + { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 1 }, + { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, + { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 }, + { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 }, + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, +}; + +static int serdes_pinctrl_get_pins_count(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_info->num_pins) + return serdes->chip_data->pinctrl_info->num_pins; + else + return 0; +} + +static const char *serdes_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_info->pins[selector].name) + return serdes->chip_data->pinctrl_info->pins[selector].name; + else + return "unknow-pin"; +} + +static int serdes_pinctrl_get_groups_count(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_info->num_groups) + return serdes->chip_data->pinctrl_info->num_groups; + else + return 0; +} + +static const char *serdes_pinctrl_get_group_name(struct udevice *dev, + unsigned int selector) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_info->groups[selector].name) + return serdes->chip_data->pinctrl_info->groups[selector].name; + else + return "unknow-group"; +} + +static int serdes_pinctrl_get_functions_count(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_info->num_functions) + return serdes->chip_data->pinctrl_info->num_functions; + else + return 0; +} + +static const char *serdes_pinctrl_get_function_name(struct udevice *dev, + unsigned int selector) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_info->functions[selector].name) + return serdes->chip_data->pinctrl_info->functions[selector].name; + else + return "unknow-function"; +} + +static int serdes_pinmux_set_mux(struct udevice *dev, + unsigned int pin_selector, + unsigned int func_selector) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + int ret = 0; + + if (serdes->chip_data->pinctrl_ops->pinmux_set) + ret = serdes->chip_data->pinctrl_ops->pinmux_set(serdes, + pin_selector, func_selector); + + SERDES_DBG_MFD("%s: %s pin=%d,func=%d\n", __func__, + serdes->chip_data->name, pin_selector, func_selector); + return ret; +} + +static int serdes_pinmux_group_set_mux(struct udevice *dev, + unsigned int group_selector, + unsigned int func_selector) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + int ret = 0; + + if (serdes->chip_data->pinctrl_ops->pinmux_group_set) + ret = serdes->chip_data->pinctrl_ops->pinmux_group_set(serdes, + group_selector, func_selector); + + SERDES_DBG_MFD("%s: %s function=%d,group=%d\n", __func__, + serdes->chip_data->name, func_selector, group_selector); + return ret; +} + +static int serdes_pinconf_set(struct udevice *dev, unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + int ret = 0; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_ops->pinconf_set) + ret = serdes->chip_data->pinctrl_ops->pinconf_set(serdes, + pin_selector, param, argument); + + SERDES_DBG_MFD("serdes: pin = %d (%s), param = %d, arg = %d\n", + pin_selector, + serdes_pinctrl_get_pin_name(dev, pin_selector), + param, argument); + + return ret; +} + +static int serdes_pinconf_group_set(struct udevice *dev, + unsigned int group_selector, + unsigned int param, unsigned int argument) +{ + int ret = 0; + struct serdes *serdes = dev_get_priv(dev->parent); + + if (serdes->chip_data->pinctrl_ops->pinconf_group_set) + ret = serdes->chip_data->pinctrl_ops->pinconf_group_set(serdes, + group_selector, param, argument); + + SERDES_DBG_MFD("serdes: group = %d (%s), param = %d, arg = %d\n", + group_selector, + serdes_pinctrl_get_group_name(dev, group_selector), + param, argument); + return ret; +} + +static struct pinctrl_ops serdes_pinctrl_ops = { + .get_pins_count = serdes_pinctrl_get_pins_count, + .get_pin_name = serdes_pinctrl_get_pin_name, + .get_groups_count = serdes_pinctrl_get_groups_count, + .get_group_name = serdes_pinctrl_get_group_name, + .get_functions_count = serdes_pinctrl_get_functions_count, + .get_function_name = serdes_pinctrl_get_function_name, + .set_state = pinctrl_generic_set_state, + .pinmux_set = serdes_pinmux_set_mux, + .pinmux_group_set = serdes_pinmux_group_set_mux, + .pinconf_num_params = ARRAY_SIZE(serdes_conf_params), + .pinconf_params = serdes_conf_params, + .pinconf_set = serdes_pinconf_set, + .pinconf_group_set = serdes_pinconf_group_set, +}; + +int serdes_pinctrl_probe(struct udevice *dev) +{ + struct serdes *serdes = dev_get_priv(dev->parent); + struct serdes_pinctrl *serdes_pinctrl = serdes->serdes_pinctrl; + int ret = 0; + + SERDES_DBG_MFD("%s: %s %s start\n", __func__, dev->name, + serdes->chip_data->name); + + serdes_pinctrl->parent = serdes; + + ret = serdes_gpio_register(dev, serdes); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id serdes_of_match[] = { +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) + { .compatible = "rohm,bu18tl82-pinctrl" }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) + { .compatible = "rohm,bu18rl82-pinctrl" }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) + { .compatible = "maxim,max96745-pinctrl", }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) + { .compatible = "maxim,max96755-pinctrl" }, +#endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) + { .compatible = "rockchip,rkx111-pinctrl" }, +#endif + { } +}; + +U_BOOT_DRIVER(serdes_pinctrl) = { + .name = "serdes-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = serdes_of_match, + .probe = serdes_pinctrl_probe, + .ops = &serdes_pinctrl_ops, + .priv_auto_alloc_size = sizeof(struct serdes_pinctrl), +}; diff --git a/u-boot/drivers/video/drm/drm_of.c b/u-boot/drivers/video/drm/drm_of.c new file mode 100644 index 0000000000..d79f6da271 --- /dev/null +++ b/u-boot/drivers/video/drm/drm_of.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2023 Rockchip Electronics Co., Ltd + * + */ +#include +#include + +#include "drm_of.h" + +enum drm_of_lvds_pixels { + DRM_OF_LVDS_EVEN = BIT(0), + DRM_OF_LVDS_ODD = BIT(1), + DRM_OF_LVDS_LEFT = BIT(2), + DRM_OF_LVDS_RIGHT = BIT(3), +}; + +static int +drm_of_lvds_get_port_pixels_type(const struct device_node *port_node) +{ + ofnode node = np_to_ofnode(port_node); + + bool even_pixels = + ofnode_read_bool(node, "dual-lvds-even-pixels"); + bool odd_pixels = + ofnode_read_bool(node, "dual-lvds-odd-pixels"); + bool left_pixels = + ofnode_read_bool(node, "dual-lvds-left-pixels"); + bool right_pixels = + ofnode_read_bool(node, "dual-lvds-right-pixels"); + + return (even_pixels ? DRM_OF_LVDS_EVEN : 0) | + (odd_pixels ? DRM_OF_LVDS_ODD : 0) | + (left_pixels ? DRM_OF_LVDS_LEFT : 0) | + (right_pixels ? DRM_OF_LVDS_RIGHT : 0); +} + +static int +drm_of_lvds_get_remote_pixels_type(const struct device_node *port_node) +{ + ofnode node = np_to_ofnode(port_node); + ofnode endpoint; + uint phandle; + int pixels_type = -EPIPE; + + ofnode_for_each_subnode(endpoint, node) { + int current_pt; + const char *name; + + if (!ofnode_is_available(endpoint)) + continue; + + name = ofnode_get_name(endpoint); + if (strncmp(name, "endpoint", 8) != 0) + continue; + + if (ofnode_read_u32(endpoint, "remote-endpoint", &phandle)) + continue; + + endpoint = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(endpoint) || !ofnode_is_available(endpoint)) + continue; + + endpoint = ofnode_get_parent(endpoint); + if (!ofnode_valid(endpoint)) + continue; + + current_pt = + drm_of_lvds_get_port_pixels_type(ofnode_to_np(endpoint + )); + if (pixels_type < 0) + pixels_type = current_pt; + + /* + * Sanity check, ensure that all remote endpoints have the same + * pixel type. We may lift this restriction later if we need to + * support multiple sinks with different dual-link + * configurations by passing the endpoints explicitly to + * drm_of_lvds_get_dual_link_pixel_order(). + */ + if (!current_pt || pixels_type != current_pt) + return -EINVAL; + } + + return pixels_type; +} + +/** + * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order + * @port1: First DT port node of the Dual-link LVDS source + * @port2: Second DT port node of the Dual-link LVDS source + * + * An LVDS dual-link connection is made of two links, the two link can transmit + * odd pixels and even pixels independently, or the two link can also transmit + * left pixels and right pixels independently. This function returns for two + * ports of an LVDS dual-link source, based on the requirements of the connected + * sink. + * + * The pixel order is determined from the dual-lvds-even-pixels + + * dual-lvds-odd-pixels or dual-lvds-left-pixels + dual-lvds-right-pixels + * properties in the sink's DT port nodes. If those + * properties are not present, or if their usage is not valid, this function + * returns -EINVAL. + * + * If either port is not connected, this function returns -EPIPE. + * + * @port1 and @port2 are typically DT sibling nodes, but may have different + * parents when, for instance, two separate LVDS encoders carry the even and + * odd pixels. + * + * Return: + * * DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS - @port1 carries even pixels and @port2 + * carries odd pixels + * * DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS - @port1 carries odd pixels and @port2 + * carries even pixels + * * DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS - @port1 carries left pixels and + * @port2 carries right pixels + * * DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS - @port1 carries right pixels and + * @port2 carries left pixels + + * * -EINVAL - @port1 and @port2 are not connected to a dual-link LVDS sink, or + * the sink configuration is invalid + * * -EPIPE - when @port1 or @port2 are not connected + */ +int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, + const struct device_node *port2) +{ + int remote_p1_pt, remote_p2_pt; + + if (!port1 || !port2) + return -EINVAL; + + remote_p1_pt = drm_of_lvds_get_remote_pixels_type(port1); + if (remote_p1_pt < 0) + return remote_p1_pt; + + remote_p2_pt = drm_of_lvds_get_remote_pixels_type(port2); + if (remote_p2_pt < 0) + return remote_p2_pt; + + /* + * A valid dual-lVDS bus is found when one remote port is marked with + * "dual-lvds-even-pixels" or "dual-lvds-left-pixels", and the other + * remote port is marked with "dual-lvds-odd-pixels"or + * "dual-lvds-right-pixels", bail out if the markers are not right. + */ + if ((remote_p1_pt + remote_p2_pt != + DRM_OF_LVDS_EVEN + DRM_OF_LVDS_ODD) && + (remote_p1_pt + remote_p2_pt != + DRM_OF_LVDS_LEFT + DRM_OF_LVDS_RIGHT)) + return -EINVAL; + + if (remote_p1_pt == DRM_OF_LVDS_EVEN) + return DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; + else if (remote_p1_pt == DRM_OF_LVDS_ODD) + return DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS; + else if (remote_p1_pt == DRM_OF_LVDS_LEFT) + return DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS; + else + return DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS; +} diff --git a/u-boot/drivers/video/drm/drm_of.h b/u-boot/drivers/video/drm/drm_of.h new file mode 100644 index 0000000000..f0cb3460ca --- /dev/null +++ b/u-boot/drivers/video/drm/drm_of.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2023 Rockchip Electronics Co., Ltd + * + */ +#ifndef __DRM_OF_H__ +#define __DRM_OF_H__ + +#include +#include + +/** + * enum drm_lvds_dual_link_pixels - Pixel order of an LVDS dual-link connection + * @DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: Even pixels are expected to be + * generated from the first port, odd pixels from the second port + * @DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: Odd pixels are expected to be + * generated from the first port, even pixels from the second port + * @DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS: Left pixels are expected to be + * generated from the first port, right pixels from the second port + * @DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS: Right pixels are expected to be + * generated from the first port, left pixels from the second port + */ +enum drm_lvds_dual_link_pixels { + DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS = 0, + DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS = 1, + DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS = 2, + DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS = 3, +}; + +int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, + const struct device_node *port2); + +#endif diff --git a/u-boot/drivers/video/drm/dw_hdmi.c b/u-boot/drivers/video/drm/dw_hdmi.c index a30e4d526c..882bae2d6e 100644 --- a/u-boot/drivers/video/drm/dw_hdmi.c +++ b/u-boot/drivers/video/drm/dw_hdmi.c @@ -181,6 +181,7 @@ struct dw_hdmi { bool cable_plugin; bool sink_is_hdmi; bool sink_has_audio; + bool force_output; void *regs; void *grf; void *gpio_base; @@ -878,7 +879,7 @@ static int rockchip_dw_hdmi_scrambling_enable(struct dw_hdmi *hdmi, drm_scdc_readb(&hdmi->adap, SCDC_TMDS_CONFIG, &stat); - if (stat < 0) { + if (stat < 0 && !hdmi->force_output) { debug("Failed to read tmds config\n"); return false; } @@ -1168,7 +1169,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, } /* Scrambling Control */ - if (hdmi_info->scdc.supported) { + if (hdmi_info->scdc.supported || hdmi->force_output) { if (vmode->mtmdsclock > 340000000 || (hdmi_info->scdc.scrambling.low_rates && hdmi->scramble_low_rates)) { @@ -2519,6 +2520,20 @@ int rockchip_dw_hdmi_disable(struct rockchip_connector *conn, struct display_sta return 0; } +static void rockchip_dw_hdmi_mode_valid(struct dw_hdmi *hdmi) +{ + struct hdmi_edid_data *edid_data = &hdmi->edid_data; + int i; + + for (i = 0; i < edid_data->modes; i++) { + if (edid_data->mode_buf[i].invalid) + continue; + + if (edid_data->mode_buf[i].clock > 600000) + edid_data->mode_buf[i].invalid = true; + } +} + int rockchip_dw_hdmi_get_timing(struct rockchip_connector *conn, struct display_state *state) { int ret, i, vic; @@ -2555,6 +2570,7 @@ int rockchip_dw_hdmi_get_timing(struct rockchip_connector *conn, struct display_ conn_state->disp_info = rockchip_get_disp_info(conn_state->type, hdmi->id); #endif drm_rk_filter_whitelist(&hdmi->edid_data); + rockchip_dw_hdmi_mode_valid(hdmi); if (hdmi->phy.ops->mode_valid) hdmi->phy.ops->mode_valid(conn, hdmi, state); drm_mode_max_resolution_filter(&hdmi->edid_data, @@ -2586,8 +2602,12 @@ int rockchip_dw_hdmi_get_timing(struct rockchip_connector *conn, struct display_ *mode = *hdmi->edid_data.preferred_mode; hdmi->vic = drm_match_cea_mode(mode); - if (state->force_output) + if (state->force_output) { + hdmi->force_output = state->force_output; + hdmi->sink_is_hdmi = true; + hdmi->sink_has_audio = true; bus_format = state->force_bus_format; + } conn_state->bus_format = bus_format; hdmi->hdmi_data.enc_in_bus_format = bus_format; hdmi->hdmi_data.enc_out_bus_format = bus_format; diff --git a/u-boot/drivers/video/drm/dw_hdmi_qp.c b/u-boot/drivers/video/drm/dw_hdmi_qp.c index 70ea921bc0..c25c5b96db 100644 --- a/u-boot/drivers/video/drm/dw_hdmi_qp.c +++ b/u-boot/drivers/video/drm/dw_hdmi_qp.c @@ -18,6 +18,7 @@ #include #include #include +#include "rockchip_bridge.h" #include "rockchip_display.h" #include "rockchip_crtc.h" #include "rockchip_connector.h" @@ -1111,9 +1112,15 @@ int dw_hdmi_detect_hotplug(struct dw_hdmi_qp *hdmi, struct display_state *state) { struct connector_state *conn_state = &state->conn_state; + struct rockchip_connector *conn = conn_state->connector; int ret; ret = hdmi->phy.ops->read_hpd(hdmi->rk_hdmi); + if (!ret) { + if (conn->bridge) + ret = rockchip_bridge_detect(conn->bridge); + } + if (ret || state->force_output) { if (!hdmi->id) conn_state->output_if |= VOP_OUTPUT_IF_HDMI0; @@ -1209,8 +1216,80 @@ void rockchip_dw_hdmi_qp_deinit(struct rockchip_connector *conn, struct display_ free(hdmi); } +static void rockchip_dw_hdmi_qp_config_output(struct rockchip_connector *conn, + struct display_state *state) +{ + struct connector_state *conn_state = &state->conn_state; + struct drm_display_mode *mode = &conn_state->mode; + struct dw_hdmi_qp *hdmi = conn->data; + unsigned int bus_format; + unsigned long enc_out_encoding; + struct overscan *overscan = &conn_state->overscan; + + dw_hdmi_qp_selete_output(&hdmi->edid_data, conn, &bus_format, + overscan, hdmi->dev_type, + hdmi->output_bus_format_rgb, hdmi->rk_hdmi, + state); + + *mode = *hdmi->edid_data.preferred_mode; + hdmi->vic = drm_match_cea_mode(mode); + + printf("mode:%dx%d bus_format:0x%x\n", mode->hdisplay, mode->vdisplay, bus_format); + conn_state->bus_format = bus_format; + hdmi->hdmi_data.enc_in_bus_format = bus_format; + hdmi->hdmi_data.enc_out_bus_format = bus_format; + + switch (bus_format) { + case MEDIA_BUS_FMT_YUYV10_1X20: + conn_state->bus_format = MEDIA_BUS_FMT_YUYV10_1X20; + hdmi->hdmi_data.enc_in_bus_format = + MEDIA_BUS_FMT_YUYV10_1X20; + conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV422; + break; + case MEDIA_BUS_FMT_YUYV8_1X16: + conn_state->bus_format = MEDIA_BUS_FMT_YUYV8_1X16; + hdmi->hdmi_data.enc_in_bus_format = + MEDIA_BUS_FMT_YUYV8_1X16; + conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV422; + break; + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV420; + break; + } + + if (hdmi->vic == 6 || hdmi->vic == 7 || hdmi->vic == 21 || + hdmi->vic == 22 || hdmi->vic == 2 || hdmi->vic == 3 || + hdmi->vic == 17 || hdmi->vic == 18) + enc_out_encoding = V4L2_YCBCR_ENC_601; + else + enc_out_encoding = V4L2_YCBCR_ENC_709; + + if (enc_out_encoding == V4L2_YCBCR_ENC_BT2020) + conn_state->color_space = V4L2_COLORSPACE_BT2020; + else if (bus_format == MEDIA_BUS_FMT_RGB888_1X24 || + bus_format == MEDIA_BUS_FMT_RGB101010_1X30) + conn_state->color_space = V4L2_COLORSPACE_DEFAULT; + else if (enc_out_encoding == V4L2_YCBCR_ENC_709) + conn_state->color_space = V4L2_COLORSPACE_REC709; + else + conn_state->color_space = V4L2_COLORSPACE_SMPTE170M; +} + int rockchip_dw_hdmi_qp_prepare(struct rockchip_connector *conn, struct display_state *state) { + struct connector_state *conn_state = &state->conn_state; + struct drm_display_mode *mode = &conn_state->mode; + struct dw_hdmi_qp *hdmi = conn->data; + + if (!hdmi->edid_data.preferred_mode && conn->bridge) { + drm_add_hdmi_modes(&hdmi->edid_data, mode); + drm_mode_sort(&hdmi->edid_data); + hdmi->sink_is_hdmi = true; + hdmi->sink_has_audio = true; + rockchip_dw_hdmi_qp_config_output(conn, state); + } + return 0; } @@ -1284,12 +1363,8 @@ static int _rockchip_dw_hdmi_qp_get_timing(struct rockchip_connector *conn, { int i; struct connector_state *conn_state = &state->conn_state; - struct drm_display_mode *mode = &conn_state->mode; struct dw_hdmi_qp *hdmi = conn->data; struct edid *edid = (struct edid *)conn_state->edid; - unsigned int bus_format; - unsigned long enc_out_encoding; - struct overscan *overscan = &conn_state->overscan; const u8 def_modes_vic[6] = {4, 16, 2, 17, 31, 19}; if (!hdmi) @@ -1323,54 +1398,8 @@ static int _rockchip_dw_hdmi_qp_get_timing(struct rockchip_connector *conn, drm_mode_vrefresh(&hdmi->edid_data.mode_buf[i]); drm_mode_sort(&hdmi->edid_data); - dw_hdmi_qp_selete_output(&hdmi->edid_data, conn, &bus_format, - overscan, hdmi->dev_type, - hdmi->output_bus_format_rgb, hdmi->rk_hdmi, - state); - *mode = *hdmi->edid_data.preferred_mode; - hdmi->vic = drm_match_cea_mode(mode); - - printf("mode:%dx%d bus_format:0x%x\n", mode->hdisplay, mode->vdisplay, bus_format); - conn_state->bus_format = bus_format; - hdmi->hdmi_data.enc_in_bus_format = bus_format; - hdmi->hdmi_data.enc_out_bus_format = bus_format; - - switch (bus_format) { - case MEDIA_BUS_FMT_YUYV10_1X20: - conn_state->bus_format = MEDIA_BUS_FMT_YUYV10_1X20; - hdmi->hdmi_data.enc_in_bus_format = - MEDIA_BUS_FMT_YUYV10_1X20; - conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV422; - break; - case MEDIA_BUS_FMT_YUYV8_1X16: - conn_state->bus_format = MEDIA_BUS_FMT_YUYV8_1X16; - hdmi->hdmi_data.enc_in_bus_format = - MEDIA_BUS_FMT_YUYV8_1X16; - conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV422; - break; - case MEDIA_BUS_FMT_UYYVYY8_0_5X24: - case MEDIA_BUS_FMT_UYYVYY10_0_5X30: - conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV420; - break; - } - - if (hdmi->vic == 6 || hdmi->vic == 7 || hdmi->vic == 21 || - hdmi->vic == 22 || hdmi->vic == 2 || hdmi->vic == 3 || - hdmi->vic == 17 || hdmi->vic == 18) - enc_out_encoding = V4L2_YCBCR_ENC_601; - else - enc_out_encoding = V4L2_YCBCR_ENC_709; - - if (enc_out_encoding == V4L2_YCBCR_ENC_BT2020) - conn_state->color_space = V4L2_COLORSPACE_BT2020; - else if (bus_format == MEDIA_BUS_FMT_RGB888_1X24 || - bus_format == MEDIA_BUS_FMT_RGB101010_1X30) - conn_state->color_space = V4L2_COLORSPACE_DEFAULT; - else if (enc_out_encoding == V4L2_YCBCR_ENC_709) - conn_state->color_space = V4L2_COLORSPACE_REC709; - else - conn_state->color_space = V4L2_COLORSPACE_SMPTE170M; + rockchip_dw_hdmi_qp_config_output(conn, state); return 0; } diff --git a/u-boot/drivers/video/drm/dw_mipi_dsi2.c b/u-boot/drivers/video/drm/dw_mipi_dsi2.c index fcd7cbe0ee..5882026c3c 100644 --- a/u-boot/drivers/video/drm/dw_mipi_dsi2.c +++ b/u-boot/drivers/video/drm/dw_mipi_dsi2.c @@ -272,6 +272,7 @@ struct dw_mipi_dsi2 { struct dw_mipi_dsi2 *slave; bool prepared; + bool auto_calc_mode; bool c_option; bool dsc_enable; bool scrambling_en; @@ -285,6 +286,7 @@ struct dw_mipi_dsi2 { u32 lanes; u32 format; u32 mode_flags; + u64 mipi_pixel_rate; struct mipi_dcphy dcphy; struct drm_display_mode mode; bool data_swap; @@ -551,6 +553,9 @@ static void dw_mipi_dsi2_ipi_set(struct dw_mipi_dsi2 *dsi2) dw_mipi_dsi2_ipi_color_coding_cfg(dsi2); + if (dsi2->auto_calc_mode) + return; + /* * if the controller is intended to operate in data stream mode, * no more steps are required. @@ -655,15 +660,27 @@ static void dw_mipi_dsi2_set_cmd_mode(struct dw_mipi_dsi2 *dsi2) static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2) { + u32 mode; + int ret; + dw_mipi_dsi2_ipi_set(dsi2); + if (dsi2->auto_calc_mode) { + dsi_write(dsi2, DSI2_MODE_CTRL, AUTOCALC_MODE); + ret = readl_poll_timeout(dsi2->base + DSI2_MODE_STATUS, + mode, mode == IDLE_MODE, + MODE_STATUS_TIMEOUT_US); + if (ret < 0) + printf("auto calculation training failed\n"); + } + if (dsi2->mode_flags & MIPI_DSI_MODE_VIDEO) dw_mipi_dsi2_set_vid_mode(dsi2); else dw_mipi_dsi2_set_data_stream_mode(dsi2); if (dsi2->slave) - dw_mipi_dsi2_enable(dsi2->slave); + dw_mipi_dsi2_enable(dsi2->slave); } static void dw_mipi_dsi2_disable(struct dw_mipi_dsi2 *dsi2) @@ -822,6 +839,8 @@ static int dw_mipi_dsi2_connector_init(struct rockchip_connector *conn, struct d dsi2->slave->master = dsi2; dsi2->lanes /= 2; + + dsi2->slave->auto_calc_mode = dsi2->auto_calc_mode; dsi2->slave->lanes = dsi2->lanes; dsi2->slave->format = dsi2->format; dsi2->slave->mode_flags = dsi2->mode_flags; @@ -981,8 +1000,7 @@ static void dw_mipi_dsi2_phy_clk_mode_cfg(struct dw_mipi_dsi2 *dsi2) static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) { - struct drm_display_mode *mode = &dsi2->mode; - u64 pixel_clk, ipi_clk, phy_hsclk, tmp; + u64 ipi_clk, phy_hsclk, tmp; /* * in DPHY mode, the phy_hstx_clk is exactly 1/16 the Lane high-speed @@ -996,8 +1014,7 @@ static void dw_mipi_dsi2_phy_ratio_cfg(struct dw_mipi_dsi2 *dsi2) phy_hsclk = DIV_ROUND_CLOSEST(dsi2->lane_hs_rate * MSEC_PER_SEC, 16); /* IPI_RATIO_MAN_CFG = PHY_HSTX_CLK / IPI_CLK */ - pixel_clk = mode->crtc_clock * MSEC_PER_SEC; - ipi_clk = pixel_clk / 4; + ipi_clk = dsi2->mipi_pixel_rate; tmp = DIV_ROUND_CLOSEST(phy_hsclk << 16, ipi_clk); dsi_write(dsi2, DSI2_PHY_IPI_RATIO_MAN_CFG, PHY_IPI_RATIO(tmp)); @@ -1033,6 +1050,10 @@ static void dw_mipi_dsi2_phy_init(struct dw_mipi_dsi2 *dsi2) { dw_mipi_dsi2_phy_mode_cfg(dsi2); dw_mipi_dsi2_phy_clk_mode_cfg(dsi2); + + if (dsi2->auto_calc_mode) + return; + dw_mipi_dsi2_phy_ratio_cfg(dsi2); dw_mipi_dsi2_lp2hs_or_hs2lp_cfg(dsi2); @@ -1092,7 +1113,7 @@ static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2) dw_mipi_dsi2_host_softrst(dsi2); dsi_write(dsi2, DSI2_PWR_UP, RESET); - dw_mipi_dsi2_work_mode(dsi2, MANUAL_MODE_EN); + dw_mipi_dsi2_work_mode(dsi2, dsi2->auto_calc_mode ? 0 : MANUAL_MODE_EN); dw_mipi_dsi2_phy_init(dsi2); dw_mipi_dsi2_tx_option_set(dsi2); dw_mipi_dsi2_irq_enable(dsi2, 0); @@ -1106,11 +1127,37 @@ static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2) dw_mipi_dsi2_pre_enable(dsi2->slave); } +static void dw_mipi_dsi2_get_mipi_pixel_clk(struct dw_mipi_dsi2 *dsi2, + struct crtc_state *s) +{ + struct drm_display_mode *mode = &dsi2->mode; + u8 k = dsi2->slave ? 2 : 1; + + /* 1.When MIPI works in uncompressed mode: + * (Video Timing Pixel Rate)/(4)=(MIPI Pixel ClockxK)=(dclk_out×K)=dclk_core + * 2.When MIPI works in compressed mode: + * MIPI Pixel Clock = cds_clk / 2 + * MIPI is configured as double channel display mode, K=2, otherwise K=1. + */ + if (dsi2->dsc_enable) { + dsi2->mipi_pixel_rate = s->dsc_cds_clk_rate / 2; + if (dsi2->slave) + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; + + return; + } + + dsi2->mipi_pixel_rate = (mode->crtc_clock * MSEC_PER_SEC) / (4 * k); + if (dsi2->slave) + dsi2->slave->mipi_pixel_rate = dsi2->mipi_pixel_rate; +} + static int dw_mipi_dsi2_connector_prepare(struct rockchip_connector *conn, struct display_state *state) { struct dw_mipi_dsi2 *dsi2 = dev_get_priv(conn->dev); struct connector_state *conn_state = &state->conn_state; + struct crtc_state *cstate = &state->crtc_state; unsigned long lane_rate; memcpy(&dsi2->mode, &conn_state->mode, sizeof(struct drm_display_mode)); @@ -1118,6 +1165,8 @@ static int dw_mipi_dsi2_connector_prepare(struct rockchip_connector *conn, memcpy(&dsi2->slave->mode, &dsi2->mode, sizeof(struct drm_display_mode)); + dw_mipi_dsi2_get_mipi_pixel_clk(dsi2, cstate); + lane_rate = dw_mipi_dsi2_get_lane_rate(dsi2); if (dsi2->dcphy.phy) dw_mipi_dsi2_set_hs_clk(dsi2, lane_rate); @@ -1192,7 +1241,9 @@ static int dw_mipi_dsi2_connector_mode_valid(struct rockchip_connector *conn, if (vm.hactive < min_pixels) vm.hactive = min_pixels; + memset(&conn_state->mode, 0, sizeof(struct drm_display_mode)); drm_display_mode_from_videomode(&vm, &conn_state->mode); + conn_state->mode.vrefresh = drm_mode_vrefresh(&conn_state->mode); return MODE_OK; } @@ -1240,6 +1291,7 @@ static int dw_mipi_dsi2_probe(struct udevice *dev) dsi2->pdata = pdata; dsi2->id = id; dsi2->data_swap = dev_read_bool(dsi2->dev, "rockchip,data-swap"); + dsi2->auto_calc_mode = dev_read_bool(dsi2->dev, "auto-calculation-mode"); rockchip_connector_bind(&dsi2->connector, dev, id, &dw_mipi_dsi2_connector_funcs, NULL, DRM_MODE_CONNECTOR_DSI); diff --git a/u-boot/drivers/video/drm/inno_mipi_phy.c b/u-boot/drivers/video/drm/inno_mipi_phy.c index 447aaec5e7..8a3741ec3e 100644 --- a/u-boot/drivers/video/drm/inno_mipi_phy.c +++ b/u-boot/drivers/video/drm/inno_mipi_phy.c @@ -93,6 +93,7 @@ #define T_HS_TRAIL_OFFSET 0x0020 #define T_HS_EXIT_OFFSET 0x0024 #define T_CLK_POST_OFFSET 0x0028 +#define T_CLK_POST_OFFSET_H 0x0040 #define T_WAKUP_H_OFFSET 0x0030 #define T_WAKUP_L_OFFSET 0x0034 #define T_CLK_PRE_OFFSET 0x0038 @@ -112,6 +113,8 @@ #define T_HS_EXIT(x) UPDATE(x, 4, 0) #define T_CLK_POST_MASK GENMASK(3, 0) #define T_CLK_POST(x) UPDATE(x, 3, 0) +#define T_CLK_POST_HI_MASK GENMASK(7, 6) +#define T_CLK_POST_HI(x) UPDATE(x, 7, 6) #define T_WAKUP_H_MASK GENMASK(1, 0) #define T_WAKUP_H(x) UPDATE(x, 1, 0) #define T_WAKUP_L_MASK GENMASK(7, 0) @@ -328,7 +331,9 @@ static void inno_mipi_dphy_timing_update(struct inno_mipi_dphy *inno, m = T_CLK_POST_MASK; v = T_CLK_POST(t->clk_post); inno_update_bits(inno, base + T_CLK_POST_OFFSET, m, v); - + m = T_CLK_POST_HI_MASK; + v = T_CLK_POST_HI(t->clk_post >> 4); + inno_update_bits(inno, base + T_CLK_POST_OFFSET_H, m, v); m = T_CLK_PRE_MASK; v = T_CLK_PRE(t->clk_pre); inno_update_bits(inno, base + T_CLK_PRE_OFFSET, m, v); diff --git a/u-boot/drivers/video/drm/libnsbmp.c b/u-boot/drivers/video/drm/libnsbmp.c new file mode 100644 index 0000000000..bbefb6707b --- /dev/null +++ b/u-boot/drivers/video/drm/libnsbmp.c @@ -0,0 +1,1369 @@ +/* + * Copyright 2006 Richard Wilson + * Copyright 2008 Sean Fox + * + * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +/** + * \file + * BMP decoding implementation + * + * This library decode windows bitmaps and icons from their disc images. + * + * The image format is described in several documents: + * https://msdn.microsoft.com/en-us/library/dd183391(v=vs.85).aspx + * http://www.fileformat.info/format/bmp/egff.htm + * https://en.wikipedia.org/wiki/BMP_file_format + * + * Despite the format being clearly defined many bitmaps found on the web are + * not compliant and this implementation attempts to cope with as many issues + * as possible rather than simply failing. + */ + +#include "libnsbmp.h" + +/* squashes unused variable compiler warnings */ +#define UNUSED(x) ((x)=(x)) + +/* BMP entry sizes */ +#define BMP_FILE_HEADER_SIZE 14 +#define ICO_FILE_HEADER_SIZE 6 +#define ICO_DIR_ENTRY_SIZE 16 + +/* the bitmap information header types (encoded as lengths) */ +#define BITMAPCOREHEADER 12 + +#ifdef WE_NEED_INT8_READING_NOW +static inline int8_t read_int8(uint8_t *data, unsigned int o) { + return (int8_t) data[o]; +} +#endif + +static inline uint8_t read_uint8(uint8_t *data, unsigned int o) { + return (uint8_t) data[o]; +} + +static inline int16_t read_int16(uint8_t *data, unsigned int o) { + return (int16_t) (data[o] | (data[o+1] << 8)); +} + +static inline uint16_t read_uint16(uint8_t *data, unsigned int o) { + return (uint16_t) (data[o] | (data[o+1] << 8)); +} + +static inline int32_t read_int32(uint8_t *data, unsigned int o) { + return (int32_t) ((unsigned)data[o] | + ((unsigned)data[o+1] << 8) | + ((unsigned)data[o+2] << 16) | + ((unsigned)data[o+3] << 24)); +} + +static inline uint32_t read_uint32(uint8_t *data, unsigned int o) { + return (uint32_t) ((unsigned)data[o] | + ((unsigned)data[o+1] << 8) | + ((unsigned)data[o+2] << 16) | + ((unsigned)data[o+3] << 24)); +} + + +/** + * Parse the bitmap info header + */ +static bmp_result bmp_info_header_parse(bmp_image *bmp, uint8_t *data) +{ + uint32_t header_size; + uint32_t i; + uint8_t j; + int32_t width, height; + uint8_t palette_size; + unsigned int flags = 0; + + /* must be at least enough data for a core header */ + if (bmp->buffer_size < (BMP_FILE_HEADER_SIZE + BITMAPCOREHEADER)) { + return BMP_INSUFFICIENT_DATA; + } + + header_size = read_uint32(data, 0); + + /* ensure there is enough data for the declared header size*/ + if ((bmp->buffer_size - BMP_FILE_HEADER_SIZE) < header_size) { + return BMP_INSUFFICIENT_DATA; + } + + /* a variety of different bitmap headers can follow, depending + * on the BMP variant. The header length field determines the type. + */ + if (header_size == BITMAPCOREHEADER) { + /* the following header is for os/2 and windows 2.x and consists of: + * + * +0 UINT32 size of this header (in bytes) + * +4 INT16 image width (in pixels) + * +6 INT16 image height (in pixels) + * +8 UINT16 number of colour planes (always 1) + * +10 UINT16 number of bits per pixel + */ + width = read_int16(data, 4); + height = read_int16(data, 6); + if ((width <= 0) || (height == 0)) + return BMP_DATA_ERROR; + if (height < 0) { + bmp->reversed = true; + height = -height; + } + /* ICOs only support 256*256 resolutions + * In the case of the ICO header, the height is actually the added + * height of XOR-Bitmap and AND-Bitmap (double the visible height) + * Technically we could remove this check and ICOs with bitmaps + * of any size could be processed; this is to conform to the spec. + */ + if (bmp->ico) { + if ((width > 256) || (height > 512)) { + return BMP_DATA_ERROR; + } else { + bmp->width = width; + bmp->height = height / 2; + } + } else { + bmp->width = width; + bmp->height = height; + } + if (read_uint16(data, 8) != 1) + return BMP_DATA_ERROR; + bmp->bpp = read_uint16(data, 10); + /** + * The bpp value should be in the range 1-32, but the only + * values considered legal are: + * RGB ENCODING: 1, 4, 8, 16, 24 and 32 + */ + if ((bmp->bpp != 1) && (bmp->bpp != 4) && + (bmp->bpp != 8) && + (bmp->bpp != 16) && + (bmp->bpp != 24) && + (bmp->bpp != 32)) + return BMP_DATA_ERROR; + if (bmp->bpp < 16) + bmp->colours = (1 << bmp->bpp); + palette_size = 3; + } else if (header_size < 40) { + return BMP_DATA_ERROR; + } else { + /* the following header is for windows 3.x and onwards. it is a + * minimum of 40 bytes and (as of Windows 95) a maximum of 108 bytes. + * + * +0 UINT32 size of this header (in bytes) + * +4 INT32 image width (in pixels) + * +8 INT32 image height (in pixels) + * +12 UINT16 number of colour planes (always 1) + * +14 UINT16 number of bits per pixel + * +16 UINT32 compression methods used + * +20 UINT32 size of bitmap (in bytes) + * +24 UINT32 horizontal resolution (in pixels per meter) + * +28 UINT32 vertical resolution (in pixels per meter) + * +32 UINT32 number of colours in the image + * +36 UINT32 number of important colours + * +40 UINT32 mask identifying bits of red component + * +44 UINT32 mask identifying bits of green component + * +48 UINT32 mask identifying bits of blue component + * +52 UINT32 mask identifying bits of alpha component + * +56 UINT32 color space type + * +60 UINT32 x coordinate of red endpoint + * +64 UINT32 y coordinate of red endpoint + * +68 UINT32 z coordinate of red endpoint + * +72 UINT32 x coordinate of green endpoint + * +76 UINT32 y coordinate of green endpoint + * +80 UINT32 z coordinate of green endpoint + * +84 UINT32 x coordinate of blue endpoint + * +88 UINT32 y coordinate of blue endpoint + * +92 UINT32 z coordinate of blue endpoint + * +96 UINT32 gamma red coordinate scale value + * +100 UINT32 gamma green coordinate scale value + * +104 UINT32 gamma blue coordinate scale value + */ + width = read_int32(data, 4); + height = read_int32(data, 8); + if ((width <= 0) || (height == 0)) + return BMP_DATA_ERROR; + if (height < 0) { + bmp->reversed = true; + if (height <= -INT32_MAX) { + height = INT32_MAX; + } else { + height = -height; + } + } + /* ICOs only support 256*256 resolutions + * In the case of the ICO header, the height is actually the added + * height of XOR-Bitmap and AND-Bitmap (double the visible height) + * Technically we could remove this check and ICOs with bitmaps + * of any size could be processed; this is to conform to the spec. + */ + if (bmp->ico) { + if ((width > 256) || (height > 512)) { + return BMP_DATA_ERROR; + } else { + bmp->width = width; + bmp->height = height / 2; + } + } else { + bmp->width = width; + bmp->height = height; + } + if (read_uint16(data, 12) != 1) + return BMP_DATA_ERROR; + bmp->bpp = read_uint16(data, 14); + if (bmp->bpp == 0) + bmp->bpp = 8; + bmp->encoding = read_uint32(data, 16); + /** + * The bpp value should be in the range 1-32, but the only + * values considered legal are: + * RGB ENCODING: 1, 4, 8, 16, 24 and 32 + * RLE4 ENCODING: 4 + * RLE8 ENCODING: 8 + * BITFIELD ENCODING: 16 and 32 + */ + switch (bmp->encoding) { + case BMP_ENCODING_RGB: + if ((bmp->bpp != 1) && (bmp->bpp != 4) && + (bmp->bpp != 8) && + (bmp->bpp != 16) && + (bmp->bpp != 24) && + (bmp->bpp != 32)) + return BMP_DATA_ERROR; + break; + case BMP_ENCODING_RLE8: + if (bmp->bpp != 8) + return BMP_DATA_ERROR; + break; + case BMP_ENCODING_RLE4: + if (bmp->bpp != 4) + return BMP_DATA_ERROR; + break; + case BMP_ENCODING_BITFIELDS: + if ((bmp->bpp != 16) && (bmp->bpp != 32)) + return BMP_DATA_ERROR; + break; + /* invalid encoding */ + default: + return BMP_DATA_ERROR; + break; + } + /* Bitfield encoding means we have red, green, blue, and alpha masks. + * Here we acquire the masks and determine the required bit shift to + * align them in our 24-bit color 8-bit alpha format. + */ + if (bmp->encoding == BMP_ENCODING_BITFIELDS) { + if (header_size == 40) { + header_size += 12; + if (bmp->buffer_size < (14 + header_size)) + return BMP_INSUFFICIENT_DATA; + for (i = 0; i < 3; i++) + bmp->mask[i] = read_uint32(data, 40 + (i << 2)); + } else { + if (header_size < 56) + return BMP_INSUFFICIENT_DATA; + for (i = 0; i < 4; i++) + bmp->mask[i] = read_uint32(data, 40 + (i << 2)); + } + for (i = 0; i < 4; i++) { + if (bmp->mask[i] == 0) + break; + for (j = 31; j > 0; j--) + if (bmp->mask[i] & ((unsigned)1 << j)) { + if ((j - 7) > 0) + bmp->mask[i] &= (unsigned)0xff << (j - 7); + else + bmp->mask[i] &= 0xff >> (-(j - 7)); + bmp->shift[i] = (i << 3) - (j - 7); + break; + } + } + } + bmp->colours = read_uint32(data, 32); + if (bmp->colours == 0 && bmp->bpp < 16) + bmp->colours = (1 << bmp->bpp); + palette_size = 4; + } + data += header_size; + + /* if there's no alpha mask, flag the bmp opaque */ + if ((!bmp->ico) && (bmp->mask[3] == 0)) { + flags |= BMP_OPAQUE; + bmp->opaque = true; + } + + /* we only have a palette for <16bpp */ + if (bmp->bpp < 16) { + /* we now have a series of palette entries of the format: + * + * +0 BYTE blue + * +1 BYTE green + * +2 BYTE red + * + * if the palette is from an OS/2 or Win2.x file then the entries + * are padded with an extra byte. + */ + + /* boundary checking */ + if (bmp->buffer_size < (14 + header_size + ((uint64_t)4 * bmp->colours))) + return BMP_INSUFFICIENT_DATA; + + /* create the colour table */ + bmp->colour_table = (uint32_t *)malloc(bmp->colours * 4); + if (!bmp->colour_table) + return BMP_INSUFFICIENT_MEMORY; + for (i = 0; i < bmp->colours; i++) { + uint32_t colour = data[2] | (data[1] << 8) | (data[0] << 16); + if (bmp->opaque) + colour |= ((uint32_t)0xff << 24); + data += palette_size; + bmp->colour_table[i] = read_uint32((uint8_t *)&colour,0); + } + + /* some bitmaps have a bad offset if there is a pallete, work + * round this by fixing up the data offset to after the palette + * but only if there is data following the palette as some + * bitmaps encode data in the palette! + */ + if ((bmp->bitmap_offset < (uint32_t)(data - bmp->bmp_data)) && + ((bmp->buffer_size - (data - bmp->bmp_data)) > 0)) { + bmp->bitmap_offset = data - bmp->bmp_data; + } + } + + /* create our bitmap */ + flags |= BMP_NEW | BMP_CLEAR_MEMORY; + bmp->bitmap = bmp->bitmap_callbacks.bitmap_create(bmp->width, bmp->height, flags); + if (!bmp->bitmap) { + if (bmp->colour_table) + free(bmp->colour_table); + bmp->colour_table = NULL; + return BMP_INSUFFICIENT_MEMORY; + } + /* BMPs within ICOs don't have BMP file headers, so the image data should + * always be right after the colour table. + */ + if (bmp->ico) + bmp->bitmap_offset = (uintptr_t)data - (uintptr_t)bmp->bmp_data; + return BMP_OK; +} + + +/** + * Parse the bitmap file header + * + * \param bmp The bitmap. + * \param data The data for the file header + * \return BMP_OK on success or error code on faliure + */ +static bmp_result bmp_file_header_parse(bmp_image *bmp, uint8_t *data) +{ + /* standard 14-byte BMP file header is: + * + * +0 UINT16 File Type ('BM') + * +2 UINT32 Size of File (in bytes) + * +6 INT16 Reserved Field (1) + * +8 INT16 Reserved Field (2) + * +10 UINT32 Starting Position of Image Data (offset in bytes) + */ + if (bmp->buffer_size < BMP_FILE_HEADER_SIZE) + return BMP_INSUFFICIENT_DATA; + + if ((data[0] != (uint8_t)'B') || (data[1] != (uint8_t)'M')) + return BMP_DATA_ERROR; + + bmp->bitmap_offset = read_uint32(data, 10); + + /* check the offset to data lies within the file */ + if (bmp->bitmap_offset >= bmp->buffer_size) { + return BMP_INSUFFICIENT_DATA; + } + + return BMP_OK; +} + + +/** + * Allocates memory for the next BMP in an ICO collection + * + * Sets proper structure values + * + * \param ico the ICO collection to add the image to + * \param image a pointer to the ICO image to be initialised + */ +static bmp_result next_ico_image(ico_collection *ico, ico_image *image) { + bmp_create(&image->bmp, &ico->bitmap_callbacks); + image->next = ico->first; + ico->first = image; + return BMP_OK; +} + + +/** + * Parse the icon file header + * + * \param ico The icon collection. + * \param data The header data to parse. + * \return BMP_OK on successful parse else error code + */ +static bmp_result ico_header_parse(ico_collection *ico, uint8_t *data) +{ + uint16_t count, i; + bmp_result result; + int area, max_area = 0; + + /* 6-byte ICO file header is: + * + * +0 INT16 Reserved (should be 0) + * +2 UINT16 Type (1 for ICO, 2 for CUR) + * +4 UINT16 Number of BMPs to follow + */ + if (ico->buffer_size < ICO_FILE_HEADER_SIZE) + return BMP_INSUFFICIENT_DATA; + // if (read_int16(data, 2) != 0x0000) + // return BMP_DATA_ERROR; + if (read_uint16(data, 2) != 0x0001) + return BMP_DATA_ERROR; + count = read_uint16(data, 4); + if (count == 0) + return BMP_DATA_ERROR; + data += ICO_FILE_HEADER_SIZE; + + /* check if we have enough data for the directory */ + if (ico->buffer_size < (uint32_t)(ICO_FILE_HEADER_SIZE + (ICO_DIR_ENTRY_SIZE * count))) + return BMP_INSUFFICIENT_DATA; + + /* Decode the BMP files. + * + * 16-byte ICO directory entry is: + * + * +0 UINT8 Width (0 for 256 pixels) + * +1 UINT8 Height (0 for 256 pixels) + * +2 UINT8 Colour count (0 if more than 256 colours) + * +3 INT8 Reserved (should be 0, but may not be) + * +4 UINT16 Colour Planes (should be 0 or 1) + * +6 UINT16 Bits Per Pixel + * +8 UINT32 Size of BMP info header + bitmap data in bytes + * +12 UINT32 Offset (points to the BMP info header, not the bitmap data) + */ + for (i = 0; i < count; i++) { + ico_image *image; + image = calloc(1, sizeof(ico_image)); + if (!image) + return BMP_INSUFFICIENT_MEMORY; + result = next_ico_image(ico, image); + if (result != BMP_OK) + return result; + image->bmp.width = read_uint8(data, 0); + if (image->bmp.width == 0) + image->bmp.width = 256; + image->bmp.height = read_uint8(data, 1); + if (image->bmp.height == 0) + image->bmp.height = 256; + image->bmp.buffer_size = read_uint32(data, 8); + image->bmp.bmp_data = ico->ico_data + read_uint32(data, 12); + if (image->bmp.bmp_data + image->bmp.buffer_size > + ico->ico_data + ico->buffer_size) + return BMP_INSUFFICIENT_DATA; + image->bmp.ico = true; + data += ICO_DIR_ENTRY_SIZE; + + /* Ensure that the bitmap data resides in the buffer */ + if (image->bmp.bmp_data - ico->ico_data >= 0 && + (uint32_t)(image->bmp.bmp_data - + ico->ico_data) >= ico->buffer_size) + return BMP_DATA_ERROR; + + /* Ensure that we have sufficient data to read the bitmap */ + if (image->bmp.buffer_size - ICO_DIR_ENTRY_SIZE >= + ico->buffer_size - (ico->ico_data - data)) + return BMP_INSUFFICIENT_DATA; + + result = bmp_info_header_parse(&image->bmp, + image->bmp.bmp_data); + if (result != BMP_OK) + return result; + + /* adjust the size based on the images available */ + area = image->bmp.width * image->bmp.height; + if (area > max_area) { + ico->width = image->bmp.width; + ico->height = image->bmp.height; + max_area = area; + } + } + return BMP_OK; +} + + +/** + * Decode BMP data stored in 32bpp colour. + * + * \param bmp the BMP image to decode + * \param start the data to decode, updated to last byte read on success + * \param bytes the number of bytes of data available + * \return BMP_OK on success + * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; + * in this case, the image may be partially viewable + */ +static bmp_result bmp_decode_rgb32(bmp_image *bmp, uint8_t **start, int bytes) +{ + uint8_t *top, *bottom, *end, *data; + uint32_t *scanline; + uint32_t x, y; + uint32_t swidth; + uint8_t i; + uint32_t word; + + data = *start; + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + bmp->decoded = true; + + /* Determine transparent index */ + if (bmp->limited_trans) { + if ((data + 4) > end) + return BMP_INSUFFICIENT_DATA; + if (bmp->encoding == BMP_ENCODING_BITFIELDS) + bmp->transparent_index = read_uint32(data, 0); + else + bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16); + } + + for (y = 0; y < bmp->height; y++) { + if ((data + (4 * bmp->width)) > end) + return BMP_INSUFFICIENT_DATA; + if (bmp->reversed) + scanline = (void *)(top + (y * swidth)); + else + scanline = (void *)(bottom - (y * swidth)); + if (bmp->encoding == BMP_ENCODING_BITFIELDS) { + for (x = 0; x < bmp->width; x++) { + word = read_uint32(data, 0); + for (i = 0; i < 4; i++) + if (bmp->shift[i] > 0) + scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]); + else + scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i])); + /* 32-bit BMPs have alpha masks, but sometimes they're not utilized */ + if (bmp->opaque) + scanline[x] |= ((unsigned)0xff << 24); + data += 4; + scanline[x] = read_uint32((uint8_t *)&scanline[x],0); + } + } else { + for (x = 0; x < bmp->width; x++) { + scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16); + if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) { + scanline[x] = bmp->trans_colour; + } + if (bmp->opaque) { + scanline[x] |= ((unsigned)0xff << 24); + } else { + scanline[x] |= (unsigned)data[3] << 24; + } + data += 4; + scanline[x] = read_uint32((uint8_t *)&scanline[x],0); + } + } + } + *start = data; + return BMP_OK; +} + + +/** + * Decode BMP data stored in 24bpp colour. + * + * \param bmp the BMP image to decode + * \param start the data to decode, updated to last byte read on success + * \param bytes the number of bytes of data available + * \return BMP_OK on success + * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; + * in this case, the image may be partially viewable + */ +static bmp_result bmp_decode_rgb24(bmp_image *bmp, uint8_t **start, int bytes) +{ + uint8_t *top, *bottom, *end, *data; + uint32_t *scanline; + uint32_t x, y; + uint32_t swidth; + uintptr_t addr; + + data = *start; + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) { + return BMP_INSUFFICIENT_MEMORY; + } + + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + addr = ((uintptr_t)data) & 3; + bmp->decoded = true; + + /* Determine transparent index */ + if (bmp->limited_trans) { + if ((data + 3) > end) { + return BMP_INSUFFICIENT_DATA; + } + + bmp->transparent_index = data[2] | (data[1] << 8) | (data[0] << 16); + } + + for (y = 0; y < bmp->height; y++) { + if ((data + (3 * bmp->width)) > end) { + return BMP_INSUFFICIENT_DATA; + } + + if (bmp->reversed) { + scanline = (void *)(top + (y * swidth)); + } else { + scanline = (void *)(bottom - (y * swidth)); + } + + for (x = 0; x < bmp->width; x++) { + scanline[x] = data[2] | (data[1] << 8) | (data[0] << 16); + if ((bmp->limited_trans) && (scanline[x] == bmp->transparent_index)) { + scanline[x] = bmp->trans_colour; + } else { + scanline[x] |= ((uint32_t)0xff << 24); + } + data += 3; + scanline[x] = read_uint32((uint8_t *)&scanline[x],0); + } + + while (addr != (((uintptr_t)data) & 3)) { + data++; + } + } + *start = data; + return BMP_OK; +} + + +/** + * Decode BMP data stored in 16bpp colour. + * + * \param bmp the BMP image to decode + * \param start the data to decode, updated to last byte read on success + * \param bytes the number of bytes of data available + * \return BMP_OK on success + * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; + * in this case, the image may be partially viewable + */ +static bmp_result bmp_decode_rgb16(bmp_image *bmp, uint8_t **start, int bytes) +{ + uint8_t *top, *bottom, *end, *data; + uint32_t *scanline; + uint32_t x, y, swidth; + uintptr_t addr; + uint8_t i; + uint16_t word; + + data = *start; + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + addr = ((uintptr_t)data) & 3; + bmp->decoded = true; + + /* Determine transparent index */ + if (bmp->limited_trans) { + if ((data + 2) > end) + return BMP_INSUFFICIENT_DATA; + bmp->transparent_index = read_uint16(data, 0); + } + + for (y = 0; y < bmp->height; y++) { + if ((data + (2 * bmp->width)) > end) + return BMP_INSUFFICIENT_DATA; + if (bmp->reversed) + scanline = (void *)(top + (y * swidth)); + else + scanline = (void *)(bottom - (y * swidth)); + if (bmp->encoding == BMP_ENCODING_BITFIELDS) { + for (x = 0; x < bmp->width; x++) { + word = read_uint16(data, 0); + if ((bmp->limited_trans) && (word == bmp->transparent_index)) + scanline[x] = bmp->trans_colour; + else { + scanline[x] = 0; + for (i = 0; i < 4; i++) + if (bmp->shift[i] > 0) + scanline[x] |= ((word & bmp->mask[i]) << bmp->shift[i]); + else + scanline[x] |= ((word & bmp->mask[i]) >> (-bmp->shift[i])); + if (bmp->opaque) + scanline[x] |= ((unsigned)0xff << 24); + } + data += 2; + scanline[x] = read_uint32((uint8_t *)&scanline[x],0); + } + } else { + for (x = 0; x < bmp->width; x++) { + word = read_uint16(data, 0); + if ((bmp->limited_trans) && (word == bmp->transparent_index)) + scanline[x] = bmp->trans_colour; + else { + /* 16-bit RGB defaults to RGB555 */ + scanline[x] = ((word & (31 << 0)) << 19) | + ((word & (31 << 5)) << 6) | + ((word & (31 << 10)) >> 7); + } + if (bmp->opaque) + scanline[x] |= ((unsigned)0xff << 24); + data += 2; + scanline[x] = read_uint32((uint8_t *)&scanline[x],0); + } + } + while (addr != (((uintptr_t)data) & 3)) + data += 2; + } + *start = data; + return BMP_OK; +} + + +/** + * Decode BMP data stored with a palette and in 8bpp colour or less. + * + * \param bmp the BMP image to decode + * \param start the data to decode, updated to last byte read on success + * \param bytes the number of bytes of data available + * \return BMP_OK on success + * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; + * in this case, the image may be partially viewable + */ +static bmp_result bmp_decode_rgb(bmp_image *bmp, uint8_t **start, int bytes) +{ + uint8_t *top, *bottom, *end, *data; + uint32_t *scanline; + uintptr_t addr; + uint32_t x, y, swidth; + uint8_t bit_shifts[8]; + uint8_t ppb = 8 / bmp->bpp; + uint8_t bit_mask = (1 << bmp->bpp) - 1; + uint8_t cur_byte = 0, bit, i; + + for (i = 0; i < ppb; i++) + bit_shifts[i] = 8 - ((i + 1) * bmp->bpp); + + data = *start; + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + addr = ((uintptr_t)data) & 3; + bmp->decoded = true; + + /* Determine transparent index */ + if (bmp->limited_trans) { + uint32_t idx = (*data >> bit_shifts[0]) & bit_mask; + if (idx >= bmp->colours) + return BMP_DATA_ERROR; + bmp->transparent_index = bmp->colour_table[idx]; + } + + for (y = 0; y < bmp->height; y++) { + bit = 8; + if ((data + ((bmp->width + ppb - 1) / ppb)) > end) + return BMP_INSUFFICIENT_DATA; + if (bmp->reversed) + scanline = (void *)(top + (y * swidth)); + else + scanline = (void *)(bottom - (y * swidth)); + for (x = 0; x < bmp->width; x++) { + uint32_t idx; + if (bit >= ppb) { + bit = 0; + cur_byte = *data++; + } + idx = (cur_byte >> bit_shifts[bit++]) & bit_mask; + if (idx < bmp->colours) { + /* ensure colour table index is in bounds */ + scanline[x] = bmp->colour_table[idx]; + if ((bmp->limited_trans) && + (scanline[x] == bmp->transparent_index)) { + scanline[x] = bmp->trans_colour; + } + } + } + while (addr != (((uintptr_t)data) & 3)) + data++; + } + *start = data; + return BMP_OK; +} + + +/** + * Decode a 1bpp mask for an ICO + * + * \param bmp the BMP image to decode + * \param data the data to decode + * \param bytes the number of bytes of data available + * \return BMP_OK on success + */ +static bmp_result bmp_decode_mask(bmp_image *bmp, uint8_t *data, int bytes) +{ + uint8_t *top, *bottom, *end; + uint32_t *scanline; + uintptr_t addr; + uint32_t x, y, swidth; + uint32_t cur_byte = 0; + + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + + addr = ((uintptr_t)data) & 3; + + for (y = 0; y < bmp->height; y++) { + if ((data + (bmp->width >> 3)) > end) + return BMP_INSUFFICIENT_DATA; + scanline = (void *)(bottom - (y * swidth)); + for (x = 0; x < bmp->width; x++) { + if ((x & 7) == 0) + cur_byte = *data++; + scanline[x] = read_uint32((uint8_t *)&scanline[x], 0); + if ((cur_byte & 128) == 0) { + scanline[x] |= ((unsigned)0xff << 24); + } else { + scanline[x] &= 0xffffff; + } + scanline[x] = read_uint32((uint8_t *)&scanline[x], 0); + cur_byte = cur_byte << 1; + } + while (addr != (((uintptr_t)data) & 3)) + data++; + } + return BMP_OK; +} + + +/** + * Decode BMP data stored encoded in RLE8. + * + * \param bmp the BMP image to decode + * \param data the data to decode + * \param bytes the number of bytes of data available + * \return BMP_OK on success + * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; + * in this case, the image may be partially viewable + */ +static bmp_result +bmp_decode_rle8(bmp_image *bmp, uint8_t *data, int bytes) +{ + uint8_t *top, *bottom, *end; + uint32_t *scanline; + uint32_t swidth; + uint32_t i, length, pixels_left; + uint32_t x = 0, y = 0, last_y = 0; + uint32_t pixel = 0; + + if (bmp->ico) + return BMP_DATA_ERROR; + + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + bmp->decoded = true; + + do { + if (data + 2 > end) + return BMP_INSUFFICIENT_DATA; + length = *data++; + if (length == 0) { + length = *data++; + switch (length) { + case 0: + /* 00 - 00 means end of scanline */ + x = 0; + if (last_y == y) { + y++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + } + last_y = y; + break; + + case 1: + /* 00 - 01 means end of RLE data */ + return BMP_OK; + + case 2: + /* 00 - 02 - XX - YY means move cursor */ + if (data + 2 > end) + return BMP_INSUFFICIENT_DATA; + x += *data++; + if (x >= bmp->width) + return BMP_DATA_ERROR; + y += *data++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + break; + + default: + /* 00 - NN means escape NN pixels */ + if (bmp->reversed) { + pixels_left = (bmp->height - y) * bmp->width - x; + scanline = (void *)(top + (y * swidth)); + } else { + pixels_left = (y + 1) * bmp->width - x; + scanline = (void *)(bottom - (y * swidth)); + } + if (length > pixels_left) + length = pixels_left; + if (data + length > end) + return BMP_INSUFFICIENT_DATA; + + /* the following code could be easily optimised + * by simply checking the bounds on entry and + * using some simple copying routines if so + */ + for (i = 0; i < length; i++) { + uint32_t idx = (uint32_t) *data++; + if (x >= bmp->width) { + x = 0; + y++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + if (bmp->reversed) { + scanline += bmp->width; + } else { + scanline -= bmp->width; + } + } + if (idx >= bmp->colours) + return BMP_DATA_ERROR; + scanline[x++] = bmp->colour_table[idx]; + } + + if ((length & 1) && (*data++ != 0x00)) + return BMP_DATA_ERROR; + + break; + } + } else { + uint32_t idx; + + /* NN means perform RLE for NN pixels */ + if (bmp->reversed) { + pixels_left = (bmp->height - y) * bmp->width - x; + scanline = (void *)(top + (y * swidth)); + } else { + pixels_left = (y + 1) * bmp->width - x; + scanline = (void *)(bottom - (y * swidth)); + } + if (length > pixels_left) + length = pixels_left; + + /* boundary checking */ + if (data + 1 > end) + return BMP_INSUFFICIENT_DATA; + + /* the following code could be easily optimised by + * simply checking the bounds on entry and using some + * simply copying routines if so + */ + idx = (uint32_t) *data++; + if (idx >= bmp->colours) + return BMP_DATA_ERROR; + + pixel = bmp->colour_table[idx]; + for (i = 0; i < length; i++) { + if (x >= bmp->width) { + x = 0; + y++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + if (bmp->reversed) { + scanline += bmp->width; + } else { + scanline -= bmp->width; + } + } + scanline[x++] = pixel; + } + } + } while (data < end); + + return BMP_OK; +} + + +/** + * Decode BMP data stored encoded in RLE4. + * + * \param bmp the BMP image to decode + * \param data the data to decode + * \param bytes the number of bytes of data available + * \return BMP_OK on success + * BMP_INSUFFICIENT_DATA if the bitmap data ends unexpectedly; + * in this case, the image may be partially viewable + */ +static bmp_result +bmp_decode_rle4(bmp_image *bmp, uint8_t *data, int bytes) +{ + uint8_t *top, *bottom, *end; + uint32_t *scanline; + uint32_t swidth; + uint32_t i, length, pixels_left; + uint32_t x = 0, y = 0, last_y = 0; + uint32_t pixel = 0, pixel2; + + if (bmp->ico) + return BMP_DATA_ERROR; + + swidth = sizeof(uint32_t) * bmp->width; + top = bmp->bitmap_callbacks.bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; + bottom = top + (uint64_t)swidth * (bmp->height - 1); + end = data + bytes; + bmp->decoded = true; + + do { + if (data + 2 > end) + return BMP_INSUFFICIENT_DATA; + length = *data++; + if (length == 0) { + length = *data++; + switch (length) { + case 0: + /* 00 - 00 means end of scanline */ + x = 0; + if (last_y == y) { + y++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + } + last_y = y; + break; + + case 1: + /* 00 - 01 means end of RLE data */ + return BMP_OK; + + case 2: + /* 00 - 02 - XX - YY means move cursor */ + if (data + 2 > end) + return BMP_INSUFFICIENT_DATA; + x += *data++; + if (x >= bmp->width) + return BMP_DATA_ERROR; + y += *data++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + break; + + default: + /* 00 - NN means escape NN pixels */ + if (bmp->reversed) { + pixels_left = (bmp->height - y) * bmp->width - x; + scanline = (void *)(top + (y * swidth)); + } else { + pixels_left = (y + 1) * bmp->width - x; + scanline = (void *)(bottom - (y * swidth)); + } + if (length > pixels_left) + length = pixels_left; + if (data + ((length + 1) / 2) > end) + return BMP_INSUFFICIENT_DATA; + + /* the following code could be easily optimised + * by simply checking the bounds on entry and + * using some simple copying routines + */ + + for (i = 0; i < length; i++) { + if (x >= bmp->width) { + x = 0; + y++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + if (bmp->reversed) { + scanline += bmp->width; + } else { + scanline -= bmp->width; + } + + } + if ((i & 1) == 0) { + pixel = *data++; + if ((pixel >> 4) >= bmp->colours) + return BMP_DATA_ERROR; + scanline[x++] = bmp->colour_table + [pixel >> 4]; + } else { + if ((pixel & 0xf) >= bmp->colours) + return BMP_DATA_ERROR; + scanline[x++] = bmp->colour_table + [pixel & 0xf]; + } + } + length = (length + 1) >> 1; + + if ((length & 1) && (*data++ != 0x00)) + return BMP_DATA_ERROR; + + break; + } + } else { + /* NN means perform RLE for NN pixels */ + if (bmp->reversed) { + pixels_left = (bmp->height - y) * bmp->width - x; + scanline = (void *)(top + (y * swidth)); + } else { + pixels_left = (y + 1) * bmp->width - x; + scanline = (void *)(bottom - (y * swidth)); + } + if (length > pixels_left) + length = pixels_left; + + /* boundary checking */ + if (data + 1 > end) + return BMP_INSUFFICIENT_DATA; + + /* the following code could be easily optimised by + * simply checking the bounds on entry and using some + * simple copying routines + */ + + pixel2 = *data++; + if ((pixel2 >> 4) >= bmp->colours || + (pixel2 & 0xf) >= bmp->colours) + return BMP_DATA_ERROR; + pixel = bmp->colour_table[pixel2 >> 4]; + pixel2 = bmp->colour_table[pixel2 & 0xf]; + for (i = 0; i < length; i++) { + if (x >= bmp->width) { + x = 0; + y++; + if (y >= bmp->height) + return BMP_DATA_ERROR; + if (bmp->reversed) { + scanline += bmp->width; + } else { + scanline -= bmp->width; + } + } + if ((i & 1) == 0) + scanline[x++] = pixel; + else + scanline[x++] = pixel2; + } + + } + } while (data < end); + + return BMP_OK; +} + + +/* exported interface documented in libnsbmp.h */ +bmp_result +bmp_create(bmp_image *bmp, + bmp_bitmap_callback_vt *bitmap_callbacks) +{ + memset(bmp, 0, sizeof(bmp_image)); + bmp->bitmap_callbacks = *bitmap_callbacks; + + return BMP_OK; +} + + +/* exported interface documented in libnsbmp.h */ +bmp_result +ico_collection_create(ico_collection *ico, + bmp_bitmap_callback_vt *bitmap_callbacks) +{ + + memset(ico, 0, sizeof(ico_collection)); + ico->bitmap_callbacks = *bitmap_callbacks; + + return BMP_OK; +} + + +/* exported interface documented in libnsbmp.h */ +bmp_result bmp_analyse(bmp_image *bmp, size_t size, uint8_t *data) +{ + bmp_result res; + + /* ensure we aren't already initialised */ + if (bmp->bitmap) { + return BMP_OK; + } + + /* initialize source data values */ + bmp->buffer_size = size; + bmp->bmp_data = data; + + res = bmp_file_header_parse(bmp, data); + if (res == BMP_OK) { + res = bmp_info_header_parse(bmp, data + BMP_FILE_HEADER_SIZE); + } + return res; +} + + +/* exported interface documented in libnsbmp.h */ +bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data) +{ + /* ensure we aren't already initialised */ + if (ico->first) + return BMP_OK; + + /* initialize values */ + ico->buffer_size = size; + ico->ico_data = data; + + return ico_header_parse(ico, data); +} + + +/* exported interface documented in libnsbmp.h */ +bmp_result bmp_decode(bmp_image *bmp) +{ + uint8_t *data; + uint32_t bytes; + bmp_result result = BMP_OK; + + data = bmp->bmp_data + bmp->bitmap_offset; + bytes = bmp->buffer_size - bmp->bitmap_offset; + + switch (bmp->encoding) { + case BMP_ENCODING_RGB: + switch (bmp->bpp) { + case 32: + result = bmp_decode_rgb32(bmp, &data, bytes); + break; + + case 24: + result = bmp_decode_rgb24(bmp, &data, bytes); + break; + + case 16: + result = bmp_decode_rgb16(bmp, &data, bytes); + break; + + default: + result = bmp_decode_rgb(bmp, &data, bytes); + break; + } + break; + + case BMP_ENCODING_RLE8: + result = bmp_decode_rle8(bmp, data, bytes); + break; + + case BMP_ENCODING_RLE4: + result = bmp_decode_rle4(bmp, data, bytes); + break; + + case BMP_ENCODING_BITFIELDS: + switch (bmp->bpp) { + case 32: + result = bmp_decode_rgb32(bmp, &data, bytes); + break; + + case 16: + result = bmp_decode_rgb16(bmp, &data, bytes); + break; + + default: + result = BMP_DATA_ERROR; + break; + } + break; + } + + /* icons with less than 32bpp have a 1bpp alpha mask */ + if ((result == BMP_OK) && (bmp->ico) && (bmp->bpp != 32)) { + bytes = (uintptr_t)bmp->bmp_data + bmp->buffer_size - (uintptr_t)data; + result = bmp_decode_mask(bmp, data, bytes); + } + return result; +} + + +/* exported interface documented in libnsbmp.h */ +bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t colour) +{ + bmp->limited_trans = true; + bmp->trans_colour = colour; + return bmp_decode(bmp); +} + + +/* exported interface documented in libnsbmp.h */ +bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height) +{ + bmp_image *bmp = NULL; + ico_image *image; + int x, y, cur, distance = (1 << 24); + + if (width == 0) + width = ico->width; + if (height == 0) + height = ico->height; + for (image = ico->first; image; image = image->next) { + if ((image->bmp.width == width) && (image->bmp.height == height)) + return &image->bmp; + x = image->bmp.width - width; + y = image->bmp.height - height; + cur = (x * x) + (y * y); + if (cur < distance) { + distance = cur; + bmp = &image->bmp; + } + } + return bmp; +} + + +/* exported interface documented in libnsbmp.h */ +void bmp_finalise(bmp_image *bmp) +{ + if (bmp->bitmap) + bmp->bitmap_callbacks.bitmap_destroy(bmp->bitmap); + bmp->bitmap = NULL; + if (bmp->colour_table) + free(bmp->colour_table); + bmp->colour_table = NULL; +} + + +/* exported interface documented in libnsbmp.h */ +void ico_finalise(ico_collection *ico) +{ + ico_image *image; + + for (image = ico->first; image; image = image->next) + bmp_finalise(&image->bmp); + while (ico->first) { + image = ico->first; + ico->first = image->next; + free(image); + } +} diff --git a/u-boot/drivers/video/drm/libnsbmp.h b/u-boot/drivers/video/drm/libnsbmp.h new file mode 100644 index 0000000000..4f750c472c --- /dev/null +++ b/u-boot/drivers/video/drm/libnsbmp.h @@ -0,0 +1,252 @@ +/* + * Copyright 2006 Richard Wilson + * Copyright 2008 Sean Fox + * + * This file is part of NetSurf's libnsbmp, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +/** + * \file + * Bitmap file decoding interface. + */ + +#ifndef _LIBNSBMP_H_ +#define _LIBNSBMP_H_ + +#include +#include +#include + +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif + +/* bmp flags */ +#define BMP_NEW 0 +/** image is opaque (as opposed to having an alpha mask) */ +#define BMP_OPAQUE (1 << 0) +/** memory should be wiped */ +#define BMP_CLEAR_MEMORY (1 << 1) + +/** + * error return values + */ +typedef enum { + BMP_OK = 0, + BMP_INSUFFICIENT_MEMORY = 1, + BMP_INSUFFICIENT_DATA = 2, + BMP_DATA_ERROR = 3 +} bmp_result; + +/** + * encoding types + */ +typedef enum { + BMP_ENCODING_RGB = 0, + BMP_ENCODING_RLE8 = 1, + BMP_ENCODING_RLE4 = 2, + BMP_ENCODING_BITFIELDS = 3 +} bmp_encoding; + +/* API for Bitmap callbacks */ +typedef void* (*bmp_bitmap_cb_create)(int width, int height, unsigned int state); +typedef void (*bmp_bitmap_cb_destroy)(void *bitmap); +typedef unsigned char* (*bmp_bitmap_cb_get_buffer)(void *bitmap); +typedef size_t (*bmp_bitmap_cb_get_bpp)(void *bitmap); + +/** + * The Bitmap callbacks function table + */ +typedef struct bmp_bitmap_callback_vt_s { + /** Callback to allocate bitmap storage. */ + bmp_bitmap_cb_create bitmap_create; + /** Called to free bitmap storage. */ + bmp_bitmap_cb_destroy bitmap_destroy; + /** Return a pointer to the pixel data in a bitmap. */ + bmp_bitmap_cb_get_buffer bitmap_get_buffer; +} bmp_bitmap_callback_vt; + +/** + * bitmap image + */ +typedef struct bmp_img { + /** callbacks for bitmap functions */ + bmp_bitmap_callback_vt bitmap_callbacks; + /** pointer to BMP data */ + uint8_t *bmp_data; + /** width of BMP (valid after _analyse) */ + uint32_t width; + /** heigth of BMP (valid after _analyse) */ + uint32_t height; + /** whether the image has been decoded */ + bool decoded; + /** decoded image */ + void *bitmap; + + /* Internal members are listed below */ + /** total number of bytes of BMP data available */ + uint32_t buffer_size; + /** pixel encoding type */ + bmp_encoding encoding; + /** offset of bitmap data */ + uint32_t bitmap_offset; + /** bits per pixel */ + uint16_t bpp; + /** number of colours */ + uint32_t colours; + /** colour table */ + uint32_t *colour_table; + /** whether to use bmp's limited transparency */ + bool limited_trans; + /** colour to display for "transparent" pixels when using limited + * transparency + */ + uint32_t trans_colour; + /** scanlines are top to bottom */ + bool reversed; + /** image is part of an ICO, mask follows */ + bool ico; + /** true if the bitmap does not contain an alpha channel */ + bool opaque; + /** four bitwise mask */ + uint32_t mask[4]; + /** four bitwise shifts */ + int32_t shift[4]; + /** colour representing "transparency" in the bitmap */ + uint32_t transparent_index; +} bmp_image; + +typedef struct ico_image { + bmp_image bmp; + struct ico_image *next; +} ico_image; + +/** + * icon image collection + */ +typedef struct ico_collection { + /** callbacks for bitmap functions */ + bmp_bitmap_callback_vt bitmap_callbacks; + /** width of largest BMP */ + uint16_t width; + /** heigth of largest BMP */ + uint16_t height; + + /* Internal members are listed below */ + /** pointer to ICO data */ + uint8_t *ico_data; + /** total number of bytes of ICO data available */ + uint32_t buffer_size; + /** root of linked list of images */ + ico_image *first; +} ico_collection; + +/** + * Initialises bitmap ready for analysing the bitmap. + * + * \param bmp The Bitmap to initialise + * \param callbacks The callbacks the library will call on operations. + * \return BMP_OK on success or appropriate error code. + */ +bmp_result bmp_create(bmp_image *bmp, bmp_bitmap_callback_vt *callbacks); + +/** + * Initialises icon ready for analysing the icon + * + * \param bmp The Bitmap to initialise + * \param callbacks The callbacks the library will call on operations. + * \return BMP_OK on success or appropriate error code. + */ +bmp_result ico_collection_create(ico_collection *ico, + bmp_bitmap_callback_vt *callbacks); + +/** + * Analyse a BMP prior to decoding. + * + * This will scan the data provided and perform checks to ensure the data is a + * valid BMP and prepare the bitmap image structure ready for decode. + * + * This function must be called and resturn BMP_OK before bmp_decode() as it + * prepares the bmp internal state for the decode process. + * + * \param bmp the BMP image to analyse. + * \param size The size of data in cdata. + * \param data The bitmap source data. + * \return BMP_OK on success or error code on faliure. + */ +bmp_result bmp_analyse(bmp_image *bmp, size_t size, uint8_t *data); + +/** + * Analyse an ICO prior to decoding. + * + * This function will scan the data provided and perform checks to ensure the + * data is a valid ICO. + * + * This function must be called before ico_find(). + * + * \param ico the ICO image to analyse + * \param size The size of data in cdata. + * \param data The bitmap source data. + * \return BMP_OK on success + */ +bmp_result ico_analyse(ico_collection *ico, size_t size, uint8_t *data); + +/** + * Decode a BMP + * + * This function decodes the BMP data such that bmp->bitmap is a valid + * image. The state of bmp->decoded is set to TRUE on exit such that it + * can easily be identified which BMPs are in a fully decoded state. + * + * \param bmp the BMP image to decode + * \return BMP_OK on success + */ +bmp_result bmp_decode(bmp_image *bmp); + +/** + * Decode a BMP using "limited transparency" + * + * Bitmaps do not have native transparency support. However, there is a + * "trick" that is used in some instances in which the first pixel of the + * bitmap becomes the "transparency index". The decoding application can + * replace this index with whatever background colour it chooses to + * create the illusion of transparency. + * + * When to use transparency is at the discretion of the decoding + * application. + * + * \param bmp the BMP image to decode + * \param colour the colour to use as "transparent" + * \return BMP_OK on success + */ +bmp_result bmp_decode_trans(bmp_image *bmp, uint32_t transparent_colour); + +/** + * Finds the closest BMP within an ICO collection + * + * This function finds the BMP with dimensions as close to a specified set + * as possible from the images in the collection. + * + * \param ico the ICO collection to examine + * \param width the preferred width (0 to use ICO header width) + * \param height the preferred height (0 to use ICO header height) + */ +bmp_image *ico_find(ico_collection *ico, uint16_t width, uint16_t height); + +/** + * Finalise a BMP prior to destruction. + * + * \param bmp the BMP image to finalise. + */ +void bmp_finalise(bmp_image *bmp); + +/** + * Finalise an ICO prior to destruction. + * + * \param ico the ICO image to finalise, + */ +void ico_finalise(ico_collection *ico); + +#endif diff --git a/u-boot/drivers/video/drm/phy-rockchip-samsung-hdptx-hdmi.c b/u-boot/drivers/video/drm/phy-rockchip-samsung-hdptx-hdmi.c index f964ddb905..43b1327153 100644 --- a/u-boot/drivers/video/drm/phy-rockchip-samsung-hdptx-hdmi.c +++ b/u-boot/drivers/video/drm/phy-rockchip-samsung-hdptx-hdmi.c @@ -2012,15 +2012,16 @@ static int rockchip_hdptx_phy_hdmi_bind(struct udevice *parent) subnode = ofnode_find_subnode(parent->node, "clk-port"); if (!ofnode_valid(subnode)) { - free(str); - printf("%s: no subnode for %s\n", __func__, parent->name); - return -ENXIO; + ret = device_bind_driver_to_node(parent, "clk_hdptx", str, + dev_ofnode(parent), NULL); + } else { + ret = device_bind_driver_to_node(parent, "clk_hdptx", str, + subnode, &child); } - ret = device_bind_driver_to_node(parent, "clk_hdptx", str, subnode, &child); if (ret) { free(str); - printf("%s: clk-port cannot bind its driver\n", __func__); + printf("%s: clk_hdptx cannot bind its driver\n", __func__); return ret; } diff --git a/u-boot/drivers/video/drm/rockchip_display.c b/u-boot/drivers/video/drm/rockchip_display.c index 2eb9112019..989c063679 100644 --- a/u-boot/drivers/video/drm/rockchip_display.c +++ b/u-boot/drivers/video/drm/rockchip_display.c @@ -23,8 +23,10 @@ #include #include #include +#include #include "bmp_helper.h" +#include "libnsbmp.h" #include "rockchip_display.h" #include "rockchip_crtc.h" #include "rockchip_connector.h" @@ -48,6 +50,8 @@ #define RK_BLK_SIZE 512 #define BMP_PROCESSED_FLAG 8399 +#define BYTES_PER_PIXEL sizeof(uint32_t) +#define MAX_IMAGE_BYTES (8 * 1024 * 1024) DECLARE_GLOBAL_DATA_PTR; static LIST_HEAD(rockchip_display_list); @@ -76,6 +80,61 @@ struct public_phy_data { bool phy_init; }; +char* rockchip_get_output_if_name(u32 output_if, char *name) +{ + if (output_if & VOP_OUTPUT_IF_RGB) + strcat(name, " RGB"); + if (output_if & VOP_OUTPUT_IF_BT1120) + strcat(name, " BT1120"); + if (output_if & VOP_OUTPUT_IF_BT656) + strcat(name, " BT656"); + if (output_if & VOP_OUTPUT_IF_LVDS0) + strcat(name, " LVDS0"); + if (output_if & VOP_OUTPUT_IF_LVDS1) + strcat(name, " LVDS1"); + if (output_if & VOP_OUTPUT_IF_MIPI0) + strcat(name, " MIPI0"); + if (output_if & VOP_OUTPUT_IF_MIPI1) + strcat(name, " MIPI1"); + if (output_if & VOP_OUTPUT_IF_eDP0) + strcat(name, " eDP0"); + if (output_if & VOP_OUTPUT_IF_eDP1) + strcat(name, " eDP1"); + if (output_if & VOP_OUTPUT_IF_DP0) + strcat(name, " DP0"); + if (output_if & VOP_OUTPUT_IF_DP1) + strcat(name, " DP1"); + if (output_if & VOP_OUTPUT_IF_HDMI0) + strcat(name, " HDMI0"); + if (output_if & VOP_OUTPUT_IF_HDMI1) + strcat(name, " HDMI1"); + + return name; +} + +u32 rockchip_drm_get_cycles_per_pixel(u32 bus_format) +{ + switch (bus_format) { + case MEDIA_BUS_FMT_RGB565_1X16: + case MEDIA_BUS_FMT_RGB666_1X18: + case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + return 1; + case MEDIA_BUS_FMT_RGB565_2X8_LE: + case MEDIA_BUS_FMT_BGR565_2X8_LE: + return 2; + case MEDIA_BUS_FMT_RGB666_3X6: + case MEDIA_BUS_FMT_RGB888_3X8: + case MEDIA_BUS_FMT_BGR888_3X8: + return 3; + case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: + case MEDIA_BUS_FMT_BGR888_DUMMY_4X8: + return 4; + default: + return 1; + } +} + int rockchip_get_baseparameter(void) { struct blk_desc *dev_desc; @@ -1082,12 +1141,13 @@ static int get_crtc_mcu_mode(struct crtc_state *crtc_state, struct device_node * return 0; } -struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp) +struct rockchip_logo_cache *find_or_alloc_logo_cache(const char *bmp, int rotate) { struct rockchip_logo_cache *tmp, *logo_cache = NULL; list_for_each_entry(tmp, &logo_cache_list, head) { - if (!strcmp(tmp->name, bmp)) { + if ((!strcmp(tmp->name, bmp) && rotate == tmp->logo_rotate) || + (soc_is_rk3566() && tmp->logo_rotate)) { logo_cache = tmp; break; } @@ -1143,7 +1203,8 @@ static int load_kernel_bmp_logo(struct logo_info *logo, const char *bmp_name) return 0; } -static int load_bmp_logo(struct logo_info *logo, const char *bmp_name) +#ifdef BMP_DECODEER_LEGACY +static int load_bmp_logo_legacy(struct logo_info *logo, const char *bmp_name) { #ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE struct rockchip_logo_cache *logo_cache; @@ -1156,7 +1217,7 @@ static int load_bmp_logo(struct logo_info *logo, const char *bmp_name) if (!logo || !bmp_name) return -EINVAL; - logo_cache = find_or_alloc_logo_cache(bmp_name); + logo_cache = find_or_alloc_logo_cache(bmp_name, logo->rotate); if (!logo_cache) return -ENOMEM; @@ -1244,6 +1305,227 @@ free_header: return -EINVAL; #endif } +#endif + +static void *bitmap_create(int width, int height, unsigned int state) +{ + /* Ensure a stupidly large bitmap is not created */ + if (width > 4096 || height > 4096) + return NULL; + + return calloc(width * height, BYTES_PER_PIXEL); +} + +static unsigned char *bitmap_get_buffer(void *bitmap) +{ + return bitmap; +} + +static void bitmap_destroy(void *bitmap) +{ + free(bitmap); +} + +static void bmp_copy(void *dst, bmp_image *bmp) +{ + u16 row, col; + u8 *image; + u8 *pdst = (u8 *)dst; + + image = (u8 *)bmp->bitmap; + for (row = 0; row != bmp->height; row++) { + for (col = 0; col != bmp->width; col++) { + size_t z = (row * bmp->width + col) * BYTES_PER_PIXEL; + + *pdst++ = image[z + 2]; + *pdst++ = image[z + 1]; + *pdst++ = image[z + 0]; + *pdst++ = image[z + 3]; + } + } +} + +static void *rockchip_logo_rotate(struct logo_info *logo, void *src) +{ + void *dst_rotate; + int width = logo->width; + int height = logo->height; + int width_rotate = logo->height & 0x3 ? (logo->height & ~0x3) + 4 : logo->height; + int height_rotate = logo->width; + int dst_size = width * height * logo->bpp >> 3; + int dst_size_rotate = width_rotate * height_rotate * logo->bpp >> 3; + int bytes_per_pixel = logo->bpp >> 3; + int padded_width; + int i, j; + char *img_data; + + if (!(logo->rotate == 90 || logo->rotate == 180 || logo->rotate == 270)) { + printf("Unsupported rotation angle\n"); + return NULL; + } + + img_data = (char *)malloc(dst_size); + if (!img_data) { + printf("failed to alloc memory for image data\n"); + return NULL; + } + memcpy(img_data, src, dst_size); + + dst_rotate = get_display_buffer(dst_size_rotate); + if (!dst_rotate) + return NULL; + memset(dst_rotate, 0, dst_size_rotate); + + switch (logo->rotate) { + case 90: + logo->width = width_rotate; + logo->height = height_rotate; + padded_width = height & 0x3 ? (height & ~0x3) + 4 : height; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + memcpy(dst_rotate + (j * padded_width * bytes_per_pixel) + + (height - i - 1) * bytes_per_pixel, + img_data + i * width * bytes_per_pixel + j * bytes_per_pixel, + bytes_per_pixel); + } + } + break; + case 180: + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + memcpy(dst_rotate + (height - i - 1) * width * bytes_per_pixel + + (width - j - 1) * bytes_per_pixel, + img_data + i * width * bytes_per_pixel + j * bytes_per_pixel, + bytes_per_pixel); + } + } + break; + case 270: + logo->width = width_rotate; + logo->height = height_rotate; + padded_width = height & 0x3 ? (height & ~0x3) + 4 : height; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) { + memcpy(dst_rotate + (width - j - 1) * padded_width * bytes_per_pixel + + i * bytes_per_pixel, + img_data + i * width * bytes_per_pixel + j * bytes_per_pixel, + bytes_per_pixel); + } + } + break; + default: + break; + } + + free(img_data); + + return dst_rotate; +} + +static int load_bmp_logo(struct logo_info *logo, const char *bmp_name) +{ +#ifdef CONFIG_ROCKCHIP_RESOURCE_IMAGE + struct rockchip_logo_cache *logo_cache; + bmp_bitmap_callback_vt bitmap_callbacks = { + bitmap_create, + bitmap_destroy, + bitmap_get_buffer, + }; + bmp_result code; + bmp_image bmp; + void *bmp_data; + void *dst = NULL; + void *dst_rotate = NULL; + int len, dst_size; + int ret = 0; + + if (!logo || !bmp_name) + return -EINVAL; + + logo_cache = find_or_alloc_logo_cache(bmp_name, logo->rotate); + if (!logo_cache) + return -ENOMEM; + + if (logo_cache->logo.mem) { + memcpy(logo, &logo_cache->logo, sizeof(*logo)); + return 0; + } + + bmp_data = malloc(MAX_IMAGE_BYTES); + if (!bmp_data) + return -ENOMEM; + + bmp_create(&bmp, &bitmap_callbacks); + + len = rockchip_read_resource_file(bmp_data, bmp_name, 0, MAX_IMAGE_BYTES); + if (len < 0) { + ret = -EINVAL; + goto free_bmp_data; + } + + /* analyse the BMP */ + code = bmp_analyse(&bmp, len, bmp_data); + if (code != BMP_OK) { + printf("failed to parse bmp:%s header\n", bmp_name); + ret = -EINVAL; + goto free_bmp_data; + } + /* fix bpp to 32 */ + logo->bpp = 32; + logo->offset = 0; + logo->ymirror = 0; + logo->width = get_unaligned_le32(&bmp.width); + logo->height = get_unaligned_le32(&bmp.height); + dst_size = logo->width * logo->height * logo->bpp >> 3; + /* decode the image to RGBA8888 format */ + code = bmp_decode(&bmp); + if (code != BMP_OK) { + /* allow partially decoded images */ + if (code != BMP_INSUFFICIENT_DATA && code != BMP_DATA_ERROR) { + printf("failed to allocate the buffer of bmp:%s\n", bmp_name); + ret = -EINVAL; + goto free_bmp_data; + } + + /* skip if the partially decoded image would be ridiculously large */ + if ((bmp.width * bmp.height) > 200000) { + printf("partially decoded bmp:%s can not be too large\n", bmp_name); + ret = -EINVAL; + goto free_bmp_data; + } + } + + dst = get_display_buffer(dst_size); + if (!dst) { + ret = -ENOMEM; + goto free_bmp_data; + } + bmp_copy(dst, &bmp); + + if (logo->rotate) { + dst_rotate = rockchip_logo_rotate(logo, dst); + if (dst_rotate) { + dst = dst_rotate; + dst_size = logo->width * logo->height * logo->bpp >> 3; + } + printf("logo ratate %d\n", logo->rotate); + } + logo->mem = dst; + + memcpy(&logo_cache->logo, logo, sizeof(*logo)); + logo_cache->logo_rotate = logo->rotate; + + flush_dcache_range((ulong)dst, ALIGN((ulong)dst + dst_size, CONFIG_SYS_CACHELINE_SIZE)); +free_bmp_data: + /* clean up */ + bmp_finalise(&bmp); + free(bmp_data); + + return ret; +#else + return -EINVAL; +#endif +} void rockchip_show_fbbase(ulong fbbase) { @@ -1291,6 +1573,7 @@ int rockchip_show_logo(void) list_for_each_entry(s, &rockchip_display_list, head) { s->logo.mode = s->logo_mode; + s->logo.rotate = s->logo_rotate; if (load_bmp_logo(&s->logo, s->ulogo_name)) { printf("failed to display uboot logo\n"); } else { @@ -1354,7 +1637,7 @@ enum { PORT_DIR_OUT, }; -static const struct device_node *rockchip_of_graph_get_port_by_id(ofnode node, int id) +const struct device_node *rockchip_of_graph_get_port_by_id(ofnode node, int id) { ofnode ports, port; u32 reg; @@ -1611,6 +1894,7 @@ static struct rockchip_connector *rockchip_get_split_connector(struct rockchip_c int ret; split_mode = ofnode_read_bool(conn->dev->node, "split-mode"); + split_mode |= ofnode_read_bool(conn->dev->node, "dual-channel"); if (!split_mode) return NULL; @@ -1624,6 +1908,9 @@ static struct rockchip_connector *rockchip_get_split_connector(struct rockchip_c case DRM_MODE_CONNECTOR_HDMIA: conn_name = "hdmi"; break; + case DRM_MODE_CONNECTOR_LVDS: + conn_name = "lvds"; + break; default: return NULL; } @@ -1850,6 +2137,8 @@ static int rockchip_display_probe(struct udevice *dev) else s->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER; + s->logo_rotate = ofnode_read_u32_default(node, "logo,rotate", 0); + s->force_output = ofnode_read_bool(node, "force-output"); if (s->force_output) { @@ -2035,7 +2324,8 @@ void rockchip_display_fixup(void *blob) continue; } - if (s->conn_state.secondary) { + if (s->conn_state.secondary && + s->conn_state.secondary->type != DRM_MODE_CONNECTOR_LVDS) { s->conn_state.mode.clock *= 2; s->conn_state.mode.hdisplay *= 2; } diff --git a/u-boot/drivers/video/drm/rockchip_display.h b/u-boot/drivers/video/drm/rockchip_display.h index 8447871c68..82789ca1df 100644 --- a/u-boot/drivers/video/drm/rockchip_display.h +++ b/u-boot/drivers/video/drm/rockchip_display.h @@ -253,6 +253,7 @@ struct connector_state { struct logo_info { int mode; + int rotate; char *mem; bool ymirror; u32 offset; @@ -265,6 +266,7 @@ struct rockchip_logo_cache { struct list_head head; char name[20]; struct logo_info logo; + int logo_rotate; }; struct display_state { @@ -283,6 +285,7 @@ struct display_state { struct logo_info logo; int logo_mode; int charge_logo_mode; + int logo_rotate; void *mem_base; int mem_size; @@ -317,6 +320,10 @@ int display_rect_calc_vscale(struct display_rect *src, struct display_rect *dst, int min_vscale, int max_vscale); const struct device_node * rockchip_of_graph_get_endpoint_by_regs(ofnode node, int port, int endpoint); +const struct device_node * +rockchip_of_graph_get_port_by_id(ofnode node, int id); +uint32_t rockchip_drm_get_cycles_per_pixel(uint32_t bus_format); +char* rockchip_get_output_if_name(u32 output_if, char *name); #ifdef CONFIG_SPL_BUILD int rockchip_spl_vop_probe(struct crtc_state *crtc_state); diff --git a/u-boot/drivers/video/drm/rockchip_dw_hdmi_qp.c b/u-boot/drivers/video/drm/rockchip_dw_hdmi_qp.c index 76971600f7..f5d3cfdfa2 100644 --- a/u-boot/drivers/video/drm/rockchip_dw_hdmi_qp.c +++ b/u-boot/drivers/video/drm/rockchip_dw_hdmi_qp.c @@ -1063,7 +1063,8 @@ null_basep: hdmi_select_link_config(hdmi, edid_data->preferred_mode, tmdsclk); dw_hdmi_qp_dsc_configure(hdmi, edid_data->preferred_mode); if (hdmi->link_cfg.frl_mode) { - dm_gpio_set_value(&hdmi->enable_gpio, 0); + if (dm_gpio_is_valid(&hdmi->enable_gpio)) + dm_gpio_set_value(&hdmi->enable_gpio, 0); /* in the current version, support max 40G frl */ if (hdmi->link_cfg.rate_per_lane >= 10) { hdmi->link_cfg.frl_lanes = 4; @@ -1078,7 +1079,8 @@ null_basep: else hdmi->bus_width |= HDMI_FRL_MODE; } else { - dm_gpio_set_value(&hdmi->enable_gpio, 1); + if (dm_gpio_is_valid(&hdmi->enable_gpio)) + dm_gpio_set_value(&hdmi->enable_gpio, 1); hdmi->bus_width = hdmi_get_tmdsclock(hdmi, pixel_clk * 10); if (hdmi_bus_fmt_is_yuv420(*bus_format)) diff --git a/u-boot/drivers/video/drm/rockchip_lvds.c b/u-boot/drivers/video/drm/rockchip_lvds.c index d7acbe48ce..d930de7009 100644 --- a/u-boot/drivers/video/drm/rockchip_lvds.c +++ b/u-boot/drivers/video/drm/rockchip_lvds.c @@ -21,6 +21,7 @@ #include "rockchip_connector.h" #include "rockchip_phy.h" #include "rockchip_panel.h" +#include "drm_of.h" #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16)) @@ -90,6 +91,7 @@ enum lvds_format { struct rockchip_lvds; struct rockchip_lvds_funcs { + int (*probe)(struct rockchip_lvds *lvds); void (*enable)(struct rockchip_lvds *lvds, int pipe); void (*disable)(struct rockchip_lvds *lvds); }; @@ -105,12 +107,14 @@ struct rockchip_lvds { enum lvds_format format; bool data_swap; bool dual_channel; + enum drm_lvds_dual_link_pixels pixel_order; }; static int rockchip_lvds_connector_init(struct rockchip_connector *conn, struct display_state *state) { struct rockchip_lvds *lvds = dev_get_priv(conn->dev); + struct rockchip_lvds *primary_lvds = NULL; struct connector_state *conn_state = &state->conn_state; struct rockchip_panel *panel = conn->panel; @@ -118,6 +122,9 @@ static int rockchip_lvds_connector_init(struct rockchip_connector *conn, lvds->phy = conn->phy; conn_state->disp_info = rockchip_get_disp_info(conn_state->type, lvds->id); + if (conn_state->secondary) + primary_lvds = dev_get_priv(conn_state->connector->dev); + switch (panel->bus_format) { case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA: /* jeida-18 */ lvds->format = LVDS_6BIT_MODE; @@ -139,6 +146,7 @@ static int rockchip_lvds_connector_init(struct rockchip_connector *conn, break; } + conn_state->bus_format = panel->bus_format; conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; if ((lvds->format == LVDS_10BIT_MODE_FORMAT_1) || @@ -146,7 +154,46 @@ static int rockchip_lvds_connector_init(struct rockchip_connector *conn, conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA; conn_state->color_space = V4L2_COLORSPACE_DEFAULT; - conn_state->output_if = VOP_OUTPUT_IF_LVDS0; + if (primary_lvds) { + conn_state->output_flags = 0; + conn_state->output_if = 0; + + switch (primary_lvds->pixel_order) { + case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: + conn_state->output_flags |= + ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE; + conn_state->output_if |= + VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; + break; + case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: + conn_state->output_flags |= + ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE; + conn_state->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; + conn_state->output_if |= + VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; + break; + case DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS: + conn_state->output_flags |= + ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; + conn_state->output_if |= + VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; + break; + case DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS: + conn_state->output_flags |= + ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; + conn_state->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; + conn_state->output_if |= + VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; + break; + default: + break; + } + } + + if (lvds->id) + conn_state->output_if |= VOP_OUTPUT_IF_LVDS1; + else + conn_state->output_if |= VOP_OUTPUT_IF_LVDS0; return 0; } @@ -205,6 +252,10 @@ static int rockchip_lvds_probe(struct udevice *dev) if (lvds->id < 0) lvds->id = 0; + lvds->pixel_order = -1; + if (lvds->funcs->probe) + lvds->funcs->probe(lvds); + rockchip_connector_bind(&lvds->connector, dev, lvds->id, &rockchip_lvds_connector_funcs, NULL, DRM_MODE_CONNECTOR_LVDS); @@ -329,21 +380,61 @@ static const struct rockchip_lvds_funcs rk3562_lvds_funcs = { .disable = rk3562_lvds_disable, }; +static int rk3568_lvds_probe(struct rockchip_lvds *lvds) +{ + if (lvds->dual_channel) { + const struct device_node *port0, *port1; + int pixel_order; + + port1 = of_alias_get_dev("lvds", 1); + if (!port1 || !of_device_is_available(port1)) { + lvds->pixel_order = 0; + return 0; + } + + port0 = rockchip_of_graph_get_port_by_id(lvds->dev->node, 1); + port1 = rockchip_of_graph_get_port_by_id(np_to_ofnode(port1), + 1); + pixel_order = + drm_of_lvds_get_dual_link_pixel_order(port0, port1); + + lvds->pixel_order = pixel_order >= 0 ? pixel_order : 0; + } + + return 0; +} + static void rk3568_lvds_enable(struct rockchip_lvds *lvds, int pipe) { - regmap_write(lvds->grf, RK3568_GRF_VO_CON2, - RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) | - RK3568_LVDS0_DCLK_INV_SEL(1)); - regmap_write(lvds->grf, RK3568_GRF_VO_CON0, - RK3568_LVDS0_SELECT(lvds->format) | RK3568_LVDS0_MSBSEL(1)); + if (lvds->id) { + regmap_write(lvds->grf, RK3568_GRF_VO_CON3, + RK3568_LVDS1_MODE_EN(1) | RK3568_LVDS1_P2S_EN(1) | + RK3568_LVDS1_DCLK_INV_SEL(1)); + regmap_write(lvds->grf, RK3568_GRF_VO_CON0, + RK3568_LVDS1_SELECT(lvds->format) | + RK3568_LVDS1_MSBSEL(1)); + } else { + regmap_write(lvds->grf, RK3568_GRF_VO_CON2, + RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) | + RK3568_LVDS0_DCLK_INV_SEL(1)); + regmap_write(lvds->grf, RK3568_GRF_VO_CON0, + RK3568_LVDS0_SELECT(lvds->format) | + RK3568_LVDS0_MSBSEL(1)); + } } static void rk3568_lvds_disable(struct rockchip_lvds *lvds) { - regmap_write(lvds->grf, RK3568_GRF_VO_CON2, RK3568_LVDS0_MODE_EN(0)); + if (lvds->id) + regmap_write(lvds->grf, RK3568_GRF_VO_CON3, + RK3568_LVDS1_MODE_EN(0)); + else + regmap_write(lvds->grf, RK3568_GRF_VO_CON2, + RK3568_LVDS0_MODE_EN(0)); } static const struct rockchip_lvds_funcs rk3568_lvds_funcs = { + .probe = rk3568_lvds_probe, .enable = rk3568_lvds_enable, .disable = rk3568_lvds_disable, }; diff --git a/u-boot/drivers/video/drm/rockchip_rgb.c b/u-boot/drivers/video/drm/rockchip_rgb.c index 35c9cf8ba1..116ac246d6 100644 --- a/u-boot/drivers/video/drm/rockchip_rgb.c +++ b/u-boot/drivers/video/drm/rockchip_rgb.c @@ -659,6 +659,9 @@ static const struct udevice_id rockchip_rgb_ids[] = { .compatible = "rockchip,rk3568-rgb", .data = (ulong)&rk3568_rgb_funcs, }, + { + .compatible = "rockchip,rk3588-rgb", + }, { .compatible = "rockchip,rv1106-rgb", .data = (ulong)&rv1106_rgb_funcs, diff --git a/u-boot/drivers/video/drm/rockchip_vop.c b/u-boot/drivers/video/drm/rockchip_vop.c index 11bbae5dd1..6d29298225 100644 --- a/u-boot/drivers/video/drm/rockchip_vop.c +++ b/u-boot/drivers/video/drm/rockchip_vop.c @@ -255,6 +255,7 @@ static int rockchip_vop_init(struct display_state *state) bool yuv_overlay = false, post_r2y_en = false, post_y2r_en = false; u16 post_csc_mode; bool dclk_inv; + char output_type_name[30] = {0}; vop = malloc(sizeof(*vop)); if (!vop) @@ -278,6 +279,12 @@ static int rockchip_vop_init(struct display_state *state) vop->win_csc = vop_data->win_csc; vop->version = vop_data->version; + printf("VOP:0x%8p update mode to: %dx%d%s%d, type:%s\n", + vop->regs, mode->crtc_hdisplay, mode->vdisplay, + mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", + mode->vrefresh, + rockchip_get_output_if_name(conn_state->output_if, output_type_name)); + /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ ret = clk_set_defaults(crtc_state->dev); if (ret) @@ -285,11 +292,12 @@ static int rockchip_vop_init(struct display_state *state) ret = clk_get_by_name(crtc_state->dev, "dclk_vop", &dclk); if (!ret) - ret = clk_set_rate(&dclk, mode->clock * 1000); + ret = clk_set_rate(&dclk, mode->crtc_clock * 1000); if (IS_ERR_VALUE(ret)) { printf("%s: Failed to set dclk: ret=%d\n", __func__, ret); return ret; } + printf("VOP:0x%8p set crtc_clock to %dKHz\n", vop->regs, mode->crtc_clock); memcpy(vop->regsbak, vop->regs, vop_data->reg_len); @@ -904,11 +912,16 @@ static int rockchip_vop_plane_check(struct display_state *state) static int rockchip_vop_mode_fixup(struct display_state *state) { + struct crtc_state *crtc_state = &state->crtc_state; struct connector_state *conn_state = &state->conn_state; struct drm_display_mode *mode = &conn_state->mode; drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V | CRTC_STEREO_DOUBLE); + mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format); + if (crtc_state->mcu_timing.mcu_pix_total) + mode->crtc_clock *= crtc_state->mcu_timing.mcu_pix_total + 1; + return 0; } diff --git a/u-boot/drivers/video/drm/rockchip_vop2.c b/u-boot/drivers/video/drm/rockchip_vop2.c index 33de5eae18..eb11f1ab38 100644 --- a/u-boot/drivers/video/drm/rockchip_vop2.c +++ b/u-boot/drivers/video/drm/rockchip_vop2.c @@ -86,10 +86,14 @@ #define RK3568_DSP_IF_CTRL 0x02c #define LVDS_DUAL_EN_SHIFT 0 +#define RK3588_BT656_UV_SWAP_SHIFT 0 #define LVDS_DUAL_LEFT_RIGHT_EN_SHIFT 1 +#define RK3588_BT656_YC_SWAP_SHIFT 1 #define LVDS_DUAL_SWAP_EN_SHIFT 2 #define BT656_UV_SWAP 4 +#define RK3588_BT1120_UV_SWAP_SHIFT 4 #define BT656_YC_SWAP 5 +#define RK3588_BT1120_YC_SWAP_SHIFT 5 #define BT656_DCLK_POL 6 #define RK3588_HDMI_DUAL_EN_SHIFT 8 #define RK3588_EDP_DUAL_EN_SHIFT 8 @@ -879,6 +883,9 @@ #define GRF_BT1120_CLK_INV_SHIFT 2 #define GRF_RGB_DCLK_INV_SHIFT 3 +#define RK3588_GRF_SOC_CON1 0x0304 +#define RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT 14 + #define RK3588_GRF_VOP_CON2 0x0008 #define RK3588_GRF_EDP0_ENABLE_SHIFT 0 #define RK3588_GRF_HDMITX0_ENABLE_SHIFT 1 @@ -1415,38 +1422,6 @@ static inline u32 vop2_grf_readl(struct vop2 *vop, void *grf_base, u32 offset, return (readl(grf_base + offset) >> shift) & mask; } -static char* get_output_if_name(u32 output_if, char *name) -{ - if (output_if & VOP_OUTPUT_IF_RGB) - strcat(name, " RGB"); - if (output_if & VOP_OUTPUT_IF_BT1120) - strcat(name, " BT1120"); - if (output_if & VOP_OUTPUT_IF_BT656) - strcat(name, " BT656"); - if (output_if & VOP_OUTPUT_IF_LVDS0) - strcat(name, " LVDS0"); - if (output_if & VOP_OUTPUT_IF_LVDS1) - strcat(name, " LVDS1"); - if (output_if & VOP_OUTPUT_IF_MIPI0) - strcat(name, " MIPI0"); - if (output_if & VOP_OUTPUT_IF_MIPI1) - strcat(name, " MIPI1"); - if (output_if & VOP_OUTPUT_IF_eDP0) - strcat(name, " eDP0"); - if (output_if & VOP_OUTPUT_IF_eDP1) - strcat(name, " eDP1"); - if (output_if & VOP_OUTPUT_IF_DP0) - strcat(name, " DP0"); - if (output_if & VOP_OUTPUT_IF_DP1) - strcat(name, " DP1"); - if (output_if & VOP_OUTPUT_IF_HDMI0) - strcat(name, " HDMI0"); - if (output_if & VOP_OUTPUT_IF_HDMI1) - strcat(name, " HDMI1"); - - return name; -} - static char *get_plane_name(int plane_id, char *name) { switch (plane_id) { @@ -1584,6 +1559,19 @@ static bool is_rb_swap(u32 bus_format, u32 output_mode) return false; } +static bool is_yc_swap(u32 bus_format) +{ + switch (bus_format) { + case MEDIA_BUS_FMT_YUYV8_1X16: + case MEDIA_BUS_FMT_YVYU8_1X16: + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + return true; + default: + return false; + } +} + static inline bool is_hot_plug_devices(int output_type) { switch (output_type) { @@ -2540,6 +2528,7 @@ static int rockchip_vop2_preinit(struct display_state *state) { struct crtc_state *cstate = &state->crtc_state; const struct vop2_data *vop2_data = cstate->crtc->data; + struct regmap *map; if (!rockchip_vop2) { rockchip_vop2 = calloc(1, sizeof(struct vop2)); @@ -2552,23 +2541,24 @@ static int rockchip_vop2_preinit(struct display_state *state) rockchip_vop2->regs = (void *)RK3528_VOP_BASE; #else rockchip_vop2->regs = dev_read_addr_ptr(cstate->dev); - rockchip_vop2->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,grf"); + rockchip_vop2->grf = regmap_get_range(map, 0); if (rockchip_vop2->grf <= 0) printf("%s: Get syscon grf failed (ret=%p)\n", __func__, rockchip_vop2->grf); #endif rockchip_vop2->version = vop2_data->version; rockchip_vop2->data = vop2_data; if (rockchip_vop2->version == VOP_VERSION_RK3588) { - struct regmap *map; - - rockchip_vop2->vop_grf = syscon_get_first_range(ROCKCHIP_SYSCON_VOP_GRF); + map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vop-grf"); + rockchip_vop2->vop_grf = regmap_get_range(map, 0); if (rockchip_vop2->vop_grf <= 0) printf("%s: Get syscon vop_grf failed (ret=%p)\n", __func__, rockchip_vop2->vop_grf); map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,vo1-grf"); rockchip_vop2->vo1_grf = regmap_get_range(map, 0); if (rockchip_vop2->vo1_grf <= 0) printf("%s: Get syscon vo1_grf failed (ret=%p)\n", __func__, rockchip_vop2->vo1_grf); - rockchip_vop2->sys_pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU); + map = syscon_regmap_lookup_by_phandle(cstate->dev, "rockchip,pmu"); + rockchip_vop2->sys_pmu = regmap_get_range(map, 0); if (rockchip_vop2->sys_pmu <= 0) printf("%s: Get syscon sys_pmu failed (ret=%p)\n", __func__, rockchip_vop2->sys_pmu); } @@ -2770,8 +2760,10 @@ static unsigned long rk3588_vop2_if_cfg(struct display_state *state) int if_pixclk_div = 0; int if_dclk_div = 0; unsigned long dclk_rate; + bool dclk_inv, yc_swap = false; u32 val; + dclk_inv = (conn_state->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) ? 1 : 0; if (output_if & (VOP_OUTPUT_IF_HDMI0 | VOP_OUTPUT_IF_HDMI1)) { val = (mode->flags & DRM_MODE_FLAG_NHSYNC) ? BIT(HSYNC_POSITIVE) : 0; val |= (mode->flags & DRM_MODE_FLAG_NVSYNC) ? BIT(VSYNC_POSITIVE) : 0; @@ -2806,16 +2798,28 @@ static unsigned long rk3588_vop2_if_cfg(struct display_state *state) if (output_if & VOP_OUTPUT_IF_RGB) { vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 4, false); + vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, + RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); } if (output_if & VOP_OUTPUT_IF_BT1120) { vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 3, false); + vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, + RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); + yc_swap = is_yc_swap(conn_state->bus_format); + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT1120_YC_SWAP_SHIFT, + yc_swap, false); } if (output_if & VOP_OUTPUT_IF_BT656) { vop2_mask_write(vop2, RK3568_DSP_IF_EN, 0x7, RK3588_RGB_EN_SHIFT, 2, false); + vop2_grf_writel(vop2, vop2->grf, RK3588_GRF_SOC_CON1, EN_MASK, + RK3588_GRF_VOP_DCLK_INV_SEL_SHIFT, !dclk_inv); + yc_swap = is_yc_swap(conn_state->bus_format); + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, RK3588_BT656_YC_SWAP_SHIFT, + yc_swap, false); } if (output_if & VOP_OUTPUT_IF_MIPI0) { @@ -2989,13 +2993,47 @@ static unsigned long rk3588_vop2_if_cfg(struct display_state *state) return dclk_rate; } +static void rk3568_vop2_setup_dual_channel_if(struct display_state *state) +{ + struct crtc_state *cstate = &state->crtc_state; + struct connector_state *conn_state = &state->conn_state; + struct vop2 *vop2 = cstate->private; + u32 vp_offset = (cstate->crtc_id * 0x100); + + if (conn_state->output_flags & + ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) { + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, + LVDS_DUAL_EN_SHIFT, 1, false); + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, + LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 0, false); + if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, + LVDS_DUAL_SWAP_EN_SHIFT, 1, false); + + return; + } + + vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, + MIPI_DUAL_EN_SHIFT, 1, false); + if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) { + vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, + MIPI_DUAL_SWAP_EN_SHIFT, 1, false); + } + + if (conn_state->output_if & VOP_OUTPUT_IF_LVDS1) { + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, + LVDS_DUAL_EN_SHIFT, 1, false); + vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, + LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, false); + } +} + static unsigned long rk3568_vop2_if_cfg(struct display_state *state) { struct crtc_state *cstate = &state->crtc_state; struct connector_state *conn_state = &state->conn_state; struct drm_display_mode *mode = &conn_state->mode; struct vop2 *vop2 = cstate->private; - u32 vp_offset = (cstate->crtc_id * 0x100); bool dclk_inv; u32 val; @@ -3056,20 +3094,6 @@ static unsigned long rk3568_vop2_if_cfg(struct display_state *state) IF_CTRL_RGB_LVDS_DCLK_POL_SHIFT, dclk_inv, false); } - if (conn_state->output_flags & - (ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE | - ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE)) { - vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, - LVDS_DUAL_EN_SHIFT, 1, false); - if (conn_state->output_flags & - ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) - vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, - LVDS_DUAL_LEFT_RIGHT_EN_SHIFT, 1, - false); - if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) - vop2_mask_write(vop2, RK3568_DSP_IF_CTRL, EN_MASK, - LVDS_DUAL_SWAP_EN_SHIFT, 1, false); - } if (conn_state->output_if & VOP_OUTPUT_IF_MIPI0) { vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, MIPI0_EN_SHIFT, @@ -3090,14 +3114,10 @@ static unsigned long rk3568_vop2_if_cfg(struct display_state *state) } if (conn_state->output_flags & - ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) { - vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, EN_MASK, - MIPI_DUAL_EN_SHIFT, 1, false); - if (conn_state->output_flags & ROCKCHIP_OUTPUT_DATA_SWAP) - vop2_mask_write(vop2, RK3568_VP0_MIPI_CTRL + vp_offset, - EN_MASK, MIPI_DUAL_SWAP_EN_SHIFT, 1, - false); - } + ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || + conn_state->output_flags & + ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) + rk3568_vop2_setup_dual_channel_if(state); if (conn_state->output_if & VOP_OUTPUT_IF_eDP0) { vop2_mask_write(vop2, RK3568_DSP_IF_EN, EN_MASK, EDP0_EN_SHIFT, @@ -3122,7 +3142,7 @@ static unsigned long rk3568_vop2_if_cfg(struct display_state *state) IF_CRTL_HDMI_PIN_POL_SHIT, val, false); } - return mode->clock; + return mode->crtc_clock; } static unsigned long rk3528_vop2_if_cfg(struct display_state *state) @@ -3636,18 +3656,6 @@ static int rockchip_vop2_send_mcu_cmd(struct display_state *state, u32 type, u32 return 0; } -static int vop2_get_vrefresh(struct display_state *state) -{ - struct crtc_state *cstate = &state->crtc_state; - struct connector_state *conn_state = &state->conn_state; - struct drm_display_mode *mode = &conn_state->mode; - - if (cstate->mcu_timing.mcu_pix_total) - return mode->vrefresh / cstate->mcu_timing.mcu_pix_total; - else - return mode->vrefresh; -} - static void vop2_dither_setup(struct vop2 *vop2, int bus_format, int crtc_id) { u32 vp_offset = crtc_id * 0x100; @@ -3739,8 +3747,8 @@ static int rockchip_vop2_init(struct display_state *state) printf("VOP update mode to: %dx%d%s%d, type:%s for VP%d\n", mode->crtc_hdisplay, mode->vdisplay, mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "p", - vop2_get_vrefresh(state), - get_output_if_name(conn_state->output_if, output_type_name), + mode->vrefresh, + rockchip_get_output_if_name(conn_state->output_if, output_type_name), cstate->crtc_id); if (mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { @@ -3771,8 +3779,9 @@ static int rockchip_vop2_init(struct display_state *state) else if (vop2->version == VOP_VERSION_RK3562) dclk_rate = rk3562_vop2_if_cfg(state); - if (conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && - !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) + if ((conn_state->output_mode == ROCKCHIP_OUT_MODE_AAAA && + !(cstate->feature & VOP_FEATURE_OUTPUT_10BIT)) || + conn_state->output_if & VOP_OUTPUT_IF_BT656) conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; vop2_post_color_swap(state); @@ -3962,12 +3971,12 @@ static int rockchip_vop2_init(struct display_state *state) __func__, cstate->crtc_id, dclk_rate, ret); return ret; } else { - dclk_div_factor = mode->clock / dclk_rate; - if (vop2->version == VOP_VERSION_RK3528 && - conn_state->output_if & VOP_OUTPUT_IF_BT656) - mode->crtc_clock = ret / 4 / 1000; - else - mode->crtc_clock = ret * dclk_div_factor / 1000; + if (cstate->mcu_timing.mcu_pix_total) { + mode->crtc_clock = roundup(ret, 1000) / 1000; + } else { + dclk_div_factor = mode->crtc_clock / dclk_rate; + mode->crtc_clock = roundup(ret, 1000) * dclk_div_factor / 1000; + } printf("VP%d set crtc_clock to %dKHz\n", cstate->crtc_id, mode->crtc_clock); } @@ -4005,12 +4014,30 @@ static void vop2_setup_scale(struct vop2 *vop2, struct vop2_win_data *win, } } - if (src_h >= (4 * dst_h)) { - ygt4 = 1; - src_h >>= 2; - } else if (src_h >= (2 * dst_h)) { - ygt2 = 1; - src_h >>= 1; + /** + * The rk3528 is processed as 2 pixel/cycle, + * so ygt2/ygt4 needs to be triggered in advance to improve performance + * when src_w is bigger than 1920. + * dst_h / src_h is at [1, 0.65) ygt2=0; ygt4=0; + * dst_h / src_h is at [0.65, 0.35) ygt2=1; ygt4=0; + * dst_h / src_h is at [0.35, 0) ygt2=0; ygt4=1; + */ + if (vop2->version == VOP_VERSION_RK3528 && src_w > 1920) { + if (src_h >= (100 * dst_h / 35)) { + ygt4 = 1; + src_h >>= 2; + } else if ((src_h >= 100 * dst_h / 65) && (src_h < 100 * dst_h / 35)) { + ygt2 = 1; + src_h >>= 1; + } + } else { + if (src_h >= (4 * dst_h)) { + ygt4 = 1; + src_h >>= 2; + } else if (src_h >= (2 * dst_h)) { + ygt2 = 1; + src_h >>= 1; + } } yrgb_hor_scl_mode = scl_get_scl_mode(src_w, dst_w); @@ -4702,22 +4729,12 @@ static int rockchip_vop2_mode_fixup(struct display_state *state) if (vop2->version == VOP_VERSION_RK3528 && conn_state->output_if & VOP_OUTPUT_IF_BT656) mode->crtc_clock *= 4; - if (cstate->mcu_timing.mcu_pix_total) { - if (conn_state->output_mode == ROCKCHIP_OUT_MODE_S888) - /* - * For serial output_mode rgb3x8, one pixel need 3 cycles. - * So dclk should be three times mode clock. - */ - mode->crtc_clock *= 3; - else if (conn_state->output_mode == ROCKCHIP_OUT_MODE_S888_DUMMY) - /* - * For serial output_mode argb4x8, one pixel need 4 cycles. - * So dclk should be four times mode clock. - */ - mode->crtc_clock *= 4; - } + mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format); + if (cstate->mcu_timing.mcu_pix_total) + mode->crtc_clock *= cstate->mcu_timing.mcu_pix_total + 1; - if (conn_state->secondary) { + if (conn_state->secondary && + conn_state->secondary->type != DRM_MODE_CONNECTOR_LVDS) { mode->crtc_clock *= 2; mode->crtc_hdisplay *= 2; mode->crtc_hsync_start *= 2; diff --git a/u-boot/drivers/video/drm/samsung_mipi_dcphy.c b/u-boot/drivers/video/drm/samsung_mipi_dcphy.c index f4cae1f1c7..1310553947 100644 --- a/u-boot/drivers/video/drm/samsung_mipi_dcphy.c +++ b/u-boot/drivers/video/drm/samsung_mipi_dcphy.c @@ -1540,6 +1540,9 @@ static void samsung_mipi_dphy_power_on(struct samsung_mipi_dcphy *samsung) samsung_mipi_dphy_lane_enable(samsung); reset_deassert(&samsung->m_phy_rst); + + /* The Tskewcal maximum is 100 usec at initial calibration. */ + udelay(100); } static void samsung_mipi_cphy_power_on(struct samsung_mipi_dcphy *samsung) diff --git a/u-boot/env/envf.c b/u-boot/env/envf.c index fc55afd0d4..a29351f37c 100644 --- a/u-boot/env/envf.c +++ b/u-boot/env/envf.c @@ -24,6 +24,12 @@ DECLARE_GLOBAL_DATA_PTR; #define BLK_CNT(desc, sz) ((sz) / (desc)->blksz) #define ENVF_MAX 64 +/* + * env_dev maybe: boot-device, sdcard. + * + * env_size/offset/offset_redund should be updated when env_dev changed. + */ +static u32 env_dev; static ulong env_size, env_offset, env_offset_redund; #if CONFIG_IS_ENABLED(ENV_PARTITION) @@ -75,6 +81,9 @@ static int can_find_pmbr(struct blk_desc *dev_desc) static void envf_init_location(struct blk_desc *desc) { + if (env_dev == ((desc->if_type << 8) | desc->devnum)) + return; + /* eMMC (default) */ env_size = CONFIG_ENV_SIZE; env_offset = CONFIG_ENV_OFFSET; @@ -99,6 +108,8 @@ static void envf_init_location(struct blk_desc *desc) #endif if (env_offset == env_offset_redund) env_offset_redund = 0; + + env_dev = (desc->if_type << 8) | desc->devnum; } static int env_read(struct blk_desc *desc, u32 offset, u32 size, env_t **envp) @@ -293,6 +304,8 @@ static int envf_save(void) return -EINVAL; } + envf_init_location(desc); + res = (char *)env->data; len = hexport_r(&env_htab, '\0', H_MATCH_KEY | H_MATCH_IDENT, &res, env_size - ENV_HEADER_SIZE, diff --git a/u-boot/include/abuf.h b/u-boot/include/abuf.h new file mode 100644 index 0000000000..d230f72806 --- /dev/null +++ b/u-boot/include/abuf.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Handles a buffer that can be allocated and freed + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __ABUF_H +#define __ABUF_H + +#include + +/** + * struct abuf - buffer that can be allocated and freed + * + * This is useful for a block of data which may be allocated with malloc(), or + * not, so that it needs to be freed correctly when finished with. + * + * For now it has a very simple purpose. + * + * Using memset() to zero all fields is guaranteed to be equivalent to + * abuf_init(). + * + * @data: Pointer to data + * @size: Size of data in bytes + * @alloced: true if allocated with malloc(), so must be freed after use + */ +struct abuf { + void *data; + size_t size; + bool alloced; +}; + +static inline void *abuf_data(const struct abuf *abuf) +{ + return abuf->data; +} + +static inline size_t abuf_size(const struct abuf *abuf) +{ + return abuf->size; +} + +/** + * abuf_set() - set the (unallocated) data in a buffer + * + * This simply makes the abuf point to the supplied data, which must be live + * for the lifetime of the abuf. It is not alloced. + * + * Any existing data in the abuf is freed and the alloced member is set to + * false. + * + * @abuf: abuf to adjust + * @data: New contents of abuf + * @size: New size of abuf + */ +void abuf_set(struct abuf *abuf, void *data, size_t size); + +/** + * abuf_map_sysmem() - calls map_sysmem() to set up an abuf + * + * This is equivalent to abuf_set(abuf, map_sysmem(addr, size), size) + * + * Any existing data in the abuf is freed and the alloced member is set to + * false. + * + * @abuf: abuf to adjust + * @addr: Address to set the abuf to + * @size: New size of abuf + */ +void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size); + +/** + * abuf_realloc() - Change the size of a buffer + * + * This uses realloc() to change the size of the buffer, with the same semantics + * as that function. If the abuf is not currently alloced, then it will alloc + * it if the size needs to increase (i.e. set the alloced member to true) + * + * @abuf: abuf to adjust + * @new_size: new size in bytes. + * if 0, the abuf is freed + * if greater than the current size, the abuf is extended and the new + * space is not inited. The alloced member is set to true + * if less than the current size, the abuf is contracted and the data at + * the end is lost. If @new_size is 0, this sets the alloced member to + * false + * @return true if OK, false if out of memory + */ +bool abuf_realloc(struct abuf *abuf, size_t new_size); + +/** + * abuf_uninit_move() - Return the allocated contents and uninit the abuf + * + * This returns the abuf data to the caller, allocating it if necessary, so that + * the caller receives data that it can be sure will hang around. The caller is + * responsible for freeing the data. + * + * If the abuf has allocated data, it is returned. If the abuf has data but it + * is not allocated, then it is first allocated, then returned. + * + * If the abuf size is 0, this returns NULL + * + * The abuf is uninited as part of this, except if the allocation fails, in + * which NULL is returned and the abuf remains untouched. + * + * The abuf must be inited before this can be called. + * + * @abuf: abuf to uninit + * @sizep: if non-NULL, returns the size of the returned data + * @return data contents, allocated with malloc(), or NULL if the data could not + * be allocated, or the data size is 0 + */ +void *abuf_uninit_move(struct abuf *abuf, size_t *sizep); + +/** + * abuf_init_move() - Make abuf take over the management of an allocated region + * + * After this, @data must not be used. All access must be via the abuf. + * + * @abuf: abuf to init + * @data: Existing allocated buffer to place in the abuf + * @size: Size of allocated buffer + */ +void abuf_init_move(struct abuf *abuf, void *data, size_t size); + +/** + * abuf_init_set() - Set up a new abuf + * + * Inits a new abuf and sets up its (unallocated) data + * + * @abuf: abuf to set up + * @data: New contents of abuf + * @size: New size of abuf + */ +void abuf_init_set(struct abuf *abuf, void *data, size_t size); + +/** + * abuf_uninit() - Free any memory used by an abuf + * + * The buffer must be inited before this can be called. + * + * @abuf: abuf to uninit + */ +void abuf_uninit(struct abuf *abuf); + +/** + * abuf_init() - Set up a new abuf + * + * This initially has no data and alloced is set to false. This is equivalent to + * setting all fields to 0, e.g. with memset(), so callers can do that instead + * if desired. + * + * @abuf: abuf to set up + */ +void abuf_init(struct abuf *abuf); + +#endif diff --git a/u-boot/include/attestation_key.h b/u-boot/include/attestation_key.h index 87b3abb89c..4a4e56f423 100644 --- a/u-boot/include/attestation_key.h +++ b/u-boot/include/attestation_key.h @@ -21,6 +21,7 @@ typedef enum { ATAP_RESULT_ERROR_INVALID_DEVICE_ID, ATAP_RESULT_ERROR_BUF_COPY, ATAP_RESULT_ERROR_STORAGE, + ATAP_RESULT_ERROR_ALREADY_EXSIT, } atap_result; /* load attestation key from misc partition. */ diff --git a/u-boot/include/configs/rk3528_common.h b/u-boot/include/configs/rk3528_common.h index ad81095a1a..78548bd36f 100644 --- a/u-boot/include/configs/rk3528_common.h +++ b/u-boot/include/configs/rk3528_common.h @@ -7,6 +7,8 @@ #ifndef __CONFIG_RK3528_COMMON_H #define __CONFIG_RK3528_COMMON_H +#define CFG_CPUID_OFFSET 0xa + #include "rockchip-common.h" #define CONFIG_SPL_FRAMEWORK @@ -71,6 +73,7 @@ /* usb mass storage */ #define CONFIG_USB_FUNCTION_MASS_STORAGE #define CONFIG_ROCKUSB_G_DNL_PID 0x350c +#define ROCKUSB_FSG_BUFLEN 0x400000 #ifdef CONFIG_ARM64 #define ENV_MEM_LAYOUT_SETTINGS \ diff --git a/u-boot/include/configs/rk3562_common.h b/u-boot/include/configs/rk3562_common.h index b076f90d6b..6d618db25e 100644 --- a/u-boot/include/configs/rk3562_common.h +++ b/u-boot/include/configs/rk3562_common.h @@ -7,6 +7,8 @@ #ifndef __CONFIG_RK3562_COMMON_H #define __CONFIG_RK3562_COMMON_H +#define CFG_CPUID_OFFSET 0xa + #include "rockchip-common.h" #define CONFIG_SPL_FRAMEWORK diff --git a/u-boot/include/configs/rk3568_common.h b/u-boot/include/configs/rk3568_common.h index 7a9d53bc9c..d963e3ac77 100644 --- a/u-boot/include/configs/rk3568_common.h +++ b/u-boot/include/configs/rk3568_common.h @@ -7,6 +7,8 @@ #ifndef __CONFIG_RK3568_COMMON_H #define __CONFIG_RK3568_COMMON_H +#define CFG_CPUID_OFFSET 0xa + #include "rockchip-common.h" #define CONFIG_SPL_FRAMEWORK @@ -58,6 +60,7 @@ CONFIG_SYS_SCSI_MAX_LUN) #endif /* Nand */ +#define CONFIG_SYS_NAND_BASE 0xFE330000 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_ONFI_DETECTION #define CONFIG_SYS_NAND_PAGE_SIZE 2048 diff --git a/u-boot/include/configs/rk3588_common.h b/u-boot/include/configs/rk3588_common.h index 1399468985..67a816a33f 100644 --- a/u-boot/include/configs/rk3588_common.h +++ b/u-boot/include/configs/rk3588_common.h @@ -23,7 +23,12 @@ #define CONFIG_SYS_MALLOC_LEN (32 << 20) #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SKIP_LOWLEVEL_INIT + +#ifdef CONFIG_SUPPORT_USBPLUG +#define CONFIG_SYS_TEXT_BASE 0x00000000 +#else #define CONFIG_SYS_TEXT_BASE 0x00200000 +#endif #define CONFIG_SYS_INIT_SP_ADDR 0x00600000 #define CONFIG_SYS_LOAD_ADDR 0x00600800 @@ -54,6 +59,7 @@ /* usb mass storage */ #define CONFIG_USB_FUNCTION_MASS_STORAGE #define CONFIG_ROCKUSB_G_DNL_PID 0x350b +#define ROCKUSB_FSG_BUFLEN 0x400000 /* * decompressed kernel: 4M ~ 84M diff --git a/u-boot/include/configs/rockchip-common.h b/u-boot/include/configs/rockchip-common.h index 002dcd60c2..f12af5d6b0 100644 --- a/u-boot/include/configs/rockchip-common.h +++ b/u-boot/include/configs/rockchip-common.h @@ -8,6 +8,10 @@ #define _ROCKCHIP_COMMON_H_ #include +#ifndef CFG_CPUID_OFFSET +#define CFG_CPUID_OFFSET 0x7 +#endif + #define COUNTER_FREQUENCY 24000000 #if CONFIG_IS_ENABLED(TINY_FRAMEWORK) && !defined(CONFIG_ARM64) diff --git a/u-boot/include/configs/rv1106_common.h b/u-boot/include/configs/rv1106_common.h index 0b4f77f749..dc927a8f36 100644 --- a/u-boot/include/configs/rv1106_common.h +++ b/u-boot/include/configs/rv1106_common.h @@ -7,6 +7,8 @@ #ifndef __CONFIG_RV1106_COMMON_H #define __CONFIG_RV1106_COMMON_H +#define CFG_CPUID_OFFSET 0xa + #include "rockchip-common.h" #define COUNTER_FREQUENCY 24000000 @@ -14,7 +16,11 @@ #define CONFIG_SYS_CBSIZE 1024 #define CONFIG_SYS_NS16550_MEM32 +#ifdef CONFIG_SUPPORT_USBPLUG +#define CONFIG_SYS_TEXT_BASE 0x00000000 +#else #define CONFIG_SYS_TEXT_BASE 0x00200000 +#endif #define CONFIG_SYS_INIT_SP_ADDR 0x00400000 #define CONFIG_SYS_LOAD_ADDR 0x00e00800 #define CONFIG_SYS_BOOTM_LEN (64 << 20) @@ -29,7 +35,7 @@ /* SPL */ #define CONFIG_SPL_FRAMEWORK #define CONFIG_SPL_TEXT_BASE 0x00000000 -#define CONFIG_SPL_MAX_SIZE 0x30000 +#define CONFIG_SPL_MAX_SIZE 0x28000 #define CONFIG_SPL_BSS_START_ADDR 0x001fe000 #define CONFIG_SPL_BSS_MAX_SIZE 0x20000 #define CONFIG_SPL_STACK 0x001fe000 diff --git a/u-boot/include/dm/pinctrl.h b/u-boot/include/dm/pinctrl.h index 0bcf30d6e6..05e0fce3b3 100644 --- a/u-boot/include/dm/pinctrl.h +++ b/u-boot/include/dm/pinctrl.h @@ -7,6 +7,9 @@ #ifndef __PINCTRL_H #define __PINCTRL_H +#define PINNAME_SIZE 10 +#define PINMUX_SIZE 40 + /** * struct pinconf_param - pin config parameters * @@ -32,29 +35,33 @@ struct pinconf_param { * depending on your necessity. * * @get_pins_count: return number of selectable named pins available - * in this driver. (necessary to parse "pins" property in DTS) + * in this driver. (necessary to parse "pins" property in DTS) * @get_pin_name: return the pin name of the pin selector, * called by the core to figure out which pin it shall do - * operations to. (necessary to parse "pins" property in DTS) + * operations to. (necessary to parse "pins" property in DTS) * @get_groups_count: return number of selectable named groups available - * in this driver. (necessary to parse "groups" property in DTS) + * in this driver. (necessary to parse "groups" property in DTS) * @get_group_name: return the group name of the group selector, * called by the core to figure out which pin group it shall do - * operations to. (necessary to parse "groups" property in DTS) + * operations to. (necessary to parse "groups" property in DTS) * @get_functions_count: return number of selectable named functions available - * in this driver. (necessary for pin-muxing) + * in this driver. (necessary for pin-muxing) * @get_function_name: return the function name of the muxing selector, * called by the core to figure out which mux setting it shall map a - * certain device to. (necessary for pin-muxing) + * certain device to. (necessary for pin-muxing) * @pinmux_set: enable a certain muxing function with a certain pin. * The @func_selector selects a certain function whereas @pin_selector * selects a certain pin to be used. On simple controllers one of them - * may be ignored. (necessary for pin-muxing against a single pin) + * may be ignored. (necessary for pin-muxing against a single pin) * @pinmux_group_set: enable a certain muxing function with a certain pin - * group. The @func_selector selects a certain function whereas + * group. The @func_selector selects a certain function whereas * @group_selector selects a certain set of pins to be used. On simple * controllers one of them may be ignored. * (necessary for pin-muxing against a pin group) + * @pinmux_property_set: enable a pinmux group. @pinmux_group should specify the + * pin identifier and mux settings. The exact format of a pinmux group is + * left up to the driver. The pin selector for the mux-ed pin should be + * returned on success. (necessary to parse the "pinmux" property in DTS) * @pinconf_num_params: number of driver-specific parameters to be parsed * from device trees (necessary for pin-configuration) * @pinconf_params: list of driver_specific parameters to be parsed from @@ -67,6 +74,14 @@ struct pinconf_param { * pointing a config node. (necessary for pinctrl_full) * @set_state_simple: do needed pinctrl operations for a peripherl @periph. * (necessary for pinctrl_simple) + * @get_pin_muxing: display the muxing of a given pin. + * @gpio_request_enable: requests and enables GPIO on a certain pin. + * Implement this only if you can mux every pin individually as GPIO. The + * affected GPIO range is passed along with an offset(pin number) into that + * specific GPIO range - function selectors and pin groups are orthogonal + * to this, the core will however make sure the pins do not collide. + * @gpio_disable_free: free up GPIO muxing on a certain pin, the reverse of + * @gpio_request_enable */ struct pinctrl_ops { int (*get_pins_count)(struct udevice *dev); @@ -80,6 +95,7 @@ struct pinctrl_ops { unsigned func_selector); int (*pinmux_group_set)(struct udevice *dev, unsigned group_selector, unsigned func_selector); + int (*pinmux_property_set)(struct udevice *dev, u32 pinmux_group); unsigned int pinconf_num_params; const struct pinconf_param *pinconf_params; int (*pinconf_set)(struct udevice *dev, unsigned pin_selector, @@ -130,6 +146,42 @@ struct pinctrl_ops { * @return mux value (SoC-specific, e.g. 0 for input, 1 for output) */ int (*get_gpio_mux)(struct udevice *dev, int banknum, int index); + + /** + * get_pin_muxing() - show pin muxing + * + * This allows to display the muxing of a given pin. It's useful for + * debug purpose to know if a pin is configured as GPIO or as an + * alternate function and which one. + * Typically it is used by a PINCTRL driver with knowledge of the SoC + * pinctrl setup. + * + * @dev: Pinctrl device to use + * @selector: Pin selector + * @buf Pin's muxing description + * @size Pin's muxing description length + * return 0 if OK, -ve on error + */ + int (*get_pin_muxing)(struct udevice *dev, unsigned int selector, + char *buf, int size); + + /** + * gpio_request_enable: requests and enables GPIO on a certain pin. + * + * @dev: Pinctrl device to use + * @selector: Pin selector + * return 0 if OK, -ve on error + */ + int (*gpio_request_enable)(struct udevice *dev, unsigned int selector); + + /** + * gpio_disable_free: free up GPIO muxing on a certain pin. + * + * @dev: Pinctrl device to use + * @selector: Pin selector + * return 0 if OK, -ve on error + */ + int (*gpio_disable_free)(struct udevice *dev, unsigned int selector); }; #define pinctrl_get_ops(dev) ((struct pinctrl_ops *)(dev)->driver->ops) @@ -331,6 +383,53 @@ int pinctrl_get_gpio_mux(struct udevice *dev, int banknum, int index); * @return pins count */ int pinctrl_get_pins_count(struct udevice *dev); + +/** + * pinctrl_get_pin_name() - Returns the pin's name + * + * This allows to display the pin's name for debug purpose + * + * @dev: Pinctrl device to use + * @selector Pin index within pin-controller + * @buf Pin's name + * @return 0 if OK, -ve on error + */ +int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, + int size); + +/** + * pinctrl_get_pin_muxing() - Returns the muxing description + * + * This allows to display the muxing description of the given pin for + * debug purpose + * + * @dev: Pinctrl device to use + * @selector Pin index within pin-controller + * @buf Pin's muxing description + * @size Pin's muxing description length + * @return 0 if OK, -ve on error + */ +int pinctrl_get_pin_muxing(struct udevice *dev, int selector, char *buf, + int size); + +/** + * pinctrl_gpio_request() - request a single pin to be used as GPIO + * + * @dev: GPIO peripheral device + * @offset: the GPIO pin offset from the GPIO controller + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_gpio_request(struct udevice *dev, unsigned offset); + +/** + * pinctrl_gpio_free() - free a single pin used as GPIO + * + * @dev: GPIO peripheral device + * @offset: the GPIO pin offset from the GPIO controller + * @return: 0 on success, or negative error code on failure + */ +int pinctrl_gpio_free(struct udevice *dev, unsigned offset); + #else static inline int pinctrl_select_state(struct udevice *dev, const char *statename) @@ -367,6 +466,29 @@ static inline int pinctrl_get_pins_count(struct udevice *dev) { return -EINVAL; } + +static inline int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf, + int size) +{ + return -EINVAL; +} + +static inline int pinctrl_get_pin_muxing(struct udevice *dev, int selector, char *buf, + int size) +{ + return -EINVAL; +} + +static inline int pinctrl_gpio_request(struct udevice *dev, unsigned offset) +{ + return -EINVAL; +} + +static inline int pinctrl_gpio_free(struct udevice *dev, unsigned offset) +{ + return -EINVAL; +} + #endif #endif /* __PINCTRL_H */ diff --git a/u-boot/include/dm/test.h b/u-boot/include/dm/test.h index cecee26f33..6ad83d1489 100644 --- a/u-boot/include/dm/test.h +++ b/u-boot/include/dm/test.h @@ -57,6 +57,8 @@ enum { enum { DM_TEST_TYPE_FIRST = 0, DM_TEST_TYPE_SECOND, + + DM_TEST_TYPE_COUNT, }; /* The number added to the ping total on each probe */ diff --git a/u-boot/include/dm/uclass.h b/u-boot/include/dm/uclass.h index aafeb80c2c..6f86106790 100644 --- a/u-boot/include/dm/uclass.h +++ b/u-boot/include/dm/uclass.h @@ -267,17 +267,31 @@ int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv, * uclass_first_device() - Get the first device in a uclass * * The device returned is probed if necessary, and ready for use + * Devices that fail to probe are skipped * * This function is useful to start iterating through a list of devices which * are functioning correctly and can be probed. * * @id: Uclass ID to look up * @devp: Returns pointer to the first device in that uclass if no error - * occurred, or NULL if there is no first device, or an error occurred with - * that device. - * @return 0 if OK (found or not found), other -ve on error + * occurred, or NULL if there is no usable device */ -int uclass_first_device(enum uclass_id id, struct udevice **devp); +void uclass_first_device(enum uclass_id id, struct udevice **devp); + +/** + * uclass_next_device() - Get the next device in a uclass + * + * The device returned is probed if necessary, and ready for use + * Devices that fail to probe are skipped + * + * This function is useful to start iterating through a list of devices which + * are functioning correctly and can be probed. + * + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next device in the uclass if no error occurred, or NULL if there is + * no next device + */ +void uclass_next_device(struct udevice **devp); /** * uclass_first_device_err() - Get the first device in a uclass @@ -286,27 +300,24 @@ int uclass_first_device(enum uclass_id id, struct udevice **devp); * * @id: Uclass ID to look up * @devp: Returns pointer to the first device in that uclass, or NULL if none - * @return 0 if found, -ENODEV if not found, other -ve on error + * Return: 0 if found, -ENODEV if not found, other -ve on error */ int uclass_first_device_err(enum uclass_id id, struct udevice **devp); /** - * uclass_next_device() - Get the next device in a uclass + * uclass_next_device_err() - Get the next device in a uclass * * The device returned is probed if necessary, and ready for use * - * This function is useful to start iterating through a list of devices which - * are functioning correctly and can be probed. - * * @devp: On entry, pointer to device to lookup. On exit, returns pointer - * to the next device in the uclass if no error occurred, or NULL if there is - * no next device, or an error occurred with that next device. - * @return 0 if OK (found or not found), other -ve on error + * to the next device in the uclass if no error occurred, or -ENODEV if + * there is no next device. + * @return 0 if found, -ENODEV if not found, other -ve on error */ -int uclass_next_device(struct udevice **devp); +int uclass_next_device_err(struct udevice **devp); /** - * uclass_first_device() - Get the first device in a uclass + * uclass_first_device_check() - Get the first device in a uclass * * The device returned is probed if necessary, and ready for use * @@ -322,7 +333,7 @@ int uclass_next_device(struct udevice **devp); int uclass_first_device_check(enum uclass_id id, struct udevice **devp); /** - * uclass_next_device() - Get the next device in a uclass + * uclass_next_device_check() - Get the next device in a uclass * * The device returned is probed if necessary, and ready for use * @@ -336,6 +347,20 @@ int uclass_first_device_check(enum uclass_id id, struct udevice **devp); */ int uclass_next_device_check(struct udevice **devp); +/** + * uclass_first_device_drvdata() - Find the first device with given driver data + * + * This searches through the devices for a particular uclass looking for one + * that has the given driver data. + * + * @id: Uclass ID to check + * @driver_data: Driver data to search for + * @devp: Returns pointer to the first matching device in that uclass, if found + * @return 0 if found, -ENODEV if not found, other -ve on error + */ +int uclass_first_device_drvdata(enum uclass_id id, ulong driver_data, + struct udevice **devp); + /** * uclass_resolve_seq() - Resolve a device's sequence number * @@ -351,6 +376,23 @@ int uclass_next_device_check(struct udevice **devp); */ int uclass_resolve_seq(struct udevice *dev); +/** + * uclass_id_foreach_dev() - Helper function to iteration through devices + * + * This creates a for() loop which works through the available devices in + * a uclass ID in order from start to end. + * + * If for some reason the uclass cannot be found, this does nothing. + * + * @id: enum uclass_id ID to use + * @pos: struct udevice * to hold the current device. Set to NULL when there + * are no more devices. + * @uc: temporary uclass variable (struct udevice *) + */ +#define uclass_id_foreach_dev(id, pos, uc) \ + if (!uclass_get(id, &uc)) \ + list_for_each_entry(pos, &uc->dev_head, uclass_node) + /** * uclass_foreach_dev() - Helper function to iteration through devices * @@ -379,4 +421,20 @@ int uclass_resolve_seq(struct udevice *dev); #define uclass_foreach_dev_safe(pos, next, uc) \ list_for_each_entry_safe(pos, next, &uc->dev_head, uclass_node) +/** + * uclass_foreach_dev_probe() - Helper function to iteration through devices + * of given uclass + * + * This creates a for() loop which works through the available devices in + * a uclass in order from start to end. Devices are probed if necessary, + * and ready for use. + * + * @id: Uclass ID + * @dev: struct udevice * to hold the current device. Set to NULL when there + * are no more devices. + */ +#define uclass_foreach_dev_probe(id, dev) \ + for (int _ret = uclass_first_device_err(id, &dev); !_ret && dev; \ + _ret = uclass_next_device_err(&dev)) + #endif diff --git a/u-boot/include/drm_modes.h b/u-boot/include/drm_modes.h index a79dfdfada..00fb3169c2 100644 --- a/u-boot/include/drm_modes.h +++ b/u-boot/include/drm_modes.h @@ -78,6 +78,53 @@ #define DRM_MODE_FLAG_PIC_AR_256_135 \ (DRM_MODE_PICTURE_ASPECT_256_135 << 19) +/* + * DRM_MODE_ROTATE_ + * + * Signals that a drm plane is been rotated degrees in counter + * clockwise direction. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_ROTATE_0 (1<<0) +#define DRM_MODE_ROTATE_90 (1<<1) +#define DRM_MODE_ROTATE_180 (1<<2) +#define DRM_MODE_ROTATE_270 (1<<3) + +/* + * DRM_MODE_ROTATE_MASK + * + * Bitmask used to look for drm plane rotations. + */ +#define DRM_MODE_ROTATE_MASK (\ + DRM_MODE_ROTATE_0 | \ + DRM_MODE_ROTATE_90 | \ + DRM_MODE_ROTATE_180 | \ + DRM_MODE_ROTATE_270) + +/* + * DRM_MODE_REFLECT_ + * + * Signals that the contents of a drm plane is reflected along the axis, + * in the same way as mirroring. + * See kerneldoc chapter "Plane Composition Properties" for more details. + * + * This define is provided as a convenience, looking up the property id + * using the name->prop id lookup is the preferred method. + */ +#define DRM_MODE_REFLECT_X (1<<4) +#define DRM_MODE_REFLECT_Y (1<<5) + +/* + * DRM_MODE_REFLECT_MASK + * + * Bitmask used to look for drm plane reflections. + */ +#define DRM_MODE_REFLECT_MASK (\ + DRM_MODE_REFLECT_X | \ + DRM_MODE_REFLECT_Y) + #define DRM_MODE_CONNECTOR_Unknown 0 #define DRM_MODE_CONNECTOR_VGA 1 #define DRM_MODE_CONNECTOR_DVII 2 diff --git a/u-boot/include/dt-bindings/clock/rk3308-cru.h b/u-boot/include/dt-bindings/clock/rk3308-cru.h index 5f4a34bc0c..ad8c7b9157 100644 --- a/u-boot/include/dt-bindings/clock/rk3308-cru.h +++ b/u-boot/include/dt-bindings/clock/rk3308-cru.h @@ -36,7 +36,7 @@ #define SCLK_I2C1 23 #define SCLK_I2C2 24 #define SCLK_I2C3 25 -#define SCLK_PWM 26 +#define SCLK_PWM0 26 #define SCLK_SPI0 27 #define SCLK_SPI1 28 #define SCLK_SPI2 29 @@ -130,6 +130,8 @@ #define SCLK_I2S3_8CH_RX_SRC 117 #define SCLK_I2S0_2CH_SRC 118 #define SCLK_I2S1_2CH_SRC 119 +#define SCLK_PWM1 120 +#define SCLK_PWM2 121 /* dclk */ #define DCLK_VOP 125 diff --git a/u-boot/include/edid.h b/u-boot/include/edid.h index 0967912b54..b10a6765db 100644 --- a/u-boot/include/edid.h +++ b/u-boot/include/edid.h @@ -1018,6 +1018,8 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, int edid_get_drm_mode(u8 *buf, int buf_size, struct drm_display_mode *mode, int *panel_bits_per_colourp); int drm_add_edid_modes(struct hdmi_edid_data *data, u8 *edid); +void drm_add_hdmi_modes(struct hdmi_edid_data *data, + const struct drm_display_mode *mode); bool drm_detect_hdmi_monitor(struct edid *edid); bool drm_detect_monitor_audio(struct edid *edid); int do_cea_modes(struct hdmi_edid_data *data, const u8 *db, u8 len); diff --git a/u-boot/include/elf.h b/u-boot/include/elf.h index fe2128f378..1ce323bbdc 100644 --- a/u-boot/include/elf.h +++ b/u-boot/include/elf.h @@ -1,35 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1995, 1996, 2001, 2002 * Erik Theisen. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause */ -/* - * This is the ELF ABI header file - * formerly known as "elf_abi.h". - */ +/* This is the ELF ABI header file formerly known as "elf_abi.h" */ #ifndef _ELF_H #define _ELF_H -#ifndef __ASSEMBLER__ +#ifndef __ASSEMBLY__ #include "compiler.h" -/* - * This version doesn't work for 64-bit ABIs - Erik. - */ +/* This version doesn't work for 64-bit ABIs - Erik */ -/* - * These typedefs need to be handled better. - */ +/* These typedefs need to be handled better */ typedef uint32_t Elf32_Addr; /* Unsigned program address */ typedef uint32_t Elf32_Off; /* Unsigned file offset */ typedef int32_t Elf32_Sword; /* Signed large integer */ typedef uint32_t Elf32_Word; /* Unsigned large integer */ typedef uint16_t Elf32_Half; /* Unsigned medium integer */ -/* 64-bit ELF base types. */ +/* 64-bit ELF base types */ typedef uint64_t Elf64_Addr; typedef uint16_t Elf64_Half; typedef int16_t Elf64_SHalf; @@ -96,7 +88,7 @@ typedef int64_t Elf64_Sxword; (ehdr).e_ident[EI_MAG3] == ELFMAG3) /* ELF Header */ -typedef struct elfhdr{ +typedef struct { unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ Elf32_Half e_type; /* object file type */ Elf32_Half e_machine; /* machine */ @@ -114,6 +106,24 @@ typedef struct elfhdr{ header string table" entry offset */ } Elf32_Ehdr; +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* ELF Identification */ + Elf64_Half e_type; /* object file type */ + Elf64_Half e_machine; /* machine */ + Elf64_Word e_version; /* object file version */ + Elf64_Addr e_entry; /* virtual entry point */ + Elf64_Off e_phoff; /* program header table offset */ + Elf64_Off e_shoff; /* section header table offset */ + Elf64_Word e_flags; /* processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size */ + Elf64_Half e_phentsize; /* program header entry size */ + Elf64_Half e_phnum; /* number of program header entries */ + Elf64_Half e_shentsize; /* section header entry size */ + Elf64_Half e_shnum; /* number of section header entries */ + Elf64_Half e_shstrndx; /* section header table's "section + header string table" entry offset */ +} Elf64_Ehdr; + /* e_type */ #define ET_NONE 0 /* No file type */ #define ET_REL 1 /* relocatable file */ @@ -122,9 +132,9 @@ typedef struct elfhdr{ #define ET_CORE 4 /* core file */ #define ET_NUM 5 /* number of types */ #define ET_LOOS 0xfe00 /* reserved range for operating */ -#define ET_HIOS 0xfeff /* system specific e_type */ +#define ET_HIOS 0xfeff /* system specific e_type */ #define ET_LOPROC 0xff00 /* reserved range for processor */ -#define ET_HIPROC 0xffff /* specific e_type */ +#define ET_HIPROC 0xffff /* specific e_type */ /* e_machine */ #define EM_NONE 0 /* No Machine */ @@ -178,14 +188,14 @@ typedef struct elfhdr{ #define EM_NDR1 57 /* Denso NDR1 microprocessor */ #define EM_STARCORE 58 /* Motorola Start*Core processor */ #define EM_ME16 59 /* Toyota ME16 processor */ -#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor */ #define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ #define EM_X86_64 62 /* AMD x86-64 */ #define EM_PDSP 63 /* Sony DSP Processor */ /* RESERVED 64,65 for future use */ #define EM_FX66 66 /* Siemens FX66 microcontroller */ #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ -#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_ST7 68 /* STMicroelectronics ST7 8 bit mc */ #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ @@ -231,13 +241,27 @@ typedef struct { Elf32_Word sh_entsize; /* section entry size */ } Elf32_Shdr; +typedef struct { + Elf64_Word sh_name; /* name - index into section header + string table section */ + Elf64_Word sh_type; /* type */ + Elf64_Xword sh_flags; /* flags */ + Elf64_Addr sh_addr; /* address */ + Elf64_Off sh_offset; /* file offset */ + Elf64_Xword sh_size; /* section size */ + Elf64_Word sh_link; /* section header table index link */ + Elf64_Word sh_info; /* extra information */ + Elf64_Xword sh_addralign; /* address alignment */ + Elf64_Xword sh_entsize; /* section entry size */ +} Elf64_Shdr; + /* Special Section Indexes */ #define SHN_UNDEF 0 /* undefined */ #define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */ #define SHN_LOPROC 0xff00 /* reserved range for processor */ -#define SHN_HIPROC 0xff1f /* specific section indexes */ +#define SHN_HIPROC 0xff1f /* specific section indexes */ #define SHN_LOOS 0xff20 /* reserved range for operating */ -#define SHN_HIOS 0xff3f /* specific semantics */ +#define SHN_HIOS 0xff3f /* specific semantics */ #define SHN_ABS 0xfff1 /* absolute value */ #define SHN_COMMON 0xfff2 /* common symbol */ #define SHN_XINDEX 0xffff /* Index is an extra table */ @@ -265,46 +289,46 @@ typedef struct { #define SHT_LOOS 0x60000000 /* Start OS-specific */ #define SHT_HIOS 0x6fffffff /* End OS-specific */ #define SHT_LOPROC 0x70000000 /* reserved range for processor */ -#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ #define SHT_LOUSER 0x80000000 /* reserved range for application */ -#define SHT_HIUSER 0xffffffff /* specific indexes */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ /* Section names */ -#define ELF_BSS ".bss" /* uninitialized data */ +#define ELF_BSS ".bss" /* uninitialized data */ #define ELF_COMMENT ".comment" /* version control information */ -#define ELF_DATA ".data" /* initialized data */ -#define ELF_DATA1 ".data1" /* initialized data */ -#define ELF_DEBUG ".debug" /* debug */ -#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ -#define ELF_DYNSTR ".dynstr" /* dynamic string table */ -#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ -#define ELF_FINI ".fini" /* termination code */ +#define ELF_DATA ".data" /* initialized data */ +#define ELF_DATA1 ".data1" /* initialized data */ +#define ELF_DEBUG ".debug" /* debug */ +#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */ +#define ELF_DYNSTR ".dynstr" /* dynamic string table */ +#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */ +#define ELF_FINI ".fini" /* termination code */ #define ELF_FINI_ARRAY ".fini_array" /* Array of destructors */ -#define ELF_GOT ".got" /* global offset table */ -#define ELF_HASH ".hash" /* symbol hash table */ -#define ELF_INIT ".init" /* initialization code */ +#define ELF_GOT ".got" /* global offset table */ +#define ELF_HASH ".hash" /* symbol hash table */ +#define ELF_INIT ".init" /* initialization code */ #define ELF_INIT_ARRAY ".init_array" /* Array of constuctors */ #define ELF_INTERP ".interp" /* Pathname of program interpreter */ #define ELF_LINE ".line" /* Symbolic line numnber information */ #define ELF_NOTE ".note" /* Contains note section */ #define ELF_PLT ".plt" /* Procedure linkage table */ #define ELF_PREINIT_ARRAY ".preinit_array" /* Array of pre-constructors */ -#define ELF_REL_DATA ".rel.data" /* relocation data */ -#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ -#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ -#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */ -#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ -#define ELF_REL_TEXT ".rel.text" /* relocation code */ -#define ELF_RODATA ".rodata" /* read-only data */ -#define ELF_RODATA1 ".rodata1" /* read-only data */ -#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ -#define ELF_STRTAB ".strtab" /* string table */ -#define ELF_SYMTAB ".symtab" /* symbol table */ +#define ELF_REL_DATA ".rel.data" /* relocation data */ +#define ELF_REL_FINI ".rel.fini" /* relocation termination code */ +#define ELF_REL_INIT ".rel.init" /* relocation initialization code */ +#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */ +#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */ +#define ELF_REL_TEXT ".rel.text" /* relocation code */ +#define ELF_RODATA ".rodata" /* read-only data */ +#define ELF_RODATA1 ".rodata1" /* read-only data */ +#define ELF_SHSTRTAB ".shstrtab" /* section header string table */ +#define ELF_STRTAB ".strtab" /* string table */ +#define ELF_SYMTAB ".symtab" /* symbol table */ #define ELF_SYMTAB_SHNDX ".symtab_shndx"/* symbol table section index */ #define ELF_TBSS ".tbss" /* thread local uninit data */ #define ELF_TDATA ".tdata" /* thread local init data */ #define ELF_TDATA1 ".tdata1" /* thread local init data */ -#define ELF_TEXT ".text" /* code */ +#define ELF_TEXT ".text" /* code */ /* Section Attribute Flags - sh_flags */ #define SHF_WRITE 0x1 /* Writable */ @@ -319,7 +343,7 @@ typedef struct { #define SHF_TLS 0x400 /* Thread local storage */ #define SHF_MASKOS 0x0ff00000 /* OS specific */ #define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */ - /* specific section attributes */ + /* specific section attributes */ /* Section Group Flags */ #define GRP_COMDAT 0x1 /* COMDAT group */ @@ -327,7 +351,7 @@ typedef struct { #define GRP_MASKPROC 0xf0000000 /* Mask processor specific flags */ /* Symbol Table Entry */ -typedef struct elf32_sym { +typedef struct { Elf32_Word st_name; /* name - index into string table */ Elf32_Addr st_value; /* symbol value */ Elf32_Word st_size; /* symbol size */ @@ -351,9 +375,9 @@ typedef struct elf32_sym { #define STB_WEAK 2 /* like global - lower precedence */ #define STB_NUM 3 /* number of symbol bindings */ #define STB_LOOS 10 /* reserved range for operating */ -#define STB_HIOS 12 /* system specific symbol bindings */ +#define STB_HIOS 12 /* system specific symbol bindings */ #define STB_LOPROC 13 /* reserved range for processor */ -#define STB_HIPROC 15 /* specific symbol bindings */ +#define STB_HIPROC 15 /* specific symbol bindings */ /* Symbol type - ELF32_ST_TYPE - st_info */ #define STT_NOTYPE 0 /* not specified */ @@ -364,9 +388,9 @@ typedef struct elf32_sym { #define STT_NUM 5 /* number of symbol types */ #define STT_TLS 6 /* Thread local storage symbol */ #define STT_LOOS 10 /* reserved range for operating */ -#define STT_HIOS 12 /* system specific symbol types */ +#define STT_HIOS 12 /* system specific symbol types */ #define STT_LOPROC 13 /* reserved range for processor */ -#define STT_HIPROC 15 /* specific symbol types */ +#define STT_HIPROC 15 /* specific symbol types */ /* Symbol visibility - ELF32_ST_VISIBILITY - st_other */ #define STV_DEFAULT 0 /* Normal visibility rules */ @@ -374,17 +398,14 @@ typedef struct elf32_sym { #define STV_HIDDEN 2 /* Symbol unavailable in other mods */ #define STV_PROTECTED 3 /* Not preemptible, not exported */ - /* Relocation entry with implicit addend */ -typedef struct -{ +typedef struct { Elf32_Addr r_offset; /* offset of relocation */ Elf32_Word r_info; /* symbol table index and type */ } Elf32_Rel; /* Relocation entry with explicit addend */ -typedef struct -{ +typedef struct { Elf32_Addr r_offset; /* offset of relocation */ Elf32_Word r_info; /* symbol table index and type */ Elf32_Sword r_addend; @@ -396,9 +417,9 @@ typedef struct { } Elf64_Rel; typedef struct { - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ - Elf64_Sxword r_addend; /* Constant addend used to compute value */ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ } Elf64_Rela; /* Extract relocation info - r_info */ @@ -411,13 +432,24 @@ typedef struct { Elf32_Word p_type; /* segment type */ Elf32_Off p_offset; /* segment offset */ Elf32_Addr p_vaddr; /* virtual address of segment */ - Elf32_Addr p_paddr; /* physical address - ignored? */ - Elf32_Word p_filesz; /* number of bytes in file for seg. */ - Elf32_Word p_memsz; /* number of bytes in mem. for seg. */ + Elf32_Addr p_paddr; /* physical address of segment */ + Elf32_Word p_filesz; /* number of bytes in file for seg */ + Elf32_Word p_memsz; /* number of bytes in mem. for seg */ Elf32_Word p_flags; /* flags */ Elf32_Word p_align; /* memory alignment */ } Elf32_Phdr; +typedef struct { + Elf64_Word p_type; /* segment type */ + Elf64_Word p_flags; /* flags */ + Elf64_Off p_offset; /* segment offset */ + Elf64_Addr p_vaddr; /* virtual address of segment */ + Elf64_Addr p_paddr; /* physical address of segment */ + Elf64_Xword p_filesz; /* number of bytes in file for seg */ + Elf64_Xword p_memsz; /* number of bytes in mem. for seg */ + Elf64_Xword p_align; /* memory alignment */ +} Elf64_Phdr; + /* Segment types - p_type */ #define PT_NULL 0 /* unused */ #define PT_LOAD 1 /* loadable segment */ @@ -429,9 +461,9 @@ typedef struct { #define PT_TLS 7 /* Thread local storage template */ #define PT_NUM 8 /* Number of segment types */ #define PT_LOOS 0x60000000 /* reserved range for operating */ -#define PT_HIOS 0x6fffffff /* system specific segment types */ +#define PT_HIOS 0x6fffffff /* system specific segment types */ #define PT_LOPROC 0x70000000 /* reserved range for processor */ -#define PT_HIPROC 0x7fffffff /* specific segment types */ +#define PT_HIPROC 0x7fffffff /* specific segment types */ /* Segment flags - p_flags */ #define PF_X 0x1 /* Executable */ @@ -439,13 +471,11 @@ typedef struct { #define PF_R 0x4 /* Readable */ #define PF_MASKOS 0x0ff00000 /* OS specific segment flags */ #define PF_MASKPROC 0xf0000000 /* reserved bits for processor */ - /* specific segment flags */ + /* specific segment flags */ /* Dynamic structure */ -typedef struct -{ +typedef struct { Elf32_Sword d_tag; /* controls meaning of d_val */ - union - { + union { Elf32_Word d_val; /* Multiple meanings - see d_tag */ Elf32_Addr d_ptr; /* program virtual address */ } d_un; @@ -477,12 +507,12 @@ typedef struct { #define DT_RELAENT 9 /* size of relocation entry */ #define DT_STRSZ 10 /* size of string table */ #define DT_SYMENT 11 /* size of symbol table entry */ -#define DT_INIT 12 /* address of initialization func. */ +#define DT_INIT 12 /* address of initialization func */ #define DT_FINI 13 /* address of termination function */ #define DT_SONAME 14 /* string table offset of shared obj */ #define DT_RPATH 15 /* string table offset of library search path */ -#define DT_SYMBOLIC 16 /* start sym search in shared obj. */ +#define DT_SYMBOLIC 16 /* start sym search in shared obj */ #define DT_REL 17 /* address of rel. tbl. w addends */ #define DT_RELSZ 18 /* size of DT_REL relocation table */ #define DT_RELENT 19 /* size of DT_REL relocation entry */ @@ -500,11 +530,11 @@ typedef struct { #define DT_ENCODING 32 /* Start of encoded range */ #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ -#define DT_NUM 34 /* Number used. */ +#define DT_NUM 34 /* Number used */ #define DT_LOOS 0x60000000 /* reserved range for OS */ -#define DT_HIOS 0x6fffffff /* specific dynamic array tags */ +#define DT_HIOS 0x6fffffff /* specific dynamic array tags */ #define DT_LOPROC 0x70000000 /* reserved range for processor */ -#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ +#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */ /* Dynamic Tag Flags - d_un.d_val */ #define DF_ORIGIN 0x01 /* Object may use DF_ORIGIN */ @@ -520,106 +550,150 @@ unsigned long elf_hash(const unsigned char *name); #endif /* __ASSEMBLER */ +/* ELF register definitions */ +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + +/* x86-64 relocation types */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +/* 32 bit signed pc relative offset to GOT */ +#define R_X86_64_GOTPCREL 9 +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ + +#define R_X86_64_NUM 16 + /* * XXX - PowerPC defines really don't belong in here, * but we'll put them in for simplicity. */ -/* Values for Elf32/64_Ehdr.e_flags. */ -#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ +/* Values for Elf32/64_Ehdr.e_flags */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +#define EF_PPC64_ELFV1_ABI 0x00000001 +#define EF_PPC64_ELFV2_ABI 0x00000002 /* Cygnus local bits below */ -#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ -#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag */ /* PowerPC relocations defined by the ABIs */ -#define R_PPC_NONE 0 -#define R_PPC_ADDR32 1 /* 32bit absolute address */ -#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ -#define R_PPC_ADDR16 3 /* 16bit absolute address */ -#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ -#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ -#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ -#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 /* PC relative 26 bit */ -#define R_PPC_REL14 11 /* PC relative 16 bit */ -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 -/* Keep this the last entry. */ -#define R_PPC_NUM 37 +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 +/* Keep this the last entry */ +#define R_PPC_NUM 37 -/* The remaining relocs are from the Embedded ELF ABI, and are not - in the SVR4 ELF ABI. */ -#define R_PPC_EMB_NADDR32 101 -#define R_PPC_EMB_NADDR16 102 -#define R_PPC_EMB_NADDR16_LO 103 -#define R_PPC_EMB_NADDR16_HI 104 -#define R_PPC_EMB_NADDR16_HA 105 -#define R_PPC_EMB_SDAI16 106 -#define R_PPC_EMB_SDA2I16 107 -#define R_PPC_EMB_SDA2REL 108 -#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ -#define R_PPC_EMB_MRKREF 110 -#define R_PPC_EMB_RELSEC16 111 -#define R_PPC_EMB_RELST_LO 112 -#define R_PPC_EMB_RELST_HI 113 -#define R_PPC_EMB_RELST_HA 114 -#define R_PPC_EMB_BIT_FLD 115 -#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ +/* + * The remaining relocs are from the Embedded ELF ABI, and are not + * in the SVR4 ELF ABI. + */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ -/* Diab tool relocations. */ -#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ -#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ -#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ -#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ -#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ -#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ +/* Diab tool relocations */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ -/* This is a phony reloc to handle any old fashioned TOC16 references - that may still be in object files. */ -#define R_PPC_TOC16 255 +/* + * This is a phony reloc to handle any old fashioned TOC16 references + * that may still be in object files. + */ +#define R_PPC_TOC16 255 /* ARM relocs */ #define R_ARM_NONE 0 /* No reloc */ #define R_ARM_RELATIVE 23 /* Adjust by program base */ /* AArch64 relocs */ -#define R_AARCH64_NONE 0 /* No relocation. */ -#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */ +#define R_AARCH64_NONE 0 /* No relocation */ +#define R_AARCH64_RELATIVE 1027 /* Adjust by program base */ /* RISC-V relocations */ #define R_RISCV_32 1 #define R_RISCV_64 2 #define R_RISCV_RELATIVE 3 -#ifndef __ASSEMBLER__ +#ifndef __ASSEMBLY__ int valid_elf_image(unsigned long addr); +unsigned long load_elf64_image_phdr(unsigned long addr); +unsigned long load_elf64_image_shdr(unsigned long addr); #endif #endif /* _ELF_H */ diff --git a/u-boot/include/fdt_support.h b/u-boot/include/fdt_support.h index 0f4ceda2a3..15ec7eaa05 100644 --- a/u-boot/include/fdt_support.h +++ b/u-boot/include/fdt_support.h @@ -11,6 +11,7 @@ #ifdef CONFIG_OF_LIBFDT #include +#include u32 fdt_getprop_u32_default_node(const void *fdt, int off, int cell, const char *prop, const u32 dflt); @@ -183,6 +184,18 @@ int fdt_find_or_add_subnode(void *fdt, int parentoffset, const char *name); */ int ft_board_setup(void *blob, bd_t *bd); +/** + * board_rng_seed() - Provide a seed to be passed via /chosen/rng-seed + * + * This function is called if CONFIG_BOARD_RNG_SEED is set, and must + * be provided by the board. It should return, via @buf, some suitable + * seed value to pass to the kernel. + * + * @param buf A struct abuf for returning the seed and its size. + * @return 0 if ok, negative on error. + */ +int board_rng_seed(struct abuf *buf); + /** * board_fdt_chosen_bootargs() - Arbitrarily amend fdt kernel command line * diff --git a/u-boot/include/id_attestation.h b/u-boot/include/id_attestation.h new file mode 100644 index 0000000000..83559d1c96 --- /dev/null +++ b/u-boot/include/id_attestation.h @@ -0,0 +1,43 @@ +/* + * Copyright 2023, Rockchip Electronics Co., Ltd + * callen.cai, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef ID_ATTESTATION_H_ +#define ID_ATTESTATION_H_ + +#include +#include "attestation_key.h" +#define IDAT_DEBUG 0 +#if IDAT_DEBUG + #define MSG(...) printf(__VA_ARGS__) +#else + #define MSG(...) do {} while (0) +#endif + +#define PROP_LEN 32 + +typedef struct AttestationIds_ { + u8 brand[PROP_LEN]; + u8 device[PROP_LEN]; + u8 product[PROP_LEN]; + u8 serial[PROP_LEN]; + u8 imei[PROP_LEN]; + u8 second_imei[PROP_LEN]; + u8 meid[PROP_LEN]; + u8 manufacturer[PROP_LEN]; + u8 model[PROP_LEN]; +} AttestationIds; + +void printAttestationIds(const AttestationIds *ids); + +/* + * write id attestation to secure storage. + * @received_data: received data from usb + * @len: the size of received_data + * @return ATAP_RESULT_OK if ok, or ATAP_RESULT_ERROR_* on error + */ +atap_result write_id_attestation_to_secure_storage(u8 *received_data, uint32_t len); +#endif //ID_ATTESTATION_H_ diff --git a/u-boot/include/linux/mtd/spinand.h b/u-boot/include/linux/mtd/spinand.h index 76c00df4e6..2ff2038bbb 100644 --- a/u-boot/include/linux/mtd/spinand.h +++ b/u-boot/include/linux/mtd/spinand.h @@ -263,6 +263,7 @@ extern const struct spinand_manufacturer etron_spinand_manufacturer; extern const struct spinand_manufacturer jsc_spinand_manufacturer; extern const struct spinand_manufacturer silicongo_spinand_manufacturer; extern const struct spinand_manufacturer unim_spinand_manufacturer; +extern const struct spinand_manufacturer unim_zl_spinand_manufacturer; extern const struct spinand_manufacturer skyhigh_spinand_manufacturer; extern const struct spinand_manufacturer gsto_spinand_manufacturer; diff --git a/u-boot/include/linux/string.h b/u-boot/include/linux/string.h index 3606620739..a2427c24f5 100644 --- a/u-boot/include/linux/string.h +++ b/u-boot/include/linux/string.h @@ -120,6 +120,19 @@ extern void * memchr(const void *,int,__kernel_size_t); void *memchr_inv(const void *, int, size_t); #endif +/** + * memdup() - allocate a buffer and copy in the contents + * + * Note that this returns a valid pointer even if @len is 0 + * + * @src: data to copy in + * @len: number of bytes to copy + * @return allocated buffer with the copied contents, or NULL if not enough + * memory is available + * + */ +char *memdup(const void *src, size_t len); + unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); diff --git a/u-boot/include/linux/usb/ch9.h b/u-boot/include/linux/usb/ch9.h index 264c9712a3..79a4c7c17c 100644 --- a/u-boot/include/linux/usb/ch9.h +++ b/u-boot/include/linux/usb/ch9.h @@ -955,8 +955,6 @@ enum usb_device_speed { USB_SPEED_SUPER, /* usb 3.0 */ }; -#ifdef __KERNEL__ - /** * usb_speed_string() - Returns human readable-name of the speed. * @speed: The speed to return human-readable name for. If it's not @@ -965,8 +963,6 @@ enum usb_device_speed { */ extern const char *usb_speed_string(enum usb_device_speed speed); -#endif - enum usb_device_state { /* NOTATTACHED isn't in the USB spec, and this state acts * the same as ATTACHED ... but it's clearer this way. diff --git a/u-boot/include/linux/usb/phy-rockchip-naneng-combphy.h b/u-boot/include/linux/usb/phy-rockchip-naneng-combphy.h new file mode 100644 index 0000000000..5996f4b051 --- /dev/null +++ b/u-boot/include/linux/usb/phy-rockchip-naneng-combphy.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Rockchip Electronics Co., Ltd + */ + +#ifndef _PHY_ROCKCHIP_NANENG_COMBPHY_H +#define _PHY_ROCKCHIP_NANENG_COMBPHY_H + +#if CONFIG_IS_ENABLED(PHY_ROCKCHIP_NANENG_COMBOPHY) +int rockchip_combphy_usb3_uboot_init(void); +#else +static inline int rockchip_combphy_usb3_uboot_init(void) +{ + return -ENOTSUPP; +} +#endif + +#endif /* _PHY_ROCKCHIP_NANENG_COMBPHY_H */ diff --git a/u-boot/include/linux/usb/phy-rockchip-usbdp.h b/u-boot/include/linux/usb/phy-rockchip-usbdp.h index 8acfa6ddf5..12117c2e90 100644 --- a/u-boot/include/linux/usb/phy-rockchip-usbdp.h +++ b/u-boot/include/linux/usb/phy-rockchip-usbdp.h @@ -8,63 +8,13 @@ #ifndef __PHY_ROCKCHIP_USBDP_H_ #define __PHY_ROCKCHIP_USBDP_H_ -#include - -/* RK3588 USBDP PHY Register Definitions */ - -#define UDPHY_PCS 0x4000 -#define UDPHY_PMA 0x8000 - -/* VO0 GRF Registers */ -#define RK3588_GRF_VO0_CON0 0x0000 -#define RK3588_GRF_VO0_CON2 0x0008 -#define DP_SINK_HPD_CFG BIT(11) -#define DP_SINK_HPD_SEL BIT(10) -#define DP_AUX_DIN_SEL BIT(9) -#define DP_AUX_DOUT_SEL BIT(8) -#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n)) -#define DP_LANE_SEL_ALL GENMASK(7, 0) -#define PHY_AUX_DP_DATA_POL_NORMAL 0 -#define PHY_AUX_DP_DATA_POL_INVERT 1 - -/* PMA CMN Registers */ -#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */ -#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4) -#define CMN_DP_LANE_EN_N(n) BIT(n) -#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4) -#define CMN_DP_LANE_EN_ALL GENMASK(3, 0) -#define PHY_LANE_MUX_USB 0 -#define PHY_LANE_MUX_DP 1 - -#define CMN_DP_LINK_OFFSET 0x28c /*cmn_reg00A3 */ -#define CMN_DP_TX_LINK_BW GENMASK(6, 5) -#define CMN_DP_TX_LANE_SWAP_EN BIT(2) - -#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */ -#define CMN_ROPLL_SSC_EN BIT(1) -#define CMN_LCPLL_SSC_EN BIT(0) - -#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */ -#define CMN_ANA_LCPLL_LOCK_DONE BIT(7) -#define CMN_ANA_LCPLL_AFC_DONE BIT(6) - -#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */ -#define CMN_ANA_ROPLL_LOCK_DONE BIT(1) -#define CMN_ANA_ROPLL_AFC_DONE BIT(0) - -#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */ -#define CMN_DP_INIT_RSTN BIT(3) -#define CMN_DP_CMN_RSTN BIT(2) -#define CMN_CDR_WTCHDG_EN BIT(1) -#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0) - -#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */ -#define LN_ANA_TX_SER_TXCLK_INV BIT(1) - -#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */ -#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0) - -#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */ -#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0) +#if CONFIG_IS_ENABLED(PHY_ROCKCHIP_USBDP) +int rockchip_u3phy_uboot_init(void); +#else +static inline int rockchip_u3phy_uboot_init(void) +{ + return -ENOTSUPP; +} +#endif #endif diff --git a/u-boot/include/optee_include/OpteeClientInterface.h b/u-boot/include/optee_include/OpteeClientInterface.h index ce8f547737..eb7ce2619d 100644 --- a/u-boot/include/optee_include/OpteeClientInterface.h +++ b/u-boot/include/optee_include/OpteeClientInterface.h @@ -18,6 +18,12 @@ enum RK_OEM_OTP_KEYID { RK_OEM_OTP_KEYMAX }; +enum RK_HDCP_KEYID { + RK_HDCP_KEY0 = 0, + RK_HDCP_KEY1 = 1, + RK_HDCP_KEYMAX +}; + /* Crypto mode */ enum RK_CIPIHER_MODE { RK_CIPHER_MODE_ECB = 0, @@ -87,6 +93,9 @@ uint32_t trusty_read_vbootkey_hash(uint32_t *buf, uint32_t length); uint32_t trusty_write_vbootkey_hash(uint32_t *buf, uint32_t length); uint32_t trusty_read_vbootkey_enable_flag(uint8_t *flag); uint32_t trusty_write_ta_encryption_key(uint32_t *buf, uint32_t length); +uint32_t trusty_ta_encryption_key_is_written(uint8_t *value); +uint32_t trusty_write_oem_encrypt_data(uint32_t *buf, uint32_t length); +uint32_t trusty_oem_encrypt_data_is_written(uint8_t *value); uint32_t trusty_check_security_level_flag(uint8_t flag); uint32_t trusty_write_oem_huk(uint32_t *buf, uint32_t length); uint32_t trusty_read_permanent_attributes_flag(uint8_t *attributes); @@ -100,6 +109,12 @@ uint32_t trusty_set_oem_hr_otp_read_lock(enum RK_OEM_OTP_KEYID key_id); uint32_t trusty_oem_otp_key_cipher(enum RK_OEM_OTP_KEYID key_id, rk_cipher_config *config, uint32_t src_phys_addr, uint32_t dst_phys_addr, uint32_t len); +uint32_t trusty_oem_user_ta_transfer(void); +uint32_t trusty_oem_user_ta_storage(void); +uint32_t trusty_write_oem_hdcp_key(enum RK_HDCP_KEYID key_id, + uint8_t *byte_buf, uint32_t byte_len); +uint32_t trusty_oem_hdcp_key_is_written(enum RK_HDCP_KEYID key_id, uint8_t *value); +uint32_t trusty_set_oem_hdcp_key_mask(enum RK_HDCP_KEYID key_id); uint32_t trusty_attest_dh(uint8_t *dh, uint32_t *dh_size); uint32_t trusty_attest_uuid(uint8_t *uuid, uint32_t *uuid_size); uint32_t trusty_attest_get_ca diff --git a/u-boot/include/optee_include/OpteeClientLoadTa.h b/u-boot/include/optee_include/OpteeClientLoadTa.h new file mode 100644 index 0000000000..f68d7887fe --- /dev/null +++ b/u-boot/include/optee_include/OpteeClientLoadTa.h @@ -0,0 +1,33 @@ +/* + * Copyright 2023, Rockchip Electronics Co., Ltd + * hisping lin, + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _OPTEE_CLIENT_LOAD_TA_H_ +#define _OPTEE_CLIENT_LOAD_TA_H_ + +#include +#include + +#define TA_BINARY_FOUND 0 +#define TA_BINARY_NOT_FOUND -2 + +struct userta_header { + uint32_t magic; + uint32_t img_ver; + uint32_t ta_num; + uint32_t reserve; +}; + +struct userta_item { + uint8_t ta_uuid[16]; + uint32_t ta_offset; + uint32_t ta_len; + uint32_t ta_ver; + uint32_t reserve; +}; + +int search_ta(void *uuid_octets, void *ta, size_t *ta_size); + +#endif /*_OPTEE_CLIENT_LOAD_TA_H_*/ diff --git a/u-boot/include/power/rk8xx_pmic.h b/u-boot/include/power/rk8xx_pmic.h index 84d1104dab..d5ec548140 100644 --- a/u-boot/include/power/rk8xx_pmic.h +++ b/u-boot/include/power/rk8xx_pmic.h @@ -245,6 +245,91 @@ enum { #define RK805_IRQ_PWRON_FALL_MSK BIT(7) #define RK805_IRQ_PWRON_RISE_MSK BIT(0) +#define RK806_CHIP_NAME 0x5A +#define RK806_CHIP_VER 0x5B +#define RK806_HW_VER 0x21 +#define HW_DUAL_PMIC 0x28 +#define HW_SINGLE_PMIC 0xe8 + +#define RK806_CMD_READ 0 +#define RK806_CMD_WRITE BIT(7) +#define RK806_CMD_CRC_EN BIT(6) +#define RK806_CMD_CRC_DIS 0 +#define RK806_CMD_LEN_MSK 0x0f +#define RK806_REG_H 0x00 + +#define RK806_SYS_CFG1 0x5f +#define RK806_PWRCTRL_CONFIG0 0x62 +#define RK806_PWRCTRL_CONFIG1 0x63 +#define RK806_VSEL_CTR_SEL0 0x64 +#define RK806_DVS_CTR_SEL4 0x6e +#define RK806_SYS_CFG3 0x72 +#define RK806_PWRON_KEY 0x76 +#define RK806_INT_STS0 0x77 +#define RK806_INT_MSK0 0x78 +#define RK806_INT_STS1 0x79 +#define RK806_INT_MSK1 0x7A +#define RK806_GPIO_INT_CONFIG 0x7B +#define RK806_ON_SOURCE 0x74 +#define RK806_OFF_SOURCE 0x75 + +#define RK806_IRQ_PWRON_FALL_MSK BIT(0) +#define RK806_IRQ_PWRON_RISE_MSK BIT(1) +#define RK806_DEV_OFF BIT(0) +#define RK806_RST_MODE1 0x01 +#define RK806_RST_MODE2 0x02 +#define RK806_PWRCTRL_FUN_MSK 0x88 +#define RK806_VSEL_CTRL_MSK 0xcc +#define RK806_VSEL_PWRCTRL1 0x11 +#define RK806_ENABLE_PWRCTRL 0x04 +#define RK806_VERSION_AB 0x01 + +#define RK806_ABNORDET_EN 0x80 +#define RK806_VERSION_MSK 0x0f +#define RK806_RESET_FUN_CLR 0x3f + +/* RK806 buck*/ +#define RK806_BUCK_ON_VSEL(n) (0x1a + n - 1) +#define RK806_BUCK_SLP_VSEL(n) (0x24 + n - 1) +#define RK806_BUCK_CONFIG(n) (0x10 + n - 1) +#define RK806_BUCK_VSEL_MASK 0xff + +/* RK806 LDO */ +#define RK806_NLDO_ON_VSEL(n) (0x43 + n - 1) +#define RK806_NLDO_SLP_VSEL(n) (0x48 + n - 1) +#define RK806_NLDO_VSEL_MASK 0xff +#define RK806_PLDO_ON_VSEL(n) (0x4e + n - 1) +#define RK806_PLDO_SLP_VSEL(n) (0x54 + n - 1) +#define RK806_PLDO_VSEL_MASK 0xff + +/* RK806 ENABLE */ +#define RK806_POWER_EN(n) (0x00 + n) +#define RK806_NLDO_EN(n) (0x03 + n) +#define RK806_PLDO_EN(n) (0x04 + n) + +#define RK806_BUCK_SUSPEND_EN 0x06 +#define RK806_NLDO_SUSPEND_EN 0x07 +#define RK806_PLDO_SUSPEND_EN 0x08 + +#define RK806_RAMP_RATE_MASK1 0xc0 +#define RK806_RAMP_RATE_REG1(n) (0x10 + n) +#define RK806_RAMP_RATE_REG1_8 0xeb +#define RK806_RAMP_RATE_REG9_10 0xea + +#define RK806_RAMP_RATE_4LSB_PER_1CLK 0x00/* LDO 100mV/uS buck 50mV/us */ +#define RK806_RAMP_RATE_2LSB_PER_1CLK 0x01/* LDO 50mV/uS buck 25mV/us */ +#define RK806_RAMP_RATE_1LSB_PER_1CLK 0x02/* LDO 25mV/uS buck 12.5mV/us */ +#define RK806_RAMP_RATE_1LSB_PER_2CLK 0x03/* LDO 12.5mV/uS buck 6.25mV/us */ + +#define RK806_RAMP_RATE_1LSB_PER_4CLK 0x04/* LDO 6.28/2mV/uS buck 3.125mV/us */ +#define RK806_RAMP_RATE_1LSB_PER_8CLK 0x05/* LDO 3.12mV/uS buck 1.56mV/us */ +#define RK806_RAMP_RATE_1LSB_PER_13CLK 0x06/* LDO 1.9mV/uS buck 961mV/us */ +#define RK806_RAMP_RATE_1LSB_PER_32CLK 0x07/* LDO 0.78mV/uS buck 0.39mV/us */ + +#define RK806_PLDO0_2_MSK(pldo) (BIT(pldo + 5)) +#define RK806_PLDO0_2_SET(pldo) (BIT(pldo + 1) | RK806_PLDO0_2_MSK(pldo)) +#define RK806_PLDO0_2_CLR(pldo) RK806_PLDO0_2_MSK(pldo) + #define RK816_INT_STS_REG1 0x49 #define RK816_INT_MSK_REG1 0x4a #define RK816_INT_STS_REG3 0x4e diff --git a/u-boot/include/rk_mini_dump.h b/u-boot/include/rk_mini_dump.h new file mode 100644 index 0000000000..2980c773fb --- /dev/null +++ b/u-boot/include/rk_mini_dump.h @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2020 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef RK_MINIDUMP_H +#define RK_MINIDUMP_H + +#include + +#define MD_MAX_NAME_LENGTH 16 +/* md_region - Minidump table entry + * @name: Entry name, Minidump will dump binary with this name. + * @id: Entry ID, used only for SDI dumps. + * @virt_addr: Address of the entry. + * @phys_addr: Physical address of the entry to dump. + * @size: Number of byte to dump from @address location + * it should be 4 byte aligned. + */ +struct md_region { + char name[MD_MAX_NAME_LENGTH]; + u32 id; + u64 virt_addr; + u64 phys_addr; + u64 size; +}; + +void rk_minidump_init(void); + +#ifdef CONFIG_ARM64 +void rk_minidump_get_el64(void **ram_image_addr, Elf64_Xword *ram_image_size); +#else +void rk_minidump_get_el32(void **ram_image_addr, Elf32_Word *ram_image_size); +#endif + +struct md_region *md_get_region(char *name); +u32 md_no_fault_handler(struct pt_regs *pt_regs, unsigned int esr); +#endif diff --git a/u-boot/include/rockusb.h b/u-boot/include/rockusb.h index 81daabfaa6..d742faeec8 100644 --- a/u-boot/include/rockusb.h +++ b/u-boot/include/rockusb.h @@ -39,9 +39,11 @@ enum rkusb_cmd { RKUSB_LBA_ERASE = 0x25, RKUSB_VS_WRITE = 0x26, RKUSB_VS_READ = 0x27, + RKUSB_SWITCH_STORAGE = 0x2A, RKUSB_GET_STORAGE_MEDIA = 0x2B, - RKUSB_SESSION = 0x30, + RKUSB_READ_OTP_DATA = 0x2C, RKUSB_READ_CAPACITY = 0xAA, + RKUSB_SWITCH_USB3 = 0xBB, RKUSB_RESET = 0xFF, }; @@ -58,6 +60,12 @@ struct fsg_common; #define IS_RKUSB_UMS_DNL(name) (!strncmp((name), "rkusb_ums_dnl", 13)) int rkusb_do_check_parity(struct fsg_common *common); +void rkusb_force_to_usb2(bool enable); +bool rkusb_force_usb2_enabled(void); +void rkusb_switch_to_usb3_enable(bool enable); +bool rkusb_switch_usb3_enabled(void); +bool rkusb_usb3_capable(void); + #else #define IS_RKUSB_UMS_DNL(name) 0 @@ -79,6 +87,33 @@ static inline int rkusb_do_check_parity(struct fsg_common *common) { return -EOPNOTSUPP; } + +static inline void rkusb_force_to_usb2(bool enable) +{ +} + +static inline bool rkusb_force_usb2_enabled(void) +{ + return false; +} + +static inline void rkusb_switch_to_usb3_enable(bool enable) +{ +} + +static inline bool rkusb_switch_usb3_enabled(void) +{ + return false; +} + +static inline bool rkusb_usb3_capable(void) +{ + return false; +} +#endif + +#ifdef CONFIG_USB_DWC3_GADGET +bool dwc3_gadget_is_connected(void); #endif /* Wait at maximum 60 seconds for cable connection */ @@ -90,6 +125,8 @@ static inline int rkusb_do_check_parity(struct fsg_common *common) struct rockusb { struct ums *ums; int ums_cnt; + bool force_usb2; + bool switch_usb3; }; #endif /* __ROCKUSB_H__ */ diff --git a/u-boot/include/usbplug.h b/u-boot/include/usbplug.h new file mode 100644 index 0000000000..3af2a99853 --- /dev/null +++ b/u-boot/include/usbplug.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2023 Rockchip Electronics Co., Ltd + * + */ + +#ifndef __USBPLUG_H +#define __USBPLUG_H + +struct blk_desc *usbplug_blk_get_devnum_by_type(enum if_type if_type, int devnum); + +#endif \ No newline at end of file diff --git a/u-boot/lib/Makefile b/u-boot/lib/Makefile index 0b7a01a034..b0b0e78904 100644 --- a/u-boot/lib/Makefile +++ b/u-boot/lib/Makefile @@ -76,6 +76,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o endif +obj-y += abuf.o obj-$(CONFIG_ADDR_MAP) += addr_map.o obj-y += hashtable.o obj-y += errno.o diff --git a/u-boot/lib/abuf.c b/u-boot/lib/abuf.c new file mode 100644 index 0000000000..aa7c429652 --- /dev/null +++ b/u-boot/lib/abuf.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Handles a buffer that can be allocated and freed + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include + +void abuf_set(struct abuf *abuf, void *data, size_t size) +{ + abuf_uninit(abuf); + abuf->data = data; + abuf->size = size; +} + +void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) +{ + abuf_set(abuf, map_sysmem(addr, size), size); +} + +bool abuf_realloc(struct abuf *abuf, size_t new_size) +{ + void *ptr; + + if (!new_size) { + /* easy case, just need to uninit, freeing any allocation */ + abuf_uninit(abuf); + return true; + } else if (abuf->alloced) { + /* currently allocated, so need to reallocate */ + ptr = realloc(abuf->data, new_size); + if (!ptr) + return false; + abuf->data = ptr; + abuf->size = new_size; + return true; + } else if (new_size <= abuf->size) { + /* + * not currently alloced and new size is no larger. Just update + * it. Data is lost off the end if new_size < abuf->size + */ + abuf->size = new_size; + return true; + } else { + /* not currently allocated and new size is larger. Alloc and + * copy in data. The new space is not inited. + */ + ptr = memdup(abuf->data, new_size); + if (!ptr) + return false; + abuf->data = ptr; + abuf->size = new_size; + abuf->alloced = true; + return true; + } +} + +void *abuf_uninit_move(struct abuf *abuf, size_t *sizep) +{ + void *ptr; + + if (sizep) + *sizep = abuf->size; + if (!abuf->size) + return NULL; + if (abuf->alloced) { + ptr = abuf->data; + } else { + ptr = memdup(abuf->data, abuf->size); + if (!ptr) + return NULL; + } + /* Clear everything out so there is no record of the data */ + abuf_init(abuf); + + return ptr; +} + +void abuf_init_set(struct abuf *abuf, void *data, size_t size) +{ + abuf_init(abuf); + abuf_set(abuf, data, size); +} + +void abuf_init_move(struct abuf *abuf, void *data, size_t size) +{ + abuf_init_set(abuf, data, size); + abuf->alloced = true; +} + +void abuf_uninit(struct abuf *abuf) +{ + if (abuf->alloced) + free(abuf->data); + abuf_init(abuf); +} + +void abuf_init(struct abuf *abuf) +{ + abuf->data = NULL; + abuf->size = 0; + abuf->alloced = false; +} diff --git a/u-boot/lib/display_options.c b/u-boot/lib/display_options.c index 4ea27ca99d..467c7b8da0 100644 --- a/u-boot/lib/display_options.c +++ b/u-boot/lib/display_options.c @@ -21,7 +21,7 @@ char *display_options_get_banner_priv(bool newlines, const char *build_tag, len = snprintf(buf, size, "%s%s", newlines ? "\n\n" : "", version_string); if (build_tag && len < size) - len += snprintf(buf + len, size - len, ", Build: %s", + len += snprintf(buf + len, size - len, ", fwver: %s", build_tag); if (len > size - 3) len = size - 3; diff --git a/u-boot/lib/efi_loader/efi_gop.c b/u-boot/lib/efi_loader/efi_gop.c index 411a8c9226..66b7093b76 100644 --- a/u-boot/lib/efi_loader/efi_gop.c +++ b/u-boot/lib/efi_loader/efi_gop.c @@ -137,7 +137,8 @@ int efi_gop_register(void) struct udevice *vdev; /* We only support a single video output device for now */ - if (uclass_first_device(UCLASS_VIDEO, &vdev) || !vdev) + uclass_first_device(UCLASS_VIDEO, &vdev); + if (!vdev) return -1; struct video_priv *priv = dev_get_uclass_priv(vdev); diff --git a/u-boot/lib/optee_clientApi/Makefile b/u-boot/lib/optee_clientApi/Makefile index 4ee69ec055..cbede317b7 100644 --- a/u-boot/lib/optee_clientApi/Makefile +++ b/u-boot/lib/optee_clientApi/Makefile @@ -8,6 +8,7 @@ obj-y += OpteeClientApiLib.o obj-y += OpteeClientInterface.o obj-y += OpteeClientSMC.o obj-y += OpteeClientRPC.o +obj-y += OpteeClientLoadTa.o obj-y += tee_smc-arm64.o obj-y += OpteeClientRkFs_common.o diff --git a/u-boot/lib/optee_clientApi/OpteeClientInterface.c b/u-boot/lib/optee_clientApi/OpteeClientInterface.c index 43546e714d..3a63f356d0 100644 --- a/u-boot/lib/optee_clientApi/OpteeClientInterface.c +++ b/u-boot/lib/optee_clientApi/OpteeClientInterface.c @@ -29,6 +29,12 @@ #define STORAGE_CMD_WRITE_OEM_OTP_KEY 14 #define STORAGE_CMD_SET_OEM_HR_OTP_READ_LOCK 15 #define STORAGE_CMD_OEM_OTP_KEY_IS_WRITTEN 16 +#define STORAGE_CMD_TA_ENCRYPTION_KEY_IS_WRITTEN 20 +#define STORAGE_CMD_WRITE_OEM_HDCP_KEY 21 +#define STORAGE_CMD_OEM_HDCP_KEY_IS_WRITTEN 22 +#define STORAGE_CMD_SET_OEM_HDCP_KEY_MASK 23 +#define STORAGE_CMD_WRITE_OEM_ENCRYPT_DATA 24 +#define STORAGE_CMD_OEM_ENCRYPT_DATA_IS_WRITTEN 25 #define CRYPTO_SERVICE_CMD_OEM_OTP_KEY_PHYS_CIPHER 0x00000002 @@ -647,6 +653,112 @@ uint32_t trusty_write_ta_encryption_key(uint32_t *buf, uint32_t length) true, buf, length); } +uint32_t trusty_ta_encryption_key_is_written(uint8_t *value) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + + *value = 0; + + TEEC_UUID tempuuid = { 0x2d26d8a8, 0x5134, 0x4dd8, + { 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + NULL, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + STORAGE_CMD_TA_ENCRYPTION_KEY_IS_WRITTEN, + &TeecOperation, + &ErrorOrigin); + if (TeecResult == TEEC_SUCCESS) + *value = TeecOperation.params[0].value.a; + + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + +uint32_t trusty_write_oem_encrypt_data(uint32_t *buf, uint32_t length) +{ + return trusty_base_efuse_or_otp_operation(STORAGE_CMD_WRITE_OEM_ENCRYPT_DATA, + true, buf, length); +} + +uint32_t trusty_oem_encrypt_data_is_written(uint8_t *value) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + + *value = 0; + + TEEC_UUID tempuuid = { 0x2d26d8a8, 0x5134, 0x4dd8, + { 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + NULL, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + STORAGE_CMD_OEM_ENCRYPT_DATA_IS_WRITTEN, + &TeecOperation, + &ErrorOrigin); + if (TeecResult == TEEC_SUCCESS) + *value = TeecOperation.params[0].value.a; + + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + uint32_t trusty_check_security_level_flag(uint8_t flag) { uint32_t levelflag; @@ -1092,6 +1204,322 @@ exit: return TeecResult; } +uint32_t trusty_write_oem_hdcp_key(enum RK_HDCP_KEYID key_id, + uint8_t *byte_buf, uint32_t byte_len) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + + TEEC_UUID tempuuid = { 0x2d26d8a8, 0x5134, 0x4dd8, + { 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + NULL, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.params[0].value.a = key_id; + + TEEC_SharedMemory SharedMem = {0}; + + SharedMem.size = byte_len; + SharedMem.flags = 0; + + TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem); + if (TeecResult != TEEC_SUCCESS) + goto exit; + + TeecOperation.params[1].tmpref.buffer = SharedMem.buffer; + TeecOperation.params[1].tmpref.size = SharedMem.size; + + memcpy(SharedMem.buffer, byte_buf, SharedMem.size); + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + STORAGE_CMD_WRITE_OEM_HDCP_KEY, + &TeecOperation, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + goto exit; + +exit: + TEEC_ReleaseSharedMemory(&SharedMem); + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + +uint32_t trusty_oem_hdcp_key_is_written(enum RK_HDCP_KEYID key_id, uint8_t *value) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + + *value = 0xFF; + + TEEC_UUID tempuuid = { 0x2d26d8a8, 0x5134, 0x4dd8, + { 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + NULL, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.params[0].value.a = key_id; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + STORAGE_CMD_OEM_HDCP_KEY_IS_WRITTEN, + &TeecOperation, + &ErrorOrigin); + if (TeecResult == TEEC_SUCCESS) + *value = TeecOperation.params[0].value.b; + + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + +uint32_t trusty_set_oem_hdcp_key_mask(enum RK_HDCP_KEYID key_id) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + + TEEC_UUID tempuuid = { 0x2d26d8a8, 0x5134, 0x4dd8, + { 0xb3, 0x2f, 0xb3, 0x4b, 0xce, 0xeb, 0xc4, 0x71 } }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + NULL, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.params[0].value.a = key_id; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + STORAGE_CMD_SET_OEM_HDCP_KEY_MASK, + &TeecOperation, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + goto exit; + +exit: + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + +uint32_t trusty_oem_user_ta_transfer(void) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + TEEC_UUID tempuuid = { 0x1db57234, 0xdacd, 0x462d, + { 0x9b, 0xb1, 0xae, 0x79, 0xde, 0x44, 0xe2, 0xa5} }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + const uint8_t transfer_inout[] = "Transfer data test."; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + &TeecOperation, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TEEC_SharedMemory SharedMem0 = {0}; + + SharedMem0.size = sizeof(transfer_inout); + SharedMem0.flags = 0; + + TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem0); + if (TeecResult != TEEC_SUCCESS) + goto exit; + + memcpy(SharedMem0.buffer, transfer_inout, SharedMem0.size); + + TEEC_SharedMemory SharedMem1 = {0}; + + SharedMem1.size = sizeof(transfer_inout); + SharedMem1.flags = 0; + + TeecResult = TEEC_AllocateSharedMemory(&TeecContext, &SharedMem1); + if (TeecResult != TEEC_SUCCESS) + goto exit; + + TeecOperation.params[0].value.a = 66; + TeecOperation.params[1].tmpref.buffer = SharedMem0.buffer; + TeecOperation.params[1].tmpref.size = SharedMem0.size; + TeecOperation.params[2].tmpref.buffer = SharedMem1.buffer; + TeecOperation.params[2].tmpref.size = SharedMem1.size; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + 102, + &TeecOperation, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + goto exit; + + //Check the result + if (TeecOperation.params[0].value.a == 66 + 1 && + TeecOperation.params[0].value.b == TeecOperation.params[0].value.a) + printf("test value : Pass!\n"); + else + printf("test value : Fail! (mismatch values)\n"); + + if (memcmp(SharedMem1.buffer, transfer_inout, sizeof(transfer_inout)) == 0) + printf("test buffer : Pass!\n"); + else + printf("test buffer : Fail! (mismatch buffer)\n"); + +exit: + TEEC_ReleaseSharedMemory(&SharedMem0); + TEEC_ReleaseSharedMemory(&SharedMem1); + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + +uint32_t trusty_oem_user_ta_storage(void) +{ + TEEC_Result TeecResult; + TEEC_Context TeecContext; + TEEC_Session TeecSession; + uint32_t ErrorOrigin; + TEEC_UUID tempuuid = { 0x1db57234, 0xdacd, 0x462d, + { 0x9b, 0xb1, 0xae, 0x79, 0xde, 0x44, 0xe2, 0xa5} }; + TEEC_UUID *TeecUuid = &tempuuid; + TEEC_Operation TeecOperation = {0}; + + TeecResult = OpteeClientApiLibInitialize(); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecResult = TEEC_InitializeContext(NULL, &TeecContext); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_OpenSession(&TeecContext, + &TeecSession, + TeecUuid, + TEEC_LOGIN_PUBLIC, + NULL, + &TeecOperation, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + return TeecResult; + + TeecOperation.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + + TeecResult = TEEC_InvokeCommand(&TeecSession, + 103, + &TeecOperation, + &ErrorOrigin); + if (TeecResult != TEEC_SUCCESS) + goto exit; + +exit: + TEEC_CloseSession(&TeecSession); + TEEC_FinalizeContext(&TeecContext); + + return TeecResult; +} + uint32_t trusty_attest_dh(uint8_t *dh, uint32_t *dh_size) { TEEC_Result TeecResult; diff --git a/u-boot/lib/optee_clientApi/OpteeClientLoadTa.c b/u-boot/lib/optee_clientApi/OpteeClientLoadTa.c new file mode 100644 index 0000000000..ccbd6e290c --- /dev/null +++ b/u-boot/lib/optee_clientApi/OpteeClientLoadTa.c @@ -0,0 +1,162 @@ +/* + * Copyright 2023, Rockchip Electronics Co., Ltd + * hisping lin, + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include + +int is_uuid_equal(TEEC_UUID uuid1, TEEC_UUID uuid2) +{ + bool a, b, c; + + a = (uuid1.timeLow == uuid2.timeLow); + b = (uuid1.timeMid == uuid2.timeMid); + c = (uuid1.timeHiAndVersion == uuid2.timeHiAndVersion); + if ((a & b & c) == 0) { + return 0; + } else { + if (memcmp(uuid1.clockSeqAndNode, + uuid2.clockSeqAndNode, 8) == 0) { + return 1; + } else { + return 0; + } + } +} + +void tee_uuid_from_octets(TEEC_UUID *d, const uint8_t *s) +{ + d->timeLow = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + d->timeMid = (s[4] << 8) | s[5]; + d->timeHiAndVersion = (s[6] << 8) | s[7]; + memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); +} + +static struct blk_desc *dev_desc; +static disk_partition_t part_info; +int search_ta(void *uuid_octets, void *ta, size_t *ta_size) +{ + char fname[255]; + char *format; + unsigned long ret = 0; + TEEC_UUID uuid; + TEEC_UUID ta_uuid; + uint8_t *userta; + struct userta_header *header; + struct userta_item *item; + int ta_ver; + int res; + + if (!uuid_octets || !ta_size) { + printf("TEEC: wrong parameter to search_ta\n"); + return -1; + } + + if (!dev_desc) { + dev_desc = rockchip_get_bootdev(); + if (!dev_desc) { + printf("TEEC: %s: Could not find device\n", __func__); + return -1; + } + + if (part_get_info_by_name(dev_desc, + "userta", &part_info) < 0) { + dev_desc = NULL; + printf("TEEC: Could not find userta partition\n"); + return -1; + } + } + +#ifdef CONFIG_OPTEE_V1 + memcpy(&uuid, uuid_octets, sizeof(TEEC_UUID)); + ta_ver = 1; + format = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x.ta"; +#endif + +#ifdef CONFIG_OPTEE_V2 + tee_uuid_from_octets(&uuid, uuid_octets); + ta_ver = 2; + format = "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x.ta"; +#endif + + snprintf(fname, 255, + format, + uuid.timeLow, + uuid.timeMid, + uuid.timeHiAndVersion, + uuid.clockSeqAndNode[0], + uuid.clockSeqAndNode[1], + uuid.clockSeqAndNode[2], + uuid.clockSeqAndNode[3], + uuid.clockSeqAndNode[4], + uuid.clockSeqAndNode[5], + uuid.clockSeqAndNode[6], + uuid.clockSeqAndNode[7]); + + printf("Attempt to load %s \n", fname); + + userta = (uint8_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, part_info.size * part_info.blksz); + if (!userta) { + printf("TEEC: Malloc failed!\n"); + res = -1; + goto exit; + } + + ret = blk_dread(dev_desc, part_info.start, part_info.size, userta); + if (ret != part_info.size) { + printf("TEEC: blk_dread fail\n"); + res = -1; + goto exit; + } + + header = (struct userta_header *)userta; + if (header->magic != 0x524B5441 || header->img_ver != 1) { + printf("TEEC: userta_header format error! \n"); + res = -1; + goto exit; + } + + item = (struct userta_item *)(header + 1); + + for (int i = 0; i < header->ta_num; i++) { + tee_uuid_from_octets(&ta_uuid, item->ta_uuid); + snprintf(fname, 255, + format, + ta_uuid.timeLow, + ta_uuid.timeMid, + ta_uuid.timeHiAndVersion, + ta_uuid.clockSeqAndNode[0], + ta_uuid.clockSeqAndNode[1], + ta_uuid.clockSeqAndNode[2], + ta_uuid.clockSeqAndNode[3], + ta_uuid.clockSeqAndNode[4], + ta_uuid.clockSeqAndNode[5], + ta_uuid.clockSeqAndNode[6], + ta_uuid.clockSeqAndNode[7]); + debug("search TA %s \n", fname); + debug("item->ta_offset=0x%x item->ta_len=0x%x *ta_size=%zu\n", + item->ta_offset, item->ta_len, *ta_size); + + if (is_uuid_equal(ta_uuid, uuid) && item->ta_ver == ta_ver) { + if (item->ta_len <= *ta_size && ta) + memcpy(ta, userta + item->ta_offset, item->ta_len); + *ta_size = item->ta_len; + res = TA_BINARY_FOUND; + goto exit; + } else { + item++; + } + } + res = TA_BINARY_NOT_FOUND; + +exit: + if (userta) + free(userta); + return res; +} diff --git a/u-boot/lib/optee_clientApi/OpteeClientRPC.c b/u-boot/lib/optee_clientApi/OpteeClientRPC.c index 8085b66997..d9dd5d9cec 100644 --- a/u-boot/lib/optee_clientApi/OpteeClientRPC.c +++ b/u-boot/lib/optee_clientApi/OpteeClientRPC.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -54,107 +55,12 @@ TEEC_Result OpteeRpcFree(uint32_t Address) return TEEC_SUCCESS; } -int is_uuid_equal(TEE_UUID uuid1, TEEC_UUID uuid2) -{ - bool a, b, c; - - a = (uuid1.timeLow == uuid2.timeLow); - b = (uuid1.timeMid == uuid2.timeMid); - c = (uuid1.timeHiAndVersion == uuid2.timeHiAndVersion); - if ((a & b & c) == 0) { - return 0; - } else { - if (memcmp(uuid1.clockSeqAndNode, - uuid2.clockSeqAndNode, 8) == 0) { - return 1; - } else { - return 0; - } - } -} - -/* - * Load a TA from storage into memory and provide it back to OpTEE. - * Param[0] = IN: struct tee_rpc_load_ta_cmd - * Param[1] = IN: all-zero OUT: TA Image allocated - */ -TEEC_Result OpteeRpcCmdLoadTa(t_teesmc32_arg *TeeSmc32Arg) -{ - TEEC_Result TeecResult = TEEC_SUCCESS; - t_teesmc32_param *TeeSmc32Param = NULL; - struct tee_rpc_load_ta_cmd *TeeLoadTaCmd = NULL; - uint32_t TeeLoadTaCmdSize = 0; - - if (TeeSmc32Arg->num_params != 2) { - TeecResult = TEEC_ERROR_BAD_PARAMETERS; - goto Exit; - } - - TEEC_UUID TA_RK_KEYMASTER_UUID = {0x258be795, 0xf9ca, 0x40e6, - {0xa8, 0x69, 0x9c, 0xe6, 0x88, 0x6c, 0x5d, 0x5d} }; - TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg); - TeeLoadTaCmd = (struct tee_rpc_load_ta_cmd *) - (size_t)TeeSmc32Param[0].u.memref.buf_ptr; - TeeLoadTaCmdSize = TeeSmc32Param[0].u.memref.size; - - if ((TeeLoadTaCmd == NULL) || - (TeeLoadTaCmdSize != sizeof(*TeeLoadTaCmd))) { - TeecResult = TEEC_ERROR_BAD_PARAMETERS; - goto Exit; - } - - TEEC_Result Status = 0; - void *ImageData = NULL; - uint32_t ImageSize = 0; - size_t AllocAddress = 0; - - if (is_uuid_equal(TeeLoadTaCmd->uuid, TA_RK_KEYMASTER_UUID)) { - ImageData = (void *)0; - ImageSize = 0; - } else { - ImageData = (void *)0; - ImageSize = 0; - } - - if (Status != 0) { - TeecResult = TEEC_ERROR_ITEM_NOT_FOUND; - goto Exit; - } - - AllocAddress = (size_t) OpteeClientMemAlloc(ImageSize); - - if (AllocAddress == 0) { - TeecResult = TEEC_ERROR_OUT_OF_MEMORY; - goto Exit; - } - - memcpy((void *)AllocAddress, ImageData, ImageSize); - - debug("TEEC: ...TA loaded at 0x%zu of size 0x%X bytes\n", - AllocAddress, ImageSize); - debug("TEEC: ...AllocAddress[0] 0x%X ; AllocAddress[1] 0x%X bytes\n", - *(char *)AllocAddress, *(char *)(AllocAddress+1)); - - TeeLoadTaCmd->va = AllocAddress; - - TeeSmc32Param[1].u.memref.buf_ptr = AllocAddress; - TeeSmc32Param[1].u.memref.size = ImageSize; - -Exit: - TeeSmc32Arg->ret = TeecResult; - TeeSmc32Arg->ret_origin = TEEC_ORIGIN_API; - - debug("TEEC: OpteeRpcCmdLoadTa Exit : TeecResult=0x%X\n", TeecResult); - - return TeecResult; -} - TEEC_Result OpteeRpcCmdLoadV2Ta(t_teesmc32_arg *TeeSmc32Arg) { TEEC_Result TeecResult = TEEC_SUCCESS; t_teesmc32_param *TeeSmc32Param = NULL; - uint8_t uuid[16]; - int i; + int ta_found = 0; + size_t size = 0; if (TeeSmc32Arg->num_params != 2) { TeecResult = TEEC_ERROR_BAD_PARAMETERS; @@ -163,70 +69,22 @@ TEEC_Result OpteeRpcCmdLoadV2Ta(t_teesmc32_arg *TeeSmc32Arg) TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg); - memcpy(uuid, (void *)&TeeSmc32Param[0].u.value, 16); - for (i = 0; i < 16; i++) - debug("TEEC: uuid 0x%x", uuid[i]); - - if (TeeSmc32Param[1].u.memref.buf_ptr == 0) { - debug("TEEC: return size of TA, keymaster_size = 0\n"); - TeeSmc32Param[1].u.memref.size = 0; + size = TeeSmc32Param[1].u.memref.size; + ta_found = search_ta((void *)(size_t)&TeeSmc32Param[0].u.value, + (void *)(size_t)TeeSmc32Param[1].u.memref.buf_ptr, &size); + if (ta_found == TA_BINARY_FOUND) { + TeeSmc32Param[1].u.memref.size = size; + TeecResult = TEEC_SUCCESS; } else { - /*memcpy((void *)(size_t)TeeSmc32Param[1].u.memref.buf_ptr, - (void *)keymaster_data, TeeSmc32Param[1].u.memref.size);*/ - debug("TEEC: memref.buf_ptr = 0x%llx; memref.size = 0x%llx\n", - (uint64_t)TeeSmc32Param[1].u.memref.buf_ptr, - (uint64_t)TeeSmc32Param[1].u.memref.size); + printf(" TA not found \n"); + TeecResult = TEEC_ERROR_ITEM_NOT_FOUND; } Exit: TeeSmc32Arg->ret = TeecResult; TeeSmc32Arg->ret_origin = TEEC_ORIGIN_API; - debug("TEEC: OpteeRpcCmdLoadTa Exit : TeecResult=0x%X\n", TeecResult); - - return TeecResult; -} - -/* - * Free a previously loaded TA and release the memory - * Param[0] = IN: TA Image to free - * - * Um, why is OpTEE holding on to this memory? The OS code suggests that OpTEE - * is using the binary in place out of shared memory but I don't understand how - * runtime modifications of the binary are being prevented if that's the case? - */ -TEEC_Result OpteeRpcCmdFreeTa(t_teesmc32_arg *TeeSmc32Arg) -{ - TEEC_Result TeecResult = TEEC_SUCCESS; - t_teesmc32_param *TeeSmc32Param = NULL; - uint32_t ImageSize = 0; - size_t AllocAddress = 0; - - if (TeeSmc32Arg->num_params != 1) { - TeecResult = TEEC_ERROR_BAD_PARAMETERS; - goto Exit; - } - - TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg); - - AllocAddress = TeeSmc32Param[0].u.memref.buf_ptr; - ImageSize = TeeSmc32Param[0].u.memref.size; - - debug("TEEC: OpteeRpcCmdFreeTa Enter: AllocAddress=0x%X, ImageSize=0x%X\n", - (uint32_t) AllocAddress, (uint32_t) ImageSize); - - if (AllocAddress == 0) { - TeecResult = TEEC_ERROR_BAD_PARAMETERS; - goto Exit; - } - - OpteeClientMemFree((void *)AllocAddress); - -Exit: - TeeSmc32Arg->ret = TeecResult; - TeeSmc32Arg->ret_origin = TEEC_ORIGIN_API; - - debug("TEEC: OpteeRpcCmdFreeTa Exit : TeecResult=0x%X\n", TeecResult); + debug("TEEC: OpteeRpcCmdLoadV2Ta Exit : TeecResult=0x%X\n", TeecResult); return TeecResult; } diff --git a/u-boot/lib/optee_clientApi/tabinary_to_img.py b/u-boot/lib/optee_clientApi/tabinary_to_img.py new file mode 100644 index 0000000000..ed7ecedb9b --- /dev/null +++ b/u-boot/lib/optee_clientApi/tabinary_to_img.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# +# Copyright 2023, Rockchip Electronics Co., Ltd +# hisping lin, +# +# SPDX-License-Identifier: GPL-2.0+ +# + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + + parser.add_argument('--out', required=True, \ + help='Name of image for the TA') + + parser.add_argument('--tadir', required=True, help='Path of TA director') + + return parser.parse_args() + +def main(): + import os + import array + import glob + import struct + import uuid + try: + from Cryptodome.Hash import SHA256 + except ImportError: + from Crypto.Hash import SHA256 + + args = get_args(); + + path = args.tadir + "/*.ta" + files = glob.glob(path) + for f in files: + print(f) + + fimg = open(args.out, 'wb') + magic = 0x524B5441 #RKTA + img_ver = 0x00000001 + ta_num = len(files) + reserve = 0 + header = struct.pack('fdt_blob; uint8_t digest[FIT_MAX_HASH_LEN]; uint8_t digest_read[FIT_MAX_HASH_LEN]; - int sig_node, node, digest_len, i, ret = 0; - - dev = misc_otp_get_device(OTP_S); - if (!dev) - return -ENODEV; - - ret = misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, - &secure_flags, OTP_SECURE_BOOT_ENABLE_SIZE); - if (ret) - return ret; - - if (secure_flags == 0xff) - return 0; + int sig_node, node, digest_len, i; + int ret = 0, written_size = 0; + /* Check burn-key-hash flag in itb first */ sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME); if (sig_node < 0) { debug("%s: No signature node found\n", __func__); @@ -636,7 +626,20 @@ int rsa_burn_key_hash(struct image_sign_info *info) return -1; if (!(prop.burn_key)) - return -EPERM; + return 0; + + /* Handle burn_key_hash process from now on */ + dev = misc_otp_get_device(OTP_S); + if (!dev) + return -ENODEV; + + ret = misc_otp_read(dev, OTP_SECURE_BOOT_ENABLE_ADDR, + &secure_flags, OTP_SECURE_BOOT_ENABLE_SIZE); + if (ret) + return ret; + + if (secure_flags == 0xff) + return 0; if (!prop.hash || !prop.modulus || !prop.public_exponent_BN) return -ENOENT; @@ -686,14 +689,24 @@ int rsa_burn_key_hash(struct image_sign_info *info) goto error; for (i = 0; i < OTP_RSA_HASH_SIZE; i++) { - if (digest_read[i]) { + if (digest_read[i] == digest[i]) { + written_size++; + } else if (digest_read[i] == 0) { + break; + } else { printf("RSA: The secure region has been written.\n"); ret = -EIO; goto error; } } - ret = misc_otp_write(dev, OTP_RSA_HASH_ADDR, digest, OTP_RSA_HASH_SIZE); + if (OTP_RSA_HASH_SIZE - written_size) { + ret = misc_otp_write(dev, OTP_RSA_HASH_ADDR + written_size, digest + written_size, + OTP_RSA_HASH_SIZE - written_size); + if (ret) + goto error; + } + if (ret) goto error; @@ -703,6 +716,7 @@ int rsa_burn_key_hash(struct image_sign_info *info) goto error; if (memcmp(digest, digest_read, digest_len) != 0) { + ret = -EAGAIN; printf("RSA: Write public key hash fail.\n"); goto error; } @@ -713,7 +727,10 @@ int rsa_burn_key_hash(struct image_sign_info *info) if (ret) goto error; - printf("RSA: Write key hash successfully\n"); + if (written_size) + printf("RSA: Repair RSA key hash successfully.\n"); + else + printf("RSA: Write RSA key hash successfully.\n"); error: free(rsa_key); diff --git a/u-boot/lib/string.c b/u-boot/lib/string.c index c4ca944bb4..9634d1d6e9 100644 --- a/u-boot/lib/string.c +++ b/u-boot/lib/string.c @@ -599,6 +599,19 @@ void * memscan(void * addr, int c, size_t size) } #endif +char *memdup(const void *src, size_t len) +{ + char *p; + + p = malloc(len); + if (!p) + return NULL; + + memcpy(p, src, len); + + return p; +} + #ifndef __HAVE_ARCH_STRSTR /** * strstr - Find the first substring in a %NUL terminated string diff --git a/u-boot/make.sh b/u-boot/make.sh index f1d3b5e1da..6051559124 100755 --- a/u-boot/make.sh +++ b/u-boot/make.sh @@ -192,6 +192,14 @@ function process_args() ARG_SPL_BIN="spl/u-boot-spl.bin" shift 1 ;; + --spl-fwver) + ARG_SPL_FWVER="SPL_FWVER=$2" + shift 2 + ;; + --fwver) + ARG_FWVER="FWVER=$2" + shift 2 + ;; --uboot|--fdt|--optee|--mcu|--bl31) # uboot.img components mkdir -p ${REP_DIR} if [ ! -f $2 ]; then @@ -616,9 +624,13 @@ function pack_uboot_itb_image() done # COMPRESSION - COMPRESSION=`awk -F"," '/COMPRESSION=/ { printf $1 }' ${INI} | tr -d ' ' | cut -c 13-` - if [ ! -z "${COMPRESSION}" -a "${COMPRESSION}" != "none" ]; then - COMPRESSION_ARG="-c ${COMPRESSION}" + if grep -q '^CONFIG_IMAGE_GZIP=y' .config ; then + COMPRESSION_ARG="-c gzip" + else + COMPRESSION=`awk -F"," '/COMPRESSION=/ { printf $1 }' ${INI} | tr -d ' ' | cut -c 13-` + if [ ! -z "${COMPRESSION}" -a "${COMPRESSION}" != "none" ]; then + COMPRESSION_ARG="-c ${COMPRESSION}" + fi fi if [ -d ${REP_DIR} ]; then @@ -789,7 +801,7 @@ select_ini_file handle_args_late sub_commands clean_files -make PYTHON=python2 CROSS_COMPILE=${TOOLCHAIN} all --jobs=${JOB} +make PYTHON=python2 ${ARG_SPL_FWVER} ${ARG_FWVER} CROSS_COMPILE=${TOOLCHAIN} all --jobs=${JOB} pack_images finish echo ${TOOLCHAIN} diff --git a/u-boot/net/eth-uclass.c b/u-boot/net/eth-uclass.c index bd153ac13a..b7a0358e4c 100644 --- a/u-boot/net/eth-uclass.c +++ b/u-boot/net/eth-uclass.c @@ -70,8 +70,8 @@ struct udevice *eth_get_dev(void) uc_priv = eth_get_uclass_priv(); if (!uc_priv->current) - eth_errno = uclass_first_device(UCLASS_ETH, - &uc_priv->current); + uclass_first_device(UCLASS_ETH, + &uc_priv->current); return uc_priv->current; } diff --git a/u-boot/scripts/fit.sh b/u-boot/scripts/fit.sh index bbdbf160cf..8999841e3c 100755 --- a/u-boot/scripts/fit.sh +++ b/u-boot/scripts/fit.sh @@ -22,13 +22,24 @@ else fit_gen_boot_itb fit_gen_boot_img fi - fit_gen_uboot_itb - fit_gen_uboot_img - fit_gen_loader + + if [ ! -z "${ARG_INI_TRUST}" ]; then + fit_gen_uboot_itb + fit_gen_uboot_img + fi + + if [ ! -z "${ARG_INI_LOADER}" ]; then + fit_gen_loader + fi echo - fit_msg_uboot + + if [ ! -z "${ARG_INI_TRUST}" ]; then + fit_msg_uboot + fi fit_msg_recovery fit_msg_boot - fit_msg_loader + if [ ! -z "${ARG_INI_LOADER}" ]; then + fit_msg_loader + fi fi diff --git a/u-boot/test/dm/core.c b/u-boot/test/dm/core.c index 052bf8fffb..7e447f728e 100644 --- a/u-boot/test/dm/core.c +++ b/u-boot/test/dm/core.c @@ -479,7 +479,6 @@ static int dm_test_leak(struct unit_test_state *uts) for (i = 0; i < 2; i++) { struct udevice *dev; - int ret; int id; dm_leak_check_start(uts); @@ -489,11 +488,9 @@ static int dm_test_leak(struct unit_test_state *uts) /* Scanning the uclass is enough to probe all the devices */ for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) { - for (ret = uclass_first_device(UCLASS_TEST, &dev); - dev; - ret = uclass_next_device(&dev)) + for (uclass_first_device(UCLASS_TEST, &dev); dev; + uclass_next_device(&dev)) ; - ut_assertok(ret); } ut_assertok(dm_leak_check_end(uts)); @@ -564,7 +561,6 @@ static int dm_test_children(struct unit_test_state *uts) struct udevice *grandchild[NODE_COUNT]; struct udevice *dev; int total; - int ret; int i; /* We don't care about the numbering for this test */ @@ -606,11 +602,9 @@ static int dm_test_children(struct unit_test_state *uts) ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]); /* Probe everything */ - for (ret = uclass_first_device(UCLASS_TEST, &dev); - dev; - ret = uclass_next_device(&dev)) + for (uclass_first_device(UCLASS_TEST, &dev); dev; + uclass_next_device(&dev)) ; - ut_assertok(ret); ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]); @@ -796,11 +790,10 @@ static int dm_test_uclass_devices_get(struct unit_test_state *uts) struct udevice *dev; int ret; - for (ret = uclass_first_device(UCLASS_TEST, &dev); + for (ret = uclass_first_device_check(UCLASS_TEST, &dev); dev; - ret = uclass_next_device(&dev)) { + ret = uclass_next_device_check(&dev)) { ut_assert(!ret); - ut_assert(dev); ut_assert(device_active(dev)); } @@ -830,11 +823,10 @@ static int dm_test_uclass_devices_get_by_name(struct unit_test_state *uts) * this will fail on checking condition: testdev == finddev, since the * uclass_get_device_by_name(), returns the first device by given name. */ - for (ret = uclass_first_device(UCLASS_TEST_FDT, &testdev); + for (ret = uclass_first_device_check(UCLASS_TEST_FDT, &testdev); testdev; - ret = uclass_next_device(&testdev)) { + ret = uclass_next_device_check(&testdev)) { ut_assertok(ret); - ut_assert(testdev); ut_assert(device_active(testdev)); findret = uclass_get_device_by_name(UCLASS_TEST_FDT, diff --git a/u-boot/test/dm/test-fdt.c b/u-boot/test/dm/test-fdt.c index dcc2ef8b65..aaedc399bd 100644 --- a/u-boot/test/dm/test-fdt.c +++ b/u-boot/test/dm/test-fdt.c @@ -311,13 +311,12 @@ static int dm_test_first_next_device(struct unit_test_state *uts) int ret; /* There should be 4 devices */ - for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; + for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; dev; - ret = uclass_next_device(&dev)) { + uclass_next_device(&dev)) { count++; parent = dev_get_parent(dev); } - ut_assertok(ret); ut_asserteq(4, count); /* Remove them and try again, with an error on the second one */ @@ -325,21 +324,56 @@ static int dm_test_first_next_device(struct unit_test_state *uts) pdata = dev_get_platdata(dev); pdata->probe_err = -ENOMEM; device_remove(parent, DM_REMOVE_NORMAL); - ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev)); - ut_asserteq(-ENOMEM, uclass_next_device(&dev)); - ut_asserteq_ptr(dev, NULL); + for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev), + count = 0; + dev; + ret = uclass_next_device_check(&dev)) { + if (!ret) + count++; + else + ut_asserteq(-ENOMEM, ret); + parent = dev_get_parent(dev); + } + ut_asserteq(3, count); /* Now an error on the first one */ ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev)); pdata = dev_get_platdata(dev); pdata->probe_err = -ENOENT; device_remove(parent, DM_REMOVE_NORMAL); - ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev)); + for (uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0; + dev; + uclass_next_device(&dev)) { + count++; + parent = dev_get_parent(dev); + } + ut_asserteq(2, count); return 0; } DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +/* Test iteration through devices in a uclass */ +static int dm_test_uclass_foreach(struct unit_test_state *uts) +{ + struct udevice *dev; + struct uclass *uc; + int count; + + count = 0; + uclass_id_foreach_dev(UCLASS_TEST_FDT, dev, uc) + count++; + ut_asserteq(8, count); + + count = 0; + uclass_foreach_dev(dev, uc) + count++; + ut_asserteq(8, count); + + return 0; +} +DM_TEST(dm_test_uclass_foreach, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + /** * check_devices() - Check return values and pointers * @@ -419,3 +453,24 @@ static int dm_test_first_next_ok_device(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test iteration through devices by drvdata */ +static int dm_test_uclass_drvdata(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT, + DM_TEST_TYPE_FIRST, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_assertok(uclass_first_device_drvdata(UCLASS_TEST_FDT, + DM_TEST_TYPE_SECOND, &dev)); + ut_asserteq_str("d-test", dev->name); + + ut_asserteq(-ENODEV, uclass_first_device_drvdata(UCLASS_TEST_FDT, + DM_TEST_TYPE_COUNT, + &dev)); + + return 0; +} +DM_TEST(dm_test_uclass_drvdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); diff --git a/u-boot/test/dm/test-main.c b/u-boot/test/dm/test-main.c index 4478e6b8fc..bc610e2001 100644 --- a/u-boot/test/dm/test-main.c +++ b/u-boot/test/dm/test-main.c @@ -45,15 +45,13 @@ static int dm_test_init(struct unit_test_state *uts, bool of_live) static int do_autoprobe(struct unit_test_state *uts) { struct udevice *dev; - int ret; /* Scanning the uclass is enough to probe all the devices */ - for (ret = uclass_first_device(UCLASS_TEST, &dev); - dev; - ret = uclass_next_device(&dev)) + for (uclass_first_device(UCLASS_TEST, &dev); dev; + uclass_next_device(&dev)) ; - return ret; + return 0; } static int dm_test_destroy(struct unit_test_state *uts)