diff options
366 files changed, 21752 insertions, 3524 deletions
diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt new file mode 100644 index 0000000..bac4afa --- /dev/null +++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt @@ -0,0 +1,136 @@ +*** Reserved memory regions *** + +Reserved memory is specified as a node under the /reserved-memory node. +The operating system shall exclude reserved memory from normal usage +one can create child nodes describing particular reserved (excluded from +normal use) memory regions. Such memory regions are usually designed for +the special usage by various device drivers. + +Parameters for each memory region can be encoded into the device tree +with the following nodes: + +/reserved-memory node +--------------------- +#address-cells, #size-cells (required) - standard definition + - Should use the same values as the root node +ranges (required) - standard definition + - Should be empty + +/reserved-memory/ child nodes +----------------------------- +Each child of the reserved-memory node specifies one or more regions of +reserved memory. Each child node may either use a 'reg' property to +specify a specific range of reserved memory, or a 'size' property with +optional constraints to request a dynamically allocated block of memory. + +Following the generic-names recommended practice, node names should +reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit +address (@<address>) should be appended to the name if the node is a +static allocation. + +Properties: +Requires either a) or b) below. +a) static allocation + reg (required) - standard definition +b) dynamic allocation + size (required) - length based on parent's #size-cells + - Size in bytes of memory to reserve. + alignment (optional) - length based on parent's #size-cells + - Address boundary for alignment of allocation. + alloc-ranges (optional) - prop-encoded-array (address, length pairs). + - Specifies regions of memory that are + acceptable to allocate from. + +If both reg and size are present, then the reg property takes precedence +and size is ignored. + +Additional properties: +compatible (optional) - standard definition + - may contain the following strings: + - shared-dma-pool: This indicates a region of memory meant to be + used as a shared pool of DMA buffers for a set of devices. It can + be used by an operating system to instantiate the necessary pool + management subsystem if necessary. + - vendor specific string in the form <vendor>,[<device>-]<usage> +no-map (optional) - empty property + - Indicates the operating system must not create a virtual mapping + of the region as part of its standard mapping of system memory, + nor permit speculative access to it under any circumstances other + than under the control of the device driver using the region. +reusable (optional) - empty property + - The operating system can use the memory in this region with the + limitation that the device driver(s) owning the region need to be + able to reclaim it back. Typically that means that the operating + system can use that region to store volatile or cached data that + can be otherwise regenerated or migrated elsewhere. + +Linux implementation note: +- If a "linux,cma-default" property is present, then Linux will use the + region for the default pool of the contiguous memory allocator. + +- If a "linux,dma-default" property is present, then Linux will use the + region for the default pool of the consistent DMA allocator. + +Device node references to reserved memory +----------------------------------------- +Regions in the /reserved-memory node may be referenced by other device +nodes by adding a memory-region property to the device node. + +memory-region (optional) - phandle, specifier pairs to children of /reserved-memory + +Example +------- +This example defines 3 contiguous regions are defined for Linux kernel: +one default of all device drivers (named linux,cma@72000000 and 64MiB in size), +one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and +one for multimedia processing (named multimedia-memory@77000000, 64MiB). + +/ { + #address-cells = <1>; + #size-cells = <1>; + + memory { + reg = <0x40000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* global autoconfigured region for contiguous allocations */ + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x4000000>; + alignment = <0x2000>; + linux,cma-default; + }; + + display_reserved: framebuffer@78000000 { + reg = <0x78000000 0x800000>; + }; + + multimedia_reserved: multimedia@77000000 { + compatible = "acme,multimedia-memory"; + reg = <0x77000000 0x4000000>; + }; + }; + + /* ... */ + + fb0: video@12300000 { + memory-region = <&display_reserved>; + /* ... */ + }; + + scaler: scaler@12500000 { + memory-region = <&multimedia_reserved>; + /* ... */ + }; + + codec: codec@12600000 { + memory-region = <&multimedia_reserved>; + /* ... */ + }; +}; diff --git a/MAINTAINERS b/MAINTAINERS index 1598dc8..c77abba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -295,7 +295,9 @@ F: drivers/misc/stm32mp_fuse.c F: drivers/mmc/stm32_sdmmc2.c F: drivers/phy/phy-stm32-usbphyc.c F: drivers/pinctrl/pinctrl_stm32.c +F: drivers/power/pmic/stpmic1.c F: drivers/power/regulator/stm32-vrefbuf.c +F: drivers/power/regulator/stpmic1.c F: drivers/ram/stm32mp1/ F: drivers/misc/stm32_rcc.c F: drivers/reset/stm32-reset.c @@ -945,11 +945,22 @@ ifneq ($(CONFIG_DM_USB)$(CONFIG_OF_CONTROL)$(CONFIG_BLK),yyy) @echo >&2 "====================================================" endif endif -ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y) -ifneq ($(CONFIG_DM_SCSI),y) +ifeq ($(CONFIG_MVSATA_IDE),y) @echo >&2 "===================== WARNING ======================" - @echo >&2 "This board does not use CONFIG_DM_SCSI. Please update" - @echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release." + @echo >&2 "This board does use CONFIG_MVSATA_IDE which is not" + @echo >&2 "ported to driver-model (DM) yet. Please update the storage" + @echo >&2 "controller driver to use CONFIG_AHCI before the v2019.07" + @echo >&2 "release." + @echo >&2 "Failure to update by the deadline may result in board removal." + @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." + @echo >&2 "====================================================" +endif +ifeq ($(CONFIG_LIBATA),y) +ifneq ($(CONFIG_AHCI),y) + @echo >&2 "===================== WARNING ======================" + @echo >&2 "This board does use CONFIG_LIBATA but has CONFIG_AHCI not" + @echo >&2 "enabled. Please update the storage controller driver to use" + @echo >&2 "CONFIG_AHCI before the v2019.07 release." @echo >&2 "Failure to update by the deadline may result in board removal." @echo >&2 "See doc/driver-model/MIGRATION.txt for more info." @echo >&2 "====================================================" diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4a23e32..4640f3b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1403,11 +1403,15 @@ config ARCH_STM32MP select SYSRESET select SYS_THUMB_BUILD imply CMD_DM + imply CMD_POWEROFF + imply ENV_VARS_UBOOT_RUNTIME_CONFIG help Support for STM32MP SoC family developed by STMicroelectronics, MPUs based on ARM cortex A core - U-BOOT is running in DDR and SPL support is the unsecure First Stage - BootLoader (FSBL) + U-BOOT is running in DDR, loaded by the First Stage BootLoader (FSBL). + FSBL can be TF-A: Trusted Firmware for Cortex A, for trusted boot + chain. + SPL is the unsecure FSBL for the basic boot chain. config ARCH_ROCKCHIP bool "Support Rockchip SoCs" @@ -1464,6 +1468,21 @@ config TI_SECURE_DEVICE authenticated) and the code. See the doc/README.ti-secure file for further details. +if AM43XX || AM33XX || OMAP54XX || ARCH_KEYSTONE +config ISW_ENTRY_ADDR + hex "Address in memory or XIP address of bootloader entry point" + default 0x402F4000 if AM43XX + default 0x402F0400 if AM33XX + default 0x40301350 if OMAP54XX + help + After any reset, the boot ROM searches the boot media for a valid + boot image. For non-XIP devices, the ROM then copies the image into + internal memory. For all boot modes, after the ROM processes the + boot image it eventually computes the entry point address depending + on the device type (secure/non-secure), boot media (xip/non-xip) and + image headers. +endif + source "arch/arm/mach-aspeed/Kconfig" source "arch/arm/mach-at91/Kconfig" @@ -1563,6 +1582,7 @@ source "arch/arm/cpu/armv8/Kconfig" source "arch/arm/mach-imx/Kconfig" source "board/bosch/shc/Kconfig" +source "board/bosch/guardian/Kconfig" source "board/CarMediaLab/flea3/Kconfig" source "board/Marvell/aspenite/Kconfig" source "board/Marvell/gplugd/Kconfig" diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 86a01c2..8167cdb 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -138,7 +138,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-388-clearfog.dtb \ armada-388-gp.dtb \ armada-388-helios4.dtb \ - armada-385-amc.dtb \ + armada-385-db-88f6820-amc.dtb \ armada-385-turris-omnia.dtb \ armada-7040-db.dtb \ armada-7040-db-nand.dtb \ @@ -151,7 +151,8 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-xp-theadorable.dtb \ armada-38x-controlcenterdc.dtb \ armada-385-atl-x530.dtb \ - armada-385-atl-x530DP.dtb + armada-385-atl-x530DP.dtb \ + armada-xp-db-xc3-24g4xg.dtb dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \ uniphier-ld11-global.dtb \ @@ -251,7 +252,8 @@ dtb-$(CONFIG_AM33XX) += \ am335x-pdu001.dtb \ am335x-chiliboard.dtb \ am335x-sl50.dtb \ - am335x-base0033.dtb + am335x-base0033.dtb \ + am335x-guardian.dtb dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb \ am43x-epos-evm.dtb \ am437x-idk-evm.dtb \ @@ -474,6 +476,7 @@ dtb-$(CONFIG_MACH_SUN50I) += \ sun50i-a64-amarula-relic.dtb \ sun50i-a64-bananapi-m64.dtb \ sun50i-a64-nanopi-a64.dtb \ + sun50i-a64-oceanic-5205-5inmfd.dtb \ sun50i-a64-olinuxino.dtb \ sun50i-a64-orangepi-win.dtb \ sun50i-a64-pine64-lts.dtb \ @@ -685,6 +688,8 @@ dtb-$(CONFIG_ARCH_ASPEED) += ast2500-evb.dtb dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb dtb-$(CONFIG_TARGET_STM32MP1) += \ + stm32mp157a-dk1.dtb \ + stm32mp157c-dk2.dtb \ stm32mp157c-ed1.dtb \ stm32mp157c-ev1.dtb diff --git a/arch/arm/dts/am335x-guardian-u-boot.dtsi b/arch/arm/dts/am335x-guardian-u-boot.dtsi new file mode 100644 index 0000000..156b9b0 --- /dev/null +++ b/arch/arm/dts/am335x-guardian-u-boot.dtsi @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 EETS GmbH - https://www.eets.ch/ + * Copyright (C) 2018 Robert Bosch Power Tools GmbH + */ + +/ { + ocp { + u-boot,dm-pre-reloc; + }; +}; + +&l4_wkup { + u-boot,dm-pre-reloc; +}; + +&mmc1 { + u-boot,dm-pre-reloc; +}; + +&mmc1_pins { + u-boot,dm-pre-reloc; +}; + +&rtc { + clocks = <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>; + clock-names = "int-clk"; +}; + +&scm { + u-boot,dm-pre-reloc; +}; + +&uart0 { + u-boot,dm-pre-reloc; +}; + +&uart0_pins { + u-boot,dm-pre-reloc; +}; + +&usb { + u-boot,dm-pre-reloc; +}; + +&usb_ctrl_mod { + u-boot,dm-pre-reloc; +}; + +&usb0 { + u-boot,dm-pre-reloc; +}; + +&usb0_phy { + u-boot,dm-pre-reloc; +}; + +&am33xx_pinmux { + u-boot,dm-pre-reloc; + + lcd0_pins: pinmux_lcd0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLUP | MUX_MODE7) + >; + }; +}; diff --git a/arch/arm/dts/am335x-guardian.dts b/arch/arm/dts/am335x-guardian.dts new file mode 100644 index 0000000..f3f022c --- /dev/null +++ b/arch/arm/dts/am335x-guardian.dts @@ -0,0 +1,509 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2018 Robert Bosch Power Tools GmbH + */ +/dts-v1/; + +#include "am33xx.dtsi" +#include <dt-bindings/input/input.h> +#include <dt-bindings/interrupt-controller/irq.h> + +/ { + model = "Bosch AM335x Guardian"; + compatible = "bosch,am335x-guardian", "ti,am33xx"; + + chosen { + stdout-path = &uart0; + tick-timer = &timer2; + }; + + cpus { + cpu@0 { + cpu0-supply = <&dcdc2_reg>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_pins>; + + button21 { + label = "guardian-power-button"; + linux,code = <KEY_POWER>; + gpios = <&gpio2 21 0>; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins>; + + led1 { + label = "green:heartbeat"; + gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led2 { + label = "green:mmc0"; + gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + }; + + panel { + compatible = "ti,tilcdc,panel"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&lcd_pins_default &lcd_disen_pins>; + pinctrl-1 = <&lcd_pins_sleep>; + + display-timings { + 320x240 { + hactive = <320>; + vactive = <240>; + hback-porch = <68>; + hfront-porch = <20>; + hsync-len = <1>; + vback-porch = <18>; + vfront-porch = <4>; + vsync-len = <1>; + clock-frequency = <9000000>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; + panel-info { + ac-bias = <255>; + ac-bias-intrpt = <0>; + dma-burst-sz = <16>; + bpp = <24>; + bus-width = <16>; + fdd = <0x80>; + sync-edge = <0>; + sync-ctrl = <1>; + raster-order = <0>; + fifo-th = <0>; + }; + + }; + + pwm7: dmtimer-pwm { + compatible = "ti,omap-dmtimer-pwm"; + ti,timers = <&timer7>; + pinctrl-names = "default"; + pinctrl-0 = <&dmtimer7_pins>; + }; + + vmmcsd_fixed: regulator-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&cppi41dma { + status = "okay"; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins>; + ranges = <0 0 0x08000000 0x1000000>; /* CS0: 16MB for NAND */ + status = "okay"; + + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ + ti,nand-ecc-opt = "bch16"; + ti,elm-id = <&elm>; + nand-bus-width = <8>; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + /* + * MTD partition table + * + * All SPL-* partitions are sized to minimal length which can + * be independently programmable. For NAND flash this is equal + * to size of erase-block. + */ + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "SPL"; + reg = <0x0 0x40000>; + }; + + partition@1 { + label = "SPL.backup1"; + reg = <0x40000 0x40000>; + }; + + partition@2 { + label = "SPL.backup2"; + reg = <0x80000 0x40000>; + }; + + partition@3 { + label = "SPL.backup3"; + reg = <0xc0000 0x40000>; + }; + + partition@4 { + label = "u-boot"; + reg = <0x100000 0x100000>; + }; + + partition@5 { + label = "u-boot.backup1"; + reg = <0x200000 0x100000>; + }; + + partition@6 { + label = "u-boot-env"; + reg = <0x300000 0x40000>; + }; + + partition@7 { + label = "u-boot-env.backup1"; + reg = <0x340000 0x40000>; + }; + + partition@8 { + label = "UBI"; + reg = <0x380000 0x1fc80000>; + }; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + clock-frequency = <400000>; + status = "okay"; + + tps: tps@24 { + reg = <0x24>; + }; +}; + +&lcdc { + blue-and-red-wiring = "crossed"; + status = "okay"; +}; + +&mmc1 { + bus-width = <0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vmmcsd_fixed>; + status = "okay"; +}; + +&rtc { + clocks = <&clk_32768_ck>, <&clk_24mhz_clkctrl AM3_CLK_24MHZ_CLKDIV32K_CLKCTRL 0>; + clock-names = "ext-clk", "int-clk"; + system-power-controller; +}; + +&spi0 { + ti,pindir-d0-out-d1-in; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + status = "okay"; +}; + +/include/ "tps65217.dtsi" + +&tps { + ti,pmic-shutdown-controller; + interrupt-parent = <&intc>; + interrupts = <7>; /* NMI */ + + backlight { + isel = <1>; /* 1 - ISET1, 2 ISET2 */ + fdim = <100>; /* TPS65217_BL_FDIM_100HZ */ + default-brightness = <100>; + }; + + regulators { + dcdc1_reg: regulator@0 { + regulator-name = "vdds_dpr"; + regulator-always-on; + }; + + dcdc2_reg: regulator@1 { + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1351500>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3_reg: regulator@2 { + regulator-name = "vdd_core"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@3 { + regulator-name = "vio,vrtc,vdds"; + regulator-always-on; + }; + + ldo2_reg: regulator@4 { + regulator-name = "vdd_3v3aux"; + regulator-always-on; + }; + + ldo3_reg: regulator@5 { + regulator-name = "vdd_1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo4_reg: regulator@6 { + regulator-name = "vdd_3v3a"; + regulator-always-on; + }; + }; +}; + +&tscadc { + status = "okay"; + + adc { + ti,adc-channels = <0 1 2 3 4 5 6>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0 { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1 { + dr_mode = "host"; + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&clkout2_pin &gpio_pins>; + + clkout2_pin: pinmux_clkout2_pin { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) + >; + }; + + dmtimer7_pins: pinmux_dmtimer7_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE5) + >; + }; + + gpio_keys_pins: pinmux_gpio_keys_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x940, PIN_INPUT | MUX_MODE7) + >; + }; + + gpio_pins: pinmux_gpio_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE7) + AM33XX_IOPAD(0x990, PIN_OUTPUT | MUX_MODE7) + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) + >; + }; + + lcd_disen_pins: pinmux_lcd_disen_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9a4, PIN_OUTPUT_PULLUP | SLEWCTRL_SLOW | MUX_MODE7) + >; + }; + + lcd_pins_default: pinmux_lcd_pins_default { + pinctrl-single,pins = < + AM33XX_IOPAD(0x820, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x824, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x828, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x82c, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x830, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x834, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x838, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x83c, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE1) + AM33XX_IOPAD(0x8a0, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8a4, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8a8, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8ac, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8b0, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8b4, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8b8, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8bc, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8c0, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8c4, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8c8, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8cc, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8d0, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8d4, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8d8, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8dc, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8e0, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8e4, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8e8, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + AM33XX_IOPAD(0x8ec, PIN_OUTPUT | SLEWCTRL_SLOW | MUX_MODE0) + >; + }; + + lcd_pins_sleep: pinmux_lcd_pins_sleep { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8a0, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8a4, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8a8, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8ac, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8b0, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8b4, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8b8, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8bc, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8c0, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8c4, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8c8, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8cc, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8d0, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8d4, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8d8, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8dc, PULL_DISABLE | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE7) + AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | SLEWCTRL_SLOW | MUX_MODE7) + >; + }; + + leds_pins: pinmux_leds_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x868, PIN_OUTPUT | MUX_MODE7) + AM33XX_IOPAD(0x86c, PIN_OUTPUT | MUX_MODE7) + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) + >; + }; + + spi0_pins: pinmux_spi0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x950, PIN_OUTPUT_PULLDOWN | MUX_MODE0) + AM33XX_IOPAD(0x954, PIN_OUTPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x95c, PIN_OUTPUT_PULLUP | MUX_MODE0) + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) + >; + }; + + nandflash_pins: pinmux_nandflash_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x800, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x804, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x808, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x80c, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x810, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x814, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x818, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x81c, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x870, PIN_INPUT | MUX_MODE0) + AM33XX_IOPAD(0x874, PIN_OUTPUT | MUX_MODE0) + AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) + AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) + AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) + AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) + AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) + >; + }; +}; diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi index 0b2a78d..e4c35d4 100644 --- a/arch/arm/dts/armada-370-xp.dtsi +++ b/arch/arm/dts/armada-370-xp.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Marvell Armada 370 and Armada XP SoC * @@ -8,50 +9,10 @@ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * Ben Dooks <ben.dooks@codethink.co.uk> * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * This file contains the definitions that are common to the Armada * 370 and Armada XP SoC. */ -/include/ "skeleton64.dtsi" - #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16)) / { @@ -86,7 +47,7 @@ pcie-mem-aperture = <0xf8000000 0x7e00000>; pcie-io-aperture = <0xffe00000 0x100000>; - devbus-bootcs { + devbus_bootcs: devbus-bootcs { compatible = "marvell,mvebu-devbus"; reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>; ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>; @@ -96,7 +57,7 @@ status = "disabled"; }; - devbus-cs0 { + devbus_cs0: devbus-cs0 { compatible = "marvell,mvebu-devbus"; reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>; ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>; @@ -106,7 +67,7 @@ status = "disabled"; }; - devbus-cs1 { + devbus_cs1: devbus-cs1 { compatible = "marvell,mvebu-devbus"; reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>; ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>; @@ -116,7 +77,7 @@ status = "disabled"; }; - devbus-cs2 { + devbus_cs2: devbus-cs2 { compatible = "marvell,mvebu-devbus"; reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>; ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>; @@ -126,7 +87,7 @@ status = "disabled"; }; - devbus-cs3 { + devbus_cs3: devbus-cs3 { compatible = "marvell,mvebu-devbus"; reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>; ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>; @@ -141,34 +102,13 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>; - u-boot,dm-pre-reloc; - rtc@10300 { + rtc: rtc@10300 { compatible = "marvell,orion-rtc"; reg = <0x10300 0x20>; interrupts = <50>; }; - spi0: spi@10600 { - reg = <0x10600 0x28>; - #address-cells = <1>; - #size-cells = <0>; - cell-index = <0>; - interrupts = <30>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - - spi1: spi@10680 { - reg = <0x10680 0x28>; - #address-cells = <1>; - #size-cells = <0>; - cell-index = <1>; - interrupts = <92>; - clocks = <&coreclk 0>; - status = "disabled"; - }; - i2c0: i2c@11000 { compatible = "marvell,mv64xxx-i2c"; #address-cells = <1>; @@ -235,33 +175,38 @@ msi-controller; }; - coherency-fabric@20200 { + coherencyfab: coherency-fabric@20200 { compatible = "marvell,coherency-fabric"; reg = <0x20200 0xb0>, <0x21010 0x1c>; }; - timer@20300 { + timer: timer@20300 { reg = <0x20300 0x30>, <0x21040 0x30>; interrupts = <37>, <38>, <39>, <40>, <5>, <6>; }; - watchdog@20300 { + watchdog: watchdog@20300 { reg = <0x20300 0x34>, <0x20704 0x4>; }; - pmsu@22000 { + cpurst: cpurst@20800 { + compatible = "marvell,armada-370-cpu-reset"; + reg = <0x20800 0x8>; + }; + + pmsu: pmsu@22000 { compatible = "marvell,armada-370-pmsu"; reg = <0x22000 0x1000>; }; - usb@50000 { + usb0: usb@50000 { compatible = "marvell,orion-ehci"; reg = <0x50000 0x500>; interrupts = <45>; status = "disabled"; }; - usb@51000 { + usb1: usb@51000 { compatible = "marvell,orion-ehci"; reg = <0x51000 0x500>; interrupts = <46>; @@ -275,7 +220,7 @@ status = "disabled"; }; - mdio: mdio { + mdio: mdio@72004 { #address-cells = <1>; #size-cells = <0>; compatible = "marvell,orion-mdio"; @@ -290,7 +235,7 @@ status = "disabled"; }; - sata@a0000 { + sata: sata@a0000 { compatible = "marvell,armada-370-sata"; reg = <0xa0000 0x5000>; interrupts = <55>; @@ -309,7 +254,7 @@ status = "disabled"; }; - mvsdio@d4000 { + sdio: mvsdio@d4000 { compatible = "marvell,orion-sdio"; reg = <0xd4000 0x200>; interrupts = <54>; @@ -321,6 +266,42 @@ status = "disabled"; }; }; + + spi0: spi@10600 { + reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */ + <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */ + <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */ + <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */ + <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */ + <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */ + <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */ + <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */ + <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */ + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = <30>; + clocks = <&coreclk 0>; + status = "disabled"; + }; + + spi1: spi@10680 { + reg = <MBUS_ID(0xf0, 0x01) 0x10680 0x28>, /* control */ + <MBUS_ID(0x01, 0x1a) 0 0xffffffff>, /* CS0 */ + <MBUS_ID(0x01, 0x5a) 0 0xffffffff>, /* CS1 */ + <MBUS_ID(0x01, 0x9a) 0 0xffffffff>, /* CS2 */ + <MBUS_ID(0x01, 0xda) 0 0xffffffff>, /* CS3 */ + <MBUS_ID(0x01, 0x1b) 0 0xffffffff>, /* CS4 */ + <MBUS_ID(0x01, 0x5b) 0 0xffffffff>, /* CS5 */ + <MBUS_ID(0x01, 0x9b) 0 0xffffffff>, /* CS6 */ + <MBUS_ID(0x01, 0xdb) 0 0xffffffff>; /* CS7 */ + #address-cells = <1>; + #size-cells = <0>; + cell-index = <1>; + interrupts = <92>; + clocks = <&coreclk 0>; + status = "disabled"; + }; }; clocks { diff --git a/arch/arm/dts/armada-385-amc.dts b/arch/arm/dts/armada-385-amc.dts deleted file mode 100644 index d292851..0000000 --- a/arch/arm/dts/armada-385-amc.dts +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Device Tree file for Marvell Armada 385 development board - * (DB-88F6820-AMC) - * - * Copyright (C) 2014 Marvell - * - * Gregory CLEMENT <gregory.clement@free-electrons.com> - * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without - * any warranty of any kind, whether express or implied. - * - * Or, alternatively, - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/dts-v1/; -#include "armada-385.dtsi" -#include <dt-bindings/gpio/gpio.h> - -/ { - model = "Marvell Armada 385 AMC"; - compatible = "marvell,a385-amc", "marvell,armada385", "marvell,armada380"; - - chosen { - stdout-path = "serial0:115200n8"; - }; - - aliases { - ethernet0 = ð0; - ethernet1 = ð2; - i2c0 = &i2c0; - spi1 = &spi1; - }; - - memory { - device_type = "memory"; - reg = <0x00000000 0x80000000>; /* 2 GB */ - }; - - soc { - ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 - MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>; - - internal-regs { - i2c@11000 { - clock-frequency = <100000>; - u-boot,i2c-slave-addr = <0x0>; - pinctrl-names = "default"; - pinctrl-0 = <&i2c0_pins>; - status = "okay"; - }; - - serial@12000 { - /* - * Exported on the micro USB connector CON16 - * through an FTDI - */ - - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins>; - status = "okay"; - u-boot,dm-pre-reloc; - }; - - ethernet@34000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "sgmii"; - }; - - usb@58000 { - status = "okay"; - }; - - ethernet@70000 { - pinctrl-names = "default"; - /* - * The Reference Clock 0 is used to provide a - * clock to the PHY - */ - pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - - - mdio@72004 { - pinctrl-names = "default"; - pinctrl-0 = <&mdio_pins>; - - phy0: ethernet-phy@1 { - reg = <1>; - }; - - phy1: ethernet-phy@0 { - reg = <0>; - }; - }; - - flash@d0000 { - status = "okay"; - num-cs = <1>; - marvell,nand-keep-config; - marvell,nand-enable-arbiter; - nand-on-flash-bbt; - }; - }; - - pcie { - status = "okay"; - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - - }; - }; -}; - -&spi1 { - pinctrl-names = "default"; - pinctrl-0 = <&spi1_pins>; - status = "okay"; - u-boot,dm-pre-reloc; - - spi-flash@0 { - u-boot,dm-pre-reloc; - #address-cells = <1>; - #size-cells = <1>; - compatible = "st,m25p128", "jedec,spi-nor"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <50000000>; - m25p,fast-read; - }; -}; - -&refclk { - clock-frequency = <20000000>; -}; diff --git a/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi b/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi index 7074a73..79b694c 100644 --- a/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi +++ b/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi @@ -11,3 +11,7 @@ &uart0 { u-boot,dm-pre-reloc; }; + +&watchdog { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/armada-385-db-88f6820-amc.dts b/arch/arm/dts/armada-385-db-88f6820-amc.dts new file mode 100644 index 0000000..59a425f --- /dev/null +++ b/arch/arm/dts/armada-385-db-88f6820-amc.dts @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Device Tree file for Marvell Armada 385 AMC board + * (DB-88F6820-AMC) + * + * Copyright (C) 2017 Allied Telesis Labs + */ + +/dts-v1/; +#include "armada-385.dtsi" + +#include <dt-bindings/gpio/gpio.h> + +/ { + model = "Marvell Armada 385 AMC"; + compatible = "marvell,a385-db-amc", "marvell,armada385", "marvell,armada380"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + ethernet1 = ð2; + i2c0 = &i2c0; + spi1 = &spi1; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2GB */ + }; + + soc { + ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>; + }; +}; + +&i2c0 { + u-boot,i2c-slave-addr = <0x0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; +}; + +&uart0 { + /* + * Exported on the micro USB connector CON3 + * through an FTDI + */ + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + u-boot,dm-pre-reloc; +}; + + +ð0 { + pinctrl-names = "default"; + /* + * The Reference Clock 0 is used to provide a + * clock to the PHY + */ + pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; +}; + +ð2 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; +}; + +&usb0 { + status = "okay"; +}; + + + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@0 { + reg = <0>; + }; +}; + +&nand_controller { + status = "okay"; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; +}; + +&pciec { + status = "okay"; +}; + +&pcie1 { + /* Port 0, Lane 0 */ + status = "okay"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + reg = <0x00000000 0x00100000>; + label = "u-boot"; + }; + partition@100000 { + reg = <0x00100000 0x00040000>; + label = "u-boot-env"; + }; + }; + }; +}; + +&refclk { + clock-frequency = <20000000>; +}; diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi b/arch/arm/dts/armada-xp-98dx3236.dtsi new file mode 100644 index 0000000..5df1d18 --- /dev/null +++ b/arch/arm/dts/armada-xp-98dx3236.dtsi @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Marvell 98dx3236 family SoC + * + * Copyright (C) 2016 Allied Telesis Labs + * + * Contains definitions specific to the 98dx3236 SoC that are not + * common to all Armada XP SoCs. + */ + +#include "armada-370-xp.dtsi" + +/ { + #address-cells = <2>; + #size-cells = <2>; + + model = "Marvell 98DX3236 SoC"; + compatible = "marvell,armadaxp-98dx3236", "marvell,armada-370-xp"; + + aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "marvell,98dx3236-smp"; + + cpu@0 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <0>; + clocks = <&cpuclk 0>; + clock-latency = <1000000>; + }; + }; + + soc { + compatible = "marvell,armadaxp-mbus", "simple-bus"; + + ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000 + MBUS_ID(0x03, 0x00) 0 0 0xa8000000 0x4000000 + MBUS_ID(0x08, 0x00) 0 0 0xac000000 0x100000>; + + bootrom { + compatible = "marvell,bootrom"; + reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>; + }; + + /* + * 98DX3236 has 1 x1 PCIe unit Gen2.0 + */ + pciec: pcie@82000000 { + compatible = "marvell,armada-xp-pcie"; + status = "disabled"; + device_type = "pci"; + + #address-cells = <3>; + #size-cells = <2>; + + msi-parent = <&mpic>; + bus-range = <0x00 0xff>; + + ranges = + <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000 /* Port 0.0 registers */ + 0x82000000 0x1 0 MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */ + 0x81000000 0x1 0 MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO */>; + + pcie1: pcie@1,0 { + device_type = "pci"; + assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0 + 0x81000000 0 0 0x81000000 0x1 0 1 0>; + bus-range = <0x00 0xff>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &mpic 58>; + marvell,pcie-port = <0>; + marvell,pcie-lane = <0>; + clocks = <&gateclk 5>; + status = "disabled"; + }; + }; + + internal-regs { + sdramc: sdramc@1400 { + compatible = "marvell,armada-xp-sdram-controller"; + reg = <0x1400 0x500>; + }; + + L2: l2-cache@8000 { + compatible = "marvell,aurora-system-cache"; + reg = <0x08000 0x1000>; + cache-id-part = <0x100>; + cache-level = <2>; + cache-unified; + wt-override; + }; + + gpio0: gpio@18100 { + compatible = "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <82>, <83>, <84>, <85>; + }; + + /* does not exist */ + gpio1: gpio@18140 { + compatible = "marvell,orion-gpio"; + reg = <0x18140 0x40>; + status = "disabled"; + }; + + gpio2: gpio@18180 { /* rework some properties */ + compatible = "marvell,orion-gpio"; + reg = <0x18180 0x40>; + ngpios = <1>; /* only gpio #32 */ + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupts = <87>; + }; + + systemc: system-controller@18200 { + compatible = "marvell,armada-370-xp-system-controller"; + reg = <0x18200 0x500>; + }; + + gateclk: clock-gating-control@18220 { + compatible = "marvell,mv98dx3236-gating-clock"; + reg = <0x18220 0x4>; + clocks = <&coreclk 0>; + #clock-cells = <1>; + }; + + cpuclk: clock-complex@18700 { + #clock-cells = <1>; + compatible = "marvell,mv98dx3236-cpu-clock"; + reg = <0x18700 0x24>, <0x1c054 0x10>; + clocks = <&coreclk 1>; + }; + + corediv-clock@18740 { + status = "disabled"; + }; + + cpu-config@21000 { + compatible = "marvell,armada-xp-cpu-config"; + reg = <0x21000 0x8>; + }; + + ethernet@70000 { + compatible = "marvell,armada-xp-neta"; + }; + + ethernet@74000 { + compatible = "marvell,armada-xp-neta"; + }; + + xor1: xor@f0800 { + compatible = "marvell,orion-xor"; + reg = <0xf0800 0x100 + 0xf0a00 0x100>; + clocks = <&gateclk 22>; + status = "okay"; + + xor10 { + interrupts = <51>; + dmacap,memcpy; + dmacap,xor; + }; + xor11 { + interrupts = <52>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; + + nand_controller: nand@d0000 { + clocks = <&dfx_coredivclk 0>; + }; + + xor0: xor@f0900 { + compatible = "marvell,orion-xor"; + reg = <0xF0900 0x100 + 0xF0B00 0x100>; + clocks = <&gateclk 28>; + status = "okay"; + + xor00 { + interrupts = <94>; + dmacap,memcpy; + dmacap,xor; + }; + xor01 { + interrupts = <95>; + dmacap,memcpy; + dmacap,xor; + dmacap,memset; + }; + }; + }; + + dfx: dfx-server@ac000000 { + compatible = "marvell,dfx-server", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>; + reg = <MBUS_ID(0x08, 0x00) 0 0x100000>; + + thermal: thermal@f8078 { + compatible = "marvell,armada380-thermal"; + reg = <0xf8078 0x4>, <0xf8074 0x4>; + status = "okay"; + }; + + coreclk: mvebu-sar@f8204 { + compatible = "marvell,mv98dx3236-core-clock"; + reg = <0xf8204 0x4>; + #clock-cells = <1>; + }; + + dfx_coredivclk: corediv-clock@f8268 { + compatible = "marvell,mv98dx3236-corediv-clock"; + reg = <0xf8268 0xc>; + #clock-cells = <1>; + clocks = <&mainpll>; + clock-output-names = "nand"; + }; + }; + + switch: switch@a8000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x03, 0x00) 0 0x100000>; + + pp0: packet-processor@0 { + compatible = "marvell,prestera-98dx3236", "marvell,prestera"; + reg = <0 0x4000000>; + interrupts = <33>, <34>, <35>; + dfx = <&dfx>; + }; + }; + }; + + clocks { + /* 25 MHz reference crystal */ + refclk: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + }; +}; + +&i2c0 { + compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11000 0x100>; +}; + +&i2c1 { + compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11100 0x100>; +}; + +&mpic { + reg = <0x20a00 0x2d0>, <0x21070 0x58>; +}; + +&rtc { + status = "disabled"; +}; + +&timer { + compatible = "marvell,armada-xp-timer"; + clocks = <&coreclk 2>, <&refclk>; + clock-names = "nbclk", "fixed"; +}; + +&watchdog { + compatible = "marvell,armada-xp-wdt"; + clocks = <&coreclk 2>, <&refclk>; + clock-names = "nbclk", "fixed"; +}; + +&cpurst { + reg = <0x20800 0x20>; +}; + +&usb0 { + clocks = <&gateclk 18>; +}; + +&usb1 { + clocks = <&gateclk 19>; +}; + +&pinctrl { + compatible = "marvell,98dx3236-pinctrl"; + + nand_pins: nand-pins { + marvell,pins = "mpp20", "mpp21", "mpp22", + "mpp23", "mpp24", "mpp25", + "mpp26", "mpp27", "mpp28", + "mpp29", "mpp30"; + marvell,function = "dev"; + }; + + nand_rb: nand-rb { + marvell,pins = "mpp19"; + marvell,function = "nand"; + }; + + spi0_pins: spi0-pins { + marvell,pins = "mpp0", "mpp1", + "mpp2", "mpp3"; + marvell,function = "spi0"; + }; +}; + +&spi0 { + compatible = "marvell,armada-xp-spi", "marvell,orion-spi"; + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; +}; + +&sdio { + status = "disabled"; +}; diff --git a/arch/arm/dts/armada-xp-98dx3336.dtsi b/arch/arm/dts/armada-xp-98dx3336.dtsi new file mode 100644 index 0000000..1d9d8a8 --- /dev/null +++ b/arch/arm/dts/armada-xp-98dx3336.dtsi @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Marvell 98dx3336 family SoC + * + * Copyright (C) 2016 Allied Telesis Labs + * + * Contains definitions specific to the 98dx3236 SoC that are not + * common to all Armada XP SoCs. + */ + +#include "armada-xp-98dx3236.dtsi" + +/ { + model = "Marvell 98DX3336 SoC"; + compatible = "marvell,armadaxp-98dx3336", "marvell,armadaxp-98dx3236", "marvell,armada-370-xp"; + + cpus { + cpu@1 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <1>; + clocks = <&cpuclk 1>; + clock-latency = <1000000>; + }; + }; + + soc { + internal-regs { + resume@20980 { + compatible = "marvell,98dx3336-resume-ctrl"; + reg = <0x20980 0x10>; + }; + }; + }; +}; + +&pp0 { + compatible = "marvell,prestera-98dx3336", "marvell,prestera"; +}; diff --git a/arch/arm/dts/armada-xp-98dx4251.dtsi b/arch/arm/dts/armada-xp-98dx4251.dtsi new file mode 100644 index 0000000..48ffdc7 --- /dev/null +++ b/arch/arm/dts/armada-xp-98dx4251.dtsi @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree Include file for Marvell 98dx4521 family SoC + * + * Copyright (C) 2016 Allied Telesis Labs + * + * Contains definitions specific to the 98dx4521 SoC that are not + * common to all Armada XP SoCs. + */ + +#include "armada-xp-98dx3236.dtsi" + +/ { + model = "Marvell 98DX4251 SoC"; + compatible = "marvell,armadaxp-98dx4251", "marvell,armadaxp-98dx3236", "marvell,armada-370-xp"; + + cpus { + cpu@1 { + device_type = "cpu"; + compatible = "marvell,sheeva-v7"; + reg = <1>; + clocks = <&cpuclk 1>; + clock-latency = <1000000>; + }; + }; + + soc { + internal-regs { + resume@20980 { + compatible = "marvell,98dx3336-resume-ctrl"; + reg = <0x20980 0x10>; + }; + }; + }; +}; + +&sdio { + status = "okay"; +}; + +&pinctrl { + compatible = "marvell,98dx4251-pinctrl"; + + sdio_pins: sdio-pins { + marvell,pins = "mpp5", "mpp6", "mpp7", + "mpp8", "mpp9", "mpp10"; + marvell,function = "sd0"; + }; +}; + +&pp0 { + compatible = "marvell,prestera-98dx4251", "marvell,prestera"; + interrupts = <33>, <34>, <35>, <36>; +}; diff --git a/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi new file mode 100644 index 0000000..90cad85 --- /dev/null +++ b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +&uart0 { + u-boot,dm-pre-reloc; +}; + +&nand_controller { + compatible="marvell,mvebu-pxa3xx-nand"; + status = "okay"; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; +}; + +&spi0 { + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + }; +}; diff --git a/arch/arm/dts/armada-xp-db-xc3-24g4xg.dts b/arch/arm/dts/armada-xp-db-xc3-24g4xg.dts new file mode 100644 index 0000000..d4b5288 --- /dev/null +++ b/arch/arm/dts/armada-xp-db-xc3-24g4xg.dts @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for DB-XC3-24G4XG board + * + * Copyright (C) 2016 Allied Telesis Labs + * + * Based on armada-xp-db.dts + * + * Note: this Device Tree assumes that the bootloader has remapped the + * internal registers to 0xf1000000 (instead of the default + * 0xd0000000). The 0xf1000000 is the default used by the recent, + * DT-capable, U-Boot bootloaders provided by Marvell. Some earlier + * boards were delivered with an older version of the bootloader that + * left internal registers mapped at 0xd0000000. If you are in this + * situation, you should either update your bootloader (preferred + * solution) or the below Device Tree should be adjusted. + */ + +/dts-v1/; +#include "armada-xp-98dx3336.dtsi" +#include "armada-xp-db-xc3-24g4xg-u-boot.dtsi" + +/ { + model = "DB-XC3-24G4XG"; + compatible = "marvell,armadaxp-98dx3336", "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp"; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + aliases { + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0 0x00000000 0 0x40000000>; /* 1 GB */ + }; +}; + +&L2 { + arm,parity-enable; + marvell,ecc-enable; +}; + +&devbus_bootcs { + status = "okay"; + + /* Device Bus parameters are required */ + + /* Read parameters */ + devbus,bus-width = <16>; + devbus,turn-off-ps = <60000>; + devbus,badr-skew-ps = <0>; + devbus,acc-first-ps = <124000>; + devbus,acc-next-ps = <248000>; + devbus,rd-setup-ps = <0>; + devbus,rd-hold-ps = <0>; + + /* Write parameters */ + devbus,sync-enable = <0>; + devbus,wr-high-ps = <60000>; + devbus,wr-low-ps = <60000>; + devbus,ale-wr-ps = <60000>; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&i2c0 { + clock-frequency = <100000>; + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + m25p,fast-read; + + partition@u-boot { + reg = <0x00000000 0x00100000>; + label = "u-boot"; + }; + partition@u-boot-env { + reg = <0x00100000 0x00040000>; + label = "u-boot-env"; + }; + partition@unused { + reg = <0x00140000 0x00ec0000>; + label = "unused"; + }; + + }; +}; diff --git a/arch/arm/dts/armada-xp-gp.dts b/arch/arm/dts/armada-xp-gp.dts index 27799d1..1139e94 100644 --- a/arch/arm/dts/armada-xp-gp.dts +++ b/arch/arm/dts/armada-xp-gp.dts @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree file for Marvell Armada XP development board * (DB-MV784MP-GP) @@ -8,44 +9,6 @@ * Gregory CLEMENT <gregory.clement@free-electrons.com> * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Note: this Device Tree assumes that the bootloader has remapped the * internal registers to 0xf1000000 (instead of the default * 0xd0000000). The 0xf1000000 is the default used by the recent, @@ -68,11 +31,7 @@ stdout-path = "serial0:115200n8"; }; - aliases { - spi0 = &spi0; - }; - - memory { + memory@0 { device_type = "memory"; /* * 8 GB of plug-in RAM modules by default.The amount @@ -98,7 +57,10 @@ soc { ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 - MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000>; + MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000 + MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000 + MBUS_ID(0x0c, 0x04) 0 0 0xf1200000 0x100000>; devbus-bootcs { status = "okay"; @@ -128,31 +90,9 @@ }; }; - pcie-controller { - status = "okay"; - - /* - * The 3 slots are physically present as - * standard PCIe slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - pcie@9,0 { - /* Port 2, Lane 0 */ - status = "okay"; - }; - pcie@10,0 { - /* Port 3, Lane 0 */ - status = "okay"; - }; - }; - internal-regs { serial@12000 { status = "okay"; - u-boot,dm-pre-reloc; }; serial@12100 { status = "okay"; @@ -177,43 +117,33 @@ status = "okay"; }; - mdio { - phy0: ethernet-phy@0 { - reg = <16>; - }; - - phy1: ethernet-phy@1 { - reg = <17>; - }; - - phy2: ethernet-phy@2 { - reg = <18>; - }; - - phy3: ethernet-phy@3 { - reg = <19>; - }; - }; - ethernet@70000 { status = "okay"; phy = <&phy0>; phy-mode = "qsgmii"; + buffer-manager = <&bm>; + bm,pool-long = <0>; }; ethernet@74000 { status = "okay"; phy = <&phy1>; phy-mode = "qsgmii"; + buffer-manager = <&bm>; + bm,pool-long = <1>; }; ethernet@30000 { status = "okay"; phy = <&phy2>; phy-mode = "qsgmii"; + buffer-manager = <&bm>; + bm,pool-long = <2>; }; ethernet@34000 { status = "okay"; phy = <&phy3>; phy-mode = "qsgmii"; + buffer-manager = <&bm>; + bm,pool-long = <3>; }; /* Front-side USB slot */ @@ -226,27 +156,72 @@ status = "okay"; }; - spi0: spi@10600 { + bm@c0000 { status = "okay"; - u-boot,dm-pre-reloc; - - spi-flash@0 { - u-boot,dm-pre-reloc; - #address-cells = <1>; - #size-cells = <1>; - compatible = "n25q128a13", "jedec,spi-nor"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <108000000>; - }; }; nand@d0000 { status = "okay"; + label = "pxa3xx_nand-0"; num-cs = <1>; marvell,nand-keep-config; - marvell,nand-enable-arbiter; nand-on-flash-bbt; }; }; + + bm-bppi { + status = "okay"; + }; + }; +}; + +&pciec { + status = "okay"; + + /* + * The 3 slots are physically present as + * standard PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@9,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + pcie@a,0 { + /* Port 3, Lane 0 */ + status = "okay"; + }; +}; + +&mdio { + phy0: ethernet-phy@0 { + reg = <16>; + }; + + phy1: ethernet-phy@1 { + reg = <17>; + }; + + phy2: ethernet-phy@2 { + reg = <18>; + }; + + phy3: ethernet-phy@3 { + reg = <19>; + }; +}; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; }; }; diff --git a/arch/arm/dts/armada-xp-maxbcm.dts b/arch/arm/dts/armada-xp-maxbcm.dts index d7d7f65..921eb70 100644 --- a/arch/arm/dts/armada-xp-maxbcm.dts +++ b/arch/arm/dts/armada-xp-maxbcm.dts @@ -225,18 +225,6 @@ status = "okay"; }; - spi0: spi@10600 { - status = "okay"; - - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "n25q128a13", "jedec,spi-nor"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <108000000>; - }; - }; - nand@d0000 { status = "okay"; num-cs = <1>; @@ -247,3 +235,15 @@ }; }; }; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; +}; diff --git a/arch/arm/dts/armada-xp-mv78230.dtsi b/arch/arm/dts/armada-xp-mv78230.dtsi index f6bab9f..8558bf6 100644 --- a/arch/arm/dts/armada-xp-mv78230.dtsi +++ b/arch/arm/dts/armada-xp-mv78230.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Marvell Armada XP family SoC * @@ -5,44 +6,6 @@ * * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Contains definitions specific to the Armada XP MV78230 SoC that are not * common to all Armada XP SoCs. */ @@ -207,25 +170,33 @@ internal-regs { gpio0: gpio@18100 { - compatible = "marvell,orion-gpio"; - reg = <0x18100 0x40>; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; + reg = <0x18100 0x40>, <0x181c0 0x08>; + reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller; #gpio-cells = <2>; + #pwm-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = <82>, <83>, <84>, <85>; + clocks = <&coreclk 0>; }; gpio1: gpio@18140 { - compatible = "marvell,orion-gpio"; - reg = <0x18140 0x40>; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; + reg = <0x18140 0x40>, <0x181c8 0x08>; + reg-names = "gpio", "pwm"; ngpios = <17>; gpio-controller; #gpio-cells = <2>; + #pwm-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = <87>, <88>, <89>; + clocks = <&coreclk 0>; }; }; }; diff --git a/arch/arm/dts/armada-xp-mv78260.dtsi b/arch/arm/dts/armada-xp-mv78260.dtsi index d39231f..2d85fe8 100644 --- a/arch/arm/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/dts/armada-xp-mv78260.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Marvell Armada XP family SoC * @@ -5,44 +6,6 @@ * * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Contains definitions specific to the Armada XP MV78260 SoC that are not * common to all Armada XP SoCs. */ @@ -294,29 +257,38 @@ internal-regs { gpio0: gpio@18100 { - compatible = "marvell,orion-gpio"; - reg = <0x18100 0x40>; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; + reg = <0x18100 0x40>, <0x181c0 0x08>; + reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller; #gpio-cells = <2>; + #pwm-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = <82>, <83>, <84>, <85>; + clocks = <&coreclk 0>; }; gpio1: gpio@18140 { - compatible = "marvell,orion-gpio"; - reg = <0x18140 0x40>; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; + reg = <0x18140 0x40>, <0x181c8 0x08>; + reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller; #gpio-cells = <2>; + #pwm-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = <87>, <88>, <89>, <90>; + clocks = <&coreclk 0>; }; gpio2: gpio@18180 { - compatible = "marvell,orion-gpio"; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; reg = <0x18180 0x40>; ngpios = <3>; gpio-controller; diff --git a/arch/arm/dts/armada-xp-mv78460.dtsi b/arch/arm/dts/armada-xp-mv78460.dtsi index c642565..230a3fd 100644 --- a/arch/arm/dts/armada-xp-mv78460.dtsi +++ b/arch/arm/dts/armada-xp-mv78460.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Marvell Armada XP family SoC * @@ -5,44 +6,6 @@ * * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Contains definitions specific to the Armada XP MV78460 SoC that are not * common to all Armada XP SoCs. */ @@ -333,29 +296,38 @@ internal-regs { gpio0: gpio@18100 { - compatible = "marvell,orion-gpio"; - reg = <0x18100 0x40>; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; + reg = <0x18100 0x40>, <0x181c0 0x08>; + reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller; #gpio-cells = <2>; + #pwm-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = <82>, <83>, <84>, <85>; + clocks = <&coreclk 0>; }; gpio1: gpio@18140 { - compatible = "marvell,orion-gpio"; - reg = <0x18140 0x40>; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; + reg = <0x18140 0x40>, <0x181c8 0x08>; + reg-names = "gpio", "pwm"; ngpios = <32>; gpio-controller; #gpio-cells = <2>; + #pwm-cells = <2>; interrupt-controller; #interrupt-cells = <2>; interrupts = <87>, <88>, <89>, <90>; + clocks = <&coreclk 0>; }; gpio2: gpio@18180 { - compatible = "marvell,orion-gpio"; + compatible = "marvell,armada-370-gpio", + "marvell,orion-gpio"; reg = <0x18180 0x40>; ngpios = <3>; gpio-controller; diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts index 0a60ddf..861967c 100644 --- a/arch/arm/dts/armada-xp-synology-ds414.dts +++ b/arch/arm/dts/armada-xp-synology-ds414.dts @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree file for Synology DS414 * * Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.org> * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * * Note: this Device Tree assumes that the bootloader has remapped the * internal registers to 0xf1000000 (instead of the old 0xd0000000). * The 0xf1000000 is the default used by the recent, DT-capable, U-Boot @@ -42,36 +38,16 @@ spi0 = &spi0; }; - memory { + memory@0 { device_type = "memory"; reg = <0 0x00000000 0 0x40000000>; /* 1GB */ }; soc { ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 - MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>; - - pcie-controller { - status = "okay"; - - /* - * Connected to Marvell 88SX7042 SATA-II controller - * handling the four disks. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - - /* - * Connected to EtronTech EJ168A XHCI controller - * providing the two rear USB 3.0 ports. - */ - pcie@5,0 { - /* Port 1, Lane 0 */ - status = "okay"; - }; - }; + MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 + MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000 + MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>; internal-regs { @@ -80,64 +56,6 @@ status = "disabled"; }; - spi0: spi@10600 { - status = "okay"; - u-boot,dm-pre-reloc; - - spi-flash@0 { - u-boot,dm-pre-reloc; - #address-cells = <1>; - #size-cells = <1>; - compatible = "micron,n25q064"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <20000000>; - - /* - * Warning! - * - * Synology u-boot uses its compiled-in environment - * and it seems Synology did not care to change u-boot - * default configuration in order to allow saving a - * modified environment at a sensible location. So, - * if you do a 'saveenv' under u-boot, your modified - * environment will be saved at 1MB after the start - * of the flash, i.e. in the middle of the uImage. - * For that reason, it is strongly advised not to - * change the default environment, unless you know - * what you are doing. - */ - partition@00000000 { /* u-boot */ - label = "RedBoot"; - reg = <0x00000000 0x000d0000>; /* 832KB */ - }; - - partition@000c0000 { /* uImage */ - label = "zImage"; - reg = <0x000d0000 0x002d0000>; /* 2880KB */ - }; - - partition@003a0000 { /* uInitramfs */ - label = "rd.gz"; - reg = <0x003a0000 0x00430000>; /* 4250KB */ - }; - - partition@007d0000 { /* MAC address and serial number */ - label = "vendor"; - reg = <0x007d0000 0x00010000>; /* 64KB */ - }; - - partition@007e0000 { - label = "RedBoot config"; - reg = <0x007e0000 0x00010000>; /* 64KB */ - }; - - partition@007f0000 { - label = "FIS directory"; - reg = <0x007f0000 0x00010000>; /* 64KB */ - }; - }; - }; - i2c@11000 { clock-frequency = <400000>; status = "okay"; @@ -179,16 +97,6 @@ status = "okay"; }; - mdio { - phy0: ethernet-phy@0 { /* Marvell 88E1512 */ - reg = <0>; - }; - - phy1: ethernet-phy@1 { /* Marvell 88E1512 */ - reg = <1>; - }; - }; - ethernet@70000 { status = "okay"; pinctrl-0 = <&ge0_rgmii_pins>; @@ -215,7 +123,7 @@ &sata3_pwr_pin &sata4_pwr_pin>; pinctrl-names = "default"; - sata1_regulator: sata1-regulator { + sata1_regulator: sata1-regulator@1 { compatible = "regulator-fixed"; reg = <1>; regulator-name = "SATA1 Power"; @@ -228,7 +136,7 @@ gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>; }; - sata2_regulator: sata2-regulator { + sata2_regulator: sata2-regulator@2 { compatible = "regulator-fixed"; reg = <2>; regulator-name = "SATA2 Power"; @@ -241,7 +149,7 @@ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>; }; - sata3_regulator: sata3-regulator { + sata3_regulator: sata3-regulator@3 { compatible = "regulator-fixed"; reg = <3>; regulator-name = "SATA3 Power"; @@ -254,7 +162,7 @@ gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>; }; - sata4_regulator: sata4-regulator { + sata4_regulator: sata4-regulator@4 { compatible = "regulator-fixed"; reg = <4>; regulator-name = "SATA4 Power"; @@ -269,6 +177,39 @@ }; }; +&pciec { + status = "okay"; + + /* + * Connected to Marvell 88SX7042 SATA-II controller + * handling the four disks. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + /* + * Connected to EtronTech EJ168A XHCI controller + * providing the two rear USB 3.0 ports. + */ + pcie@5,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; +}; + + +&mdio { + phy0: ethernet-phy@0 { /* Marvell 88E1512 */ + reg = <0>; + }; + + phy1: ethernet-phy@1 { /* Marvell 88E1512 */ + reg = <1>; + }; +}; + &pinctrl { sata1_pwr_pin: sata1-pwr-pin { marvell,pins = "mpp42"; @@ -335,3 +276,59 @@ marvell,function = "gpio"; }; }; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "micron,n25q064", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <20000000>; + + /* + * Warning! + * + * Synology u-boot uses its compiled-in environment + * and it seems Synology did not care to change u-boot + * default configuration in order to allow saving a + * modified environment at a sensible location. So, + * if you do a 'saveenv' under u-boot, your modified + * environment will be saved at 1MB after the start + * of the flash, i.e. in the middle of the uImage. + * For that reason, it is strongly advised not to + * change the default environment, unless you know + * what you are doing. + */ + partition@0 { /* u-boot */ + label = "RedBoot"; + reg = <0x00000000 0x000d0000>; /* 832KB */ + }; + + partition@c0000 { /* uImage */ + label = "zImage"; + reg = <0x000d0000 0x002d0000>; /* 2880KB */ + }; + + partition@3a0000 { /* uInitramfs */ + label = "rd.gz"; + reg = <0x003a0000 0x00430000>; /* 4250KB */ + }; + + partition@7d0000 { /* MAC address and serial number */ + label = "vendor"; + reg = <0x007d0000 0x00010000>; /* 64KB */ + }; + + partition@7e0000 { + label = "RedBoot config"; + reg = <0x007e0000 0x00010000>; /* 64KB */ + }; + + partition@7f0000 { + label = "FIS directory"; + reg = <0x007f0000 0x00010000>; /* 64KB */ + }; + }; +}; diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts index b0f6c2b..5b18d62 100644 --- a/arch/arm/dts/armada-xp-theadorable.dts +++ b/arch/arm/dts/armada-xp-theadorable.dts @@ -126,40 +126,6 @@ status = "okay"; }; - spi0: spi@10600 { - status = "okay"; - u-boot,dm-pre-reloc; - - spi-flash@0 { - u-boot,dm-pre-reloc; - #address-cells = <1>; - #size-cells = <1>; - compatible = "n25q128a13", "jedec,spi-nor"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <27777777>; - }; - - fpga@1 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-generic-device"; - reg = <1>; /* Chip select 1 */ - spi-max-frequency = <27777777>; - }; - }; - - spi1: spi@10680 { - status = "okay"; - - fpga@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "spi-generic-device"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <27777777>; - }; - }; - /* The LCD controller is only used on this board */ lcd0: lcd-controller@e0000 { compatible = "marvell,armada-xp-lcd"; @@ -188,6 +154,41 @@ }; }; +&spi0 { + status = "okay"; + u-boot,dm-pre-reloc; + + spi-flash@0 { + u-boot,dm-pre-reloc; + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <27777777>; + }; + + fpga@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-generic-device"; + reg = <1>; /* Chip select 1 */ + spi-max-frequency = <27777777>; + }; +}; + +&spi1 { + status = "okay"; + + fpga@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-generic-device"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <27777777>; + }; +}; + + &pciec { status = "okay"; diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi index 3fac39e..d856d96 100644 --- a/arch/arm/dts/armada-xp.dtsi +++ b/arch/arm/dts/armada-xp.dtsi @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree Include file for Marvell Armada XP family SoC * @@ -8,44 +9,6 @@ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> * Ben Dooks <ben.dooks@codethink.co.uk> * - * This file is dual-licensed: you can use it either under the terms - * of the GPL or the X11 license, at your option. Note that this dual - * licensing only applies to this file, and not this project as a - * whole. - * - * a) This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Or, alternatively - * - * b) Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use - * copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Contains definitions specific to the Armada XP SoC that are not * common to all Armada SoCs. */ @@ -53,6 +16,9 @@ #include "armada-370-xp.dtsi" / { + #address-cells = <2>; + #size-cells = <2>; + model = "Marvell Armada XP family SoC"; compatible = "marvell,armadaxp", "marvell,armada-370-xp"; @@ -71,12 +37,12 @@ }; internal-regs { - sdramc@1400 { + sdramc: sdramc@1400 { compatible = "marvell,armada-xp-sdram-controller"; reg = <0x1400 0x500>; }; - L2: l2-cache { + L2: l2-cache@8000 { compatible = "marvell,aurora-system-cache"; reg = <0x08000 0x1000>; cache-id-part = <0x100>; @@ -85,29 +51,6 @@ wt-override; }; - spi0: spi@10600 { - compatible = "marvell,armada-xp-spi", - "marvell,orion-spi"; - pinctrl-0 = <&spi0_pins>; - pinctrl-names = "default"; - }; - - spi1: spi@10680 { - compatible = "marvell,armada-xp-spi", - "marvell,orion-spi"; - }; - - - i2c0: i2c@11000 { - compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; - reg = <0x11000 0x100>; - }; - - i2c1: i2c@11100 { - compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; - reg = <0x11100 0x100>; - }; - uart2: serial@12200 { compatible = "snps,dw-apb-uart"; pinctrl-0 = <&uart2_pins>; @@ -132,7 +75,7 @@ status = "disabled"; }; - system-controller@18200 { + systemc: system-controller@18200 { compatible = "marvell,armada-370-xp-system-controller"; reg = <0x18200 0x500>; }; @@ -150,7 +93,7 @@ #clock-cells = <1>; }; - thermal@182b0 { + thermal: thermal@182b0 { compatible = "marvell,armadaxp-thermal"; reg = <0x182b0 0x4 0x184d0 0x4>; @@ -164,25 +107,9 @@ clocks = <&coreclk 1>; }; - interrupt-controller@20a00 { - reg = <0x20a00 0x2d0>, <0x21070 0x58>; - }; - - timer@20300 { - compatible = "marvell,armada-xp-timer"; - clocks = <&coreclk 2>, <&refclk>; - clock-names = "nbclk", "fixed"; - }; - - watchdog@20300 { - compatible = "marvell,armada-xp-wdt"; - clocks = <&coreclk 2>, <&refclk>; - clock-names = "nbclk", "fixed"; - }; - - cpurst@20800 { - compatible = "marvell,armada-370-cpu-reset"; - reg = <0x20800 0x20>; + cpu-config@21000 { + compatible = "marvell,armada-xp-cpu-config"; + reg = <0x21000 0x8>; }; eth2: ethernet@30000 { @@ -193,15 +120,7 @@ status = "disabled"; }; - usb@50000 { - clocks = <&gateclk 18>; - }; - - usb@51000 { - clocks = <&gateclk 19>; - }; - - usb@52000 { + usb2: usb@52000 { compatible = "marvell,orion-ehci"; reg = <0x52000 0x500>; interrupts = <47>; @@ -209,7 +128,7 @@ status = "disabled"; }; - xor@60900 { + xor1: xor@60900 { compatible = "marvell,orion-xor"; reg = <0x60900 0x100 0x60b00 0x100>; @@ -237,7 +156,27 @@ compatible = "marvell,armada-xp-neta"; }; - xor@f0900 { + cesa: crypto@90000 { + compatible = "marvell,armada-xp-crypto"; + reg = <0x90000 0x10000>; + reg-names = "regs"; + interrupts = <48>, <49>; + clocks = <&gateclk 23>, <&gateclk 23>; + clock-names = "cesa0", "cesa1"; + marvell,crypto-srams = <&crypto_sram0>, + <&crypto_sram1>; + marvell,crypto-sram-size = <0x800>; + }; + + bm: bm@c0000 { + compatible = "marvell,armada-380-neta-bm"; + reg = <0xc0000 0xac>; + clocks = <&gateclk 13>; + internal-mem = <&bm_bppi>; + status = "disabled"; + }; + + xor0: xor@f0900 { compatible = "marvell,orion-xor"; reg = <0xF0900 0x100 0xF0B00 0x100>; @@ -257,6 +196,35 @@ }; }; }; + + crypto_sram0: sa-sram0 { + compatible = "mmio-sram"; + reg = <MBUS_ID(0x09, 0x09) 0 0x800>; + clocks = <&gateclk 23>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x09) 0 0x800>; + }; + + crypto_sram1: sa-sram1 { + compatible = "mmio-sram"; + reg = <MBUS_ID(0x09, 0x05) 0 0x800>; + clocks = <&gateclk 23>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>; + }; + + bm_bppi: bm-bppi { + compatible = "mmio-sram"; + reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>; + ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&gateclk 13>; + no-memory-wc; + status = "disabled"; + }; }; clocks { @@ -269,6 +237,44 @@ }; }; +&i2c0 { + compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11000 0x100>; +}; + +&i2c1 { + compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11100 0x100>; +}; + +&mpic { + reg = <0x20a00 0x2d0>, <0x21070 0x58>; +}; + +&timer { + compatible = "marvell,armada-xp-timer"; + clocks = <&coreclk 2>, <&refclk>; + clock-names = "nbclk", "fixed"; +}; + +&watchdog { + compatible = "marvell,armada-xp-wdt"; + clocks = <&coreclk 2>, <&refclk>; + clock-names = "nbclk", "fixed"; +}; + +&cpurst { + reg = <0x20800 0x20>; +}; + +&usb0 { + clocks = <&gateclk 18>; +}; + +&usb1 { + clocks = <&gateclk 19>; +}; + &pinctrl { ge0_gmii_pins: ge0-gmii-pins { marvell,pins = @@ -309,6 +315,12 @@ marvell,function = "spi0"; }; + spi1_pins: spi1-pins { + marvell,pins = "mpp13", "mpp14", + "mpp16", "mpp17"; + marvell,function = "spi1"; + }; + uart2_pins: uart2-pins { marvell,pins = "mpp42", "mpp43"; marvell,function = "uart2"; @@ -319,3 +331,15 @@ marvell,function = "uart3"; }; }; + +&spi0 { + compatible = "marvell,armada-xp-spi", "marvell,orion-spi"; + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; +}; + +&spi1 { + compatible = "marvell,armada-xp-spi", "marvell,orion-spi"; + pinctrl-0 = <&spi1_pins>; + pinctrl-names = "default"; +}; diff --git a/arch/arm/dts/bcm63158.dtsi b/arch/arm/dts/bcm63158.dtsi index 6a3fbc9..4f41f62 100644 --- a/arch/arm/dts/bcm63158.dtsi +++ b/arch/arm/dts/bcm63158.dtsi @@ -98,5 +98,85 @@ compatible = "wdt-reboot"; wdt = <&wdt1>; }; + + gpio0: gpio-controller@0xff800500 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800500 0x0 0x4>, + <0x0 0xff800520 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio1: gpio-controller@0xff800504 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800504 0x0 0x4>, + <0x0 0xff800524 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio2: gpio-controller@0xff800508 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800508 0x0 0x4>, + <0x0 0xff800528 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio3: gpio-controller@0xff80050c { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff80050c 0x0 0x4>, + <0x0 0xff80052c 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio4: gpio-controller@0xff800510 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800510 0x0 0x4>, + <0x0 0xff800530 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio5: gpio-controller@0xff800514 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800514 0x0 0x4>, + <0x0 0xff800534 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio6: gpio-controller@0xff800518 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800518 0x0 0x4>, + <0x0 0xff800538 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio7: gpio-controller@0xff80051c { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff80051c 0x0 0x4>, + <0x0 0xff80053c 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; }; }; diff --git a/arch/arm/dts/bcm6858.dtsi b/arch/arm/dts/bcm6858.dtsi index 23b80c6..5d5e64d 100644 --- a/arch/arm/dts/bcm6858.dtsi +++ b/arch/arm/dts/bcm6858.dtsi @@ -98,5 +98,85 @@ compatible = "wdt-reboot"; wdt = <&wdt1>; }; + + gpio0: gpio-controller@0xff800500 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800500 0x0 0x4>, + <0x0 0xff800520 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio1: gpio-controller@0xff800504 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800504 0x0 0x4>, + <0x0 0xff800524 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio2: gpio-controller@0xff800508 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800508 0x0 0x4>, + <0x0 0xff800528 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio3: gpio-controller@0xff80050c { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff80050c 0x0 0x4>, + <0x0 0xff80052c 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio4: gpio-controller@0xff800510 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800510 0x0 0x4>, + <0x0 0xff800530 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio5: gpio-controller@0xff800514 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800514 0x0 0x4>, + <0x0 0xff800534 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio6: gpio-controller@0xff800518 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff800518 0x0 0x4>, + <0x0 0xff800538 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio7: gpio-controller@0xff80051c { + compatible = "brcm,bcm6345-gpio"; + reg = <0x0 0xff80051c 0x0 0x4>, + <0x0 0xff80053c 0x0 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; }; }; diff --git a/arch/arm/dts/bcm963158.dts b/arch/arm/dts/bcm963158.dts index dc5afb5..b5c825b 100644 --- a/arch/arm/dts/bcm963158.dts +++ b/arch/arm/dts/bcm963158.dts @@ -29,3 +29,35 @@ u-boot,dm-pre-reloc; status = "okay"; }; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&gpio5 { + status = "okay"; +}; + +&gpio6 { + status = "okay"; +}; + +&gpio7 { + status = "okay"; +}; diff --git a/arch/arm/dts/bcm968580xref.dts b/arch/arm/dts/bcm968580xref.dts index 0c59f94..15febb0 100644 --- a/arch/arm/dts/bcm968580xref.dts +++ b/arch/arm/dts/bcm968580xref.dts @@ -29,3 +29,35 @@ u-boot,dm-pre-reloc; status = "okay"; }; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&gpio5 { + status = "okay"; +}; + +&gpio6 { + status = "okay"; +}; + +&gpio7 { + status = "okay"; +}; diff --git a/arch/arm/dts/da850-evm-u-boot.dtsi b/arch/arm/dts/da850-evm-u-boot.dtsi index 360e79e..1683f34 100644 --- a/arch/arm/dts/da850-evm-u-boot.dtsi +++ b/arch/arm/dts/da850-evm-u-boot.dtsi @@ -6,6 +6,24 @@ * Copyright (C) Adam Ford */ +/ { + soc@1c00000 { + u-boot,dm-spl; + }; +}; + &flash { compatible = "m25p64", "jedec,spi-nor"; }; + +&mmc0 { + u-boot,dm-spl; +}; + +&serial2 { + u-boot,dm-spl; +}; + +&spi1 { + u-boot,dm-spl; +}; diff --git a/arch/arm/dts/dra7.dtsi b/arch/arm/dts/dra7.dtsi index 0f982d8..fd1aea0 100644 --- a/arch/arm/dts/dra7.dtsi +++ b/arch/arm/dts/dra7.dtsi @@ -170,7 +170,7 @@ pbias_mmc_reg: pbias_mmc_omap5 { regulator-name = "pbias_mmc_omap5"; regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; }; }; diff --git a/arch/arm/dts/dra71-evm.dts b/arch/arm/dts/dra71-evm.dts index 41c9132..64363f7 100644 --- a/arch/arm/dts/dra71-evm.dts +++ b/arch/arm/dts/dra71-evm.dts @@ -24,13 +24,13 @@ regulator-name = "vddshv8"; regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; + regulator-max-microvolt = <3300000>; regulator-boot-on; vin-supply = <&evm_5v0>; gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>; states = <1800000 0x0 - 3000000 0x1>; + 3300000 0x1>; }; evm_1v8_sw: fixedregulator-evm_1v8 { diff --git a/arch/arm/dts/imx53-kp-u-boot.dtsi b/arch/arm/dts/imx53-kp-u-boot.dtsi new file mode 100644 index 0000000..acab9b3 --- /dev/null +++ b/arch/arm/dts/imx53-kp-u-boot.dtsi @@ -0,0 +1,10 @@ +/* + * Copyright 2019 + * Lukasz Majewski, DENX Software Engineering, lukma@denx.de + * + * SPDX-License-Identifier: GPL-2.0+ or X11 + */ + +&pmic { + u-boot,i2c-transaction-bytes = <3>; +}; diff --git a/arch/arm/dts/k3-am65-wakeup.dtsi b/arch/arm/dts/k3-am65-wakeup.dtsi index 8d7b47f..1f591ef 100644 --- a/arch/arm/dts/k3-am65-wakeup.dtsi +++ b/arch/arm/dts/k3-am65-wakeup.dtsi @@ -7,7 +7,7 @@ &cbass_wakeup { dmsc: dmsc { - compatible = "ti,k2g-sci"; + compatible = "ti,am654-sci"; ti,host-id = <12>; #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi index 143eb6d..c5d23d0 100644 --- a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -4,6 +4,7 @@ */ #include <dt-bindings/pinctrl/k3-am65.h> +#include <dt-bindings/dma/k3-udma.h> / { chosen { @@ -63,6 +64,52 @@ pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xffffffff>; }; + + navss_mcu: navss-mcu { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + ti,sci-dev-id = <119>; + + mcu_ringacc: ringacc@2b800000 { + compatible = "ti,am654-navss-ringacc"; + reg = <0x0 0x2b800000 0x0 0x400000>, + <0x0 0x2b000000 0x0 0x400000>, + <0x0 0x28590000 0x0 0x100>, + <0x0 0x2a500000 0x0 0x40000>; + reg-names = "rt", "fifos", + "proxy_gcfg", "proxy_target"; + ti,num-rings = <286>; + ti,sci-rm-range-gp-rings = <0x2>; /* GP ring range */ + ti,dma-ring-reset-quirk; + ti,sci = <&dmsc>; + ti,sci-dev-id = <195>; + }; + + mcu_udmap: udmap@285c0000 { + compatible = "ti,k3-navss-udmap"; + reg = <0x0 0x285c0000 0x0 0x100>, + <0x0 0x2a800000 0x0 0x40000>, + <0x0 0x2aa00000 0x0 0x40000>; + reg-names = "gcfg", "rchanrt", "tchanrt"; + #dma-cells = <3>; + + ti,ringacc = <&mcu_ringacc>; + ti,psil-base = <0x6000>; + + ti,sci = <&dmsc>; + ti,sci-dev-id = <194>; + + ti,sci-rm-range-tchan = <0x1>, /* TX_HCHAN */ + <0x2>; /* TX_CHAN */ + ti,sci-rm-range-rchan = <0x3>, /* RX_HCHAN */ + <0x4>; /* RX_CHAN */ + ti,sci-rm-range-rflow = <0x5>; /* GP RFLOW */ + dma-coherent; + }; + }; }; &cbass_wakeup { diff --git a/arch/arm/dts/keystone-k2g-evm.dts b/arch/arm/dts/keystone-k2g-evm.dts index d91869f..7c5deef 100644 --- a/arch/arm/dts/keystone-k2g-evm.dts +++ b/arch/arm/dts/keystone-k2g-evm.dts @@ -29,7 +29,6 @@ status = "okay"; ethphy0: ethernet-phy@0 { reg = <0>; - phy-mode = "rgmii-id"; }; }; diff --git a/arch/arm/dts/keystone-k2g-ice.dts b/arch/arm/dts/keystone-k2g-ice.dts index 680dfee..ecca2df 100644 --- a/arch/arm/dts/keystone-k2g-ice.dts +++ b/arch/arm/dts/keystone-k2g-ice.dts @@ -7,6 +7,7 @@ /dts-v1/; #include "keystone-k2g.dtsi" +#include <dt-bindings/net/ti-dp83867.h> / { compatible = "ti,k2g-ice", "ti,k2g", "ti,keystone"; @@ -81,3 +82,37 @@ }; }; }; + +&qmss { + status = "okay"; +}; + +&knav_dmas { + status = "okay"; +}; + +&netcp { + pinctrl-names = "default"; + //pinctrl-0 = <&emac_pins>; + status = "okay"; +}; + +&mdio { + pinctrl-names = "default"; + //pinctrl-0 = <&mdio_pins>; + status = "okay"; + ethphy0: ethernet-phy@0 { + reg = <0>; + ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>; + ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>; + ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>; + ti,min-output-impedance; + ti,dp83867-rxctrl-strap-quirk; + }; +}; + +&gbe0 { + phy-handle = <ðphy0>; + phy-mode = "rgmii-id"; + status = "okay"; +}; diff --git a/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi new file mode 100644 index 0000000..7d9b95c --- /dev/null +++ b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * STM32MP157C DK1/DK2 BOARD configuration + * 1x DDR3L 4Gb, 16-bit, 533MHz. + * Reference used NT5CC256M16DP-DI from NANYA + * + * DDR type / Platform DDR3/3L + * freq 533MHz + * width 16 + * datasheet 0 = MT41J256M16-187 / DDR3-1066 bin G + * DDR density 4 + * timing mode optimized + * Scheduling/QoS options : type = 2 + * address mapping : RBC + * Tc > + 85C : N + */ +#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.43" +#define DDR_MEM_SPEED 533 +#define DDR_MEM_SIZE 0x20000000 + +#define DDR_MSTR 0x00041401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041C +#define DDR_DRAMTMG2 0x0608090F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x08040608 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02060105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ADDRMAP1 0x00070707 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x1F000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x06060606 +#define DDR_ADDRMAP6 0x0F060606 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000C01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x01000001 +#define DDR_PERFLPR1 0x08000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00010000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x02100C03 +#define DDR_PCFGQOS1_0 0x00800100 +#define DDR_PCFGWQOS0_0 0x01100C03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PCFGR_1 0x00010000 +#define DDR_PCFGW_1 0x00000000 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 +#define DDR_PCFGWQOS1_1 0x01000200 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200001F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x38D488D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000840 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX0DLLCR 0x40000000 +#define DDR_DX0DQTR 0xFFFFFFFF +#define DDR_DX0DQSTR 0x3DB02000 +#define DDR_DX1GCR 0x0000CE81 +#define DDR_DX1DLLCR 0x40000000 +#define DDR_DX1DQTR 0xFFFFFFFF +#define DDR_DX1DQSTR 0x3DB02000 +#define DDR_DX2GCR 0x0000CE81 +#define DDR_DX2DLLCR 0x40000000 +#define DDR_DX2DQTR 0xFFFFFFFF +#define DDR_DX2DQSTR 0x3DB02000 +#define DDR_DX3GCR 0x0000CE81 +#define DDR_DX3DLLCR 0x40000000 +#define DDR_DX3DQTR 0xFFFFFFFF +#define DDR_DX3DQSTR 0x3DB02000 + +#include "stm32mp15-ddr.dtsi" diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi index 85da592..c069875 100644 --- a/arch/arm/dts/stm32mp157-pinctrl.dtsi +++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi @@ -148,6 +148,13 @@ gpio-ranges = <&pinctrl 0 160 8>; }; + adc12_usb_pwr_pins_a: adc12-usb-pwr-pins-0 { + pins { + pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* ADC12 in18 */ + <STM32_PINMUX('A', 5, ANALOG)>; /* ADC12 in19 */ + }; + }; + cec_pins_a: cec-0 { pins { pinmux = <STM32_PINMUX('A', 15, AF4)>; @@ -157,6 +164,52 @@ }; }; + ethernet0_rgmii_pins_a: rgmii-0 { + pins1 { + pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */ + <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */ + <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */ + <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */ + <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */ + <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */ + <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */ + <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */ + <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins2 { + pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */ + <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */ + <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */ + <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */ + <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */ + <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + + ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 { + pins1 { + pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */ + <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */ + <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */ + <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */ + <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */ + <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */ + <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */ + <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */ + <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */ + <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */ + <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */ + <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */ + <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */ + <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */ + <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */ + }; + }; + i2c1_pins_a: i2c1-0 { pins { pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */ @@ -187,6 +240,19 @@ }; }; + m_can1_pins_a: m-can1-0 { + pins1 { + pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = <STM32_PINMUX('I', 9, AF9)>; /* CAN1_RX */ + bias-disable; + }; + }; + pwm2_pins_a: pwm2-0 { pins { pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */ @@ -360,6 +426,21 @@ slew-rate = <0>; }; }; + + spi1_pins_a: spi1-0 { + pins1 { + pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */ + <STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + + pins2 { + pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */ + bias-disable; + }; + }; }; }; }; diff --git a/arch/arm/dts/stm32mp157-u-boot.dtsi b/arch/arm/dts/stm32mp157-u-boot.dtsi index 90d13f3..ab6f673 100644 --- a/arch/arm/dts/stm32mp157-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157-u-boot.dtsi @@ -17,6 +17,8 @@ gpio9 = &gpioj; gpio10 = &gpiok; gpio25 = &gpioz; + pinctrl0 = &pinctrl; + pinctrl1 = &pinctrl_z; }; config { @@ -39,6 +41,10 @@ }; }; +&bsec { + u-boot,dm-pre-reloc; +}; + &clk_hsi { u-boot,dm-pre-reloc; }; diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi new file mode 100644 index 0000000..af7acfa --- /dev/null +++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright : STMicroelectronics 2018 + */ + +#include <dt-bindings/clock/stm32mp1-clksrc.h> +#include "stm32mp157-u-boot.dtsi" +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + +/ { + aliases { + i2c3 = &i2c4; + mmc0 = &sdmmc1; + }; + config { + u-boot,boot-led = "heartbeat"; + u-boot,error-led = "error"; + st,adc_usb_pd = <&adc1 18>, <&adc1 19>; + }; + led { + red { + label = "error"; + gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; + default-state = "off"; + status = "okay"; + }; + + blue { + default-state = "on"; + }; + }; +}; + +&adc { + pinctrl-names = "default"; + pinctrl-0 = <&adc12_usb_pwr_pins_a>; + vdd-supply = <&vdd>; + vdda-supply = <&vdd>; + vref-supply = <&vrefbuf>; + status = "okay"; + adc1: adc@0 { + /* + * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. + * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: + * 5 * (56 + 47kOhms) * 5pF => 2.5us. + * Use arbitrary margin here (e.g. 5µs). + */ + st,min-sample-time-nsecs = <5000>; + /* ANA0, ANA1, USB Type-C CC1 & CC2 */ + st,adc-channels = <0 1 18 19>; + status = "okay"; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&i2c4 { + u-boot,dm-pre-reloc; +}; + +&i2c4_pins_a { + u-boot,dm-pre-reloc; + pins { + u-boot,dm-pre-reloc; + }; +}; + +&pmic { + u-boot,dm-pre-reloc; +}; + +&rcc { + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_DISABLED + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4Q + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + cfg = < 2 80 0 0 0 PQR(1,0,0) >; + frac = < 0x800 >; + u-boot,dm-pre-reloc; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + cfg = < 2 65 1 0 0 PQR(1,1,1) >; + frac = < 0x1400 >; + u-boot,dm-pre-reloc; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + cfg = < 1 33 1 16 36 PQR(1,1,1) >; + frac = < 0x1a04 >; + u-boot,dm-pre-reloc; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + cfg = < 3 98 5 7 7 PQR(1,1,1) >; + u-boot,dm-pre-reloc; + }; +}; + +&sdmmc1 { + u-boot,dm-spl; +}; + +&sdmmc1_b4_pins_a { + u-boot,dm-spl; + pins { + u-boot,dm-spl; + }; +}; + +&uart4 { + u-boot,dm-pre-reloc; +}; + +&uart4_pins_a { + u-boot,dm-pre-reloc; + pins1 { + u-boot,dm-pre-reloc; + }; + pins2 { + u-boot,dm-pre-reloc; + }; +}; + +&usbotg_hs { + usb1600; + hnp-srp-disable; +}; + +&v3v3 { + regulator-always-on; +}; diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts new file mode 100644 index 0000000..0882765 --- /dev/null +++ b/arch/arm/dts/stm32mp157a-dk1.dts @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157c.dtsi" +#include "stm32mp157-pinctrl.dtsi" +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/mfd/st,stpmic1.h> + +/ { + model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { + ethernet0 = ðernet0; + serial0 = &uart4; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + reg = <0xc0000000 0x20000000>; + }; + + led { + compatible = "gpio-leds"; + blue { + label = "heartbeat"; + gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + }; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rgmii_pins_a>; + pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii"; + max-speed = <1000>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /delete-property/dmas; + /delete-property/dma-names; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + st,main-control-register = <0x04>; + st,vin-control-register = <0xc0>; + st,usb-control-register = <0x20>; + + regulators { + compatible = "st,stpmic1-regulators"; + + ldo1-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + interrupts = <IT_CURLIM_LDO1 0>; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + interrupts = <IT_CURLIM_LDO2 0>; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + interrupts = <IT_CURLIM_LDO4 0>; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = <IT_CURLIM_LDO5 0>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + interrupts = <IT_CURLIM_LDO6 0>; + + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = <IT_OCP_BOOST 0>; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = <IT_OCP_OTG 0>; + regulator-active-discharge; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = <IT_OCP_SWOUT 0>; + regulator-active-discharge; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>; + interrupt-names = "onkey-falling", "onkey-rising"; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&pwr { + pwr-supply = <&vdd>; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + broken-cd; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + phy-names = "usb"; + status = "okay"; +}; + +&usbphyc { + vdd3v3-supply = <&vdd_usb>; + status = "okay"; +}; + +&vrefbuf { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + vdda-supply = <&vdd>; + status = "okay"; +}; diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi new file mode 100644 index 0000000..06ef3a4 --- /dev/null +++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright : STMicroelectronics 2018 + */ + +#include "stm32mp157a-dk1-u-boot.dtsi" diff --git a/arch/arm/dts/stm32mp157c-dk2.dts b/arch/arm/dts/stm32mp157c-dk2.dts new file mode 100644 index 0000000..9a81d2d --- /dev/null +++ b/arch/arm/dts/stm32mp157c-dk2.dts @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157a-dk1.dts" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; +}; + +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + phy-dsi-supply = <®18>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <<dc_ep1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + + panel@0 { + compatible = "orisetech,otm8009a"; + reg = <0>; + reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; + status = "okay"; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; +}; + +<dc { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + ltdc_ep1_out: endpoint@1 { + reg = <1>; + remote-endpoint = <&dsi_in>; + }; + }; +}; diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi index 70bbf66..55f9903 100644 --- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi @@ -9,9 +9,14 @@ / { aliases { + i2c3 = &i2c4; mmc0 = &sdmmc1; mmc1 = &sdmmc2; - i2c3 = &i2c4; + }; + + config { + st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>; + st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>; }; led { @@ -43,14 +48,8 @@ st,digbypass; }; -&uart4_pins_a { +&i2c4 { u-boot,dm-pre-reloc; - pins1 { - u-boot,dm-pre-reloc; - }; - pins2 { - u-boot,dm-pre-reloc; - }; }; &i2c4_pins_a { @@ -60,14 +59,6 @@ }; }; -&uart4 { - u-boot,dm-pre-reloc; -}; - -&i2c4 { - u-boot,dm-pre-reloc; -}; - &pmic { u-boot,dm-pre-reloc; }; @@ -165,8 +156,6 @@ }; }; -/* SPL part **************************************/ -/* MMC1 boot */ &sdmmc1_b4_pins_a { u-boot,dm-spl; pins { @@ -185,7 +174,6 @@ u-boot,dm-spl; }; -/* MMC2 boot */ &sdmmc2_b4_pins_a { u-boot,dm-spl; pins { @@ -203,3 +191,17 @@ &sdmmc2 { u-boot,dm-spl; }; + +&uart4 { + u-boot,dm-pre-reloc; +}; + +&uart4_pins_a { + u-boot,dm-pre-reloc; + pins1 { + u-boot,dm-pre-reloc; + }; + pins2 { + u-boot,dm-pre-reloc; + }; +}; diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts index 7a9b742..2664c9c 100644 --- a/arch/arm/dts/stm32mp157c-ed1.dts +++ b/arch/arm/dts/stm32mp157c-ed1.dts @@ -8,20 +8,24 @@ #include "stm32mp157c.dtsi" #include "stm32mp157-pinctrl.dtsi" #include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/mfd/st,stpmu1.h> +#include <dt-bindings/mfd/st,stpmic1.h> / { model = "STMicroelectronics STM32MP157C eval daughter"; compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; chosen { - stdout-path = "serial3:115200n8"; + stdout-path = "serial0:115200n8"; }; memory@c0000000 { reg = <0xC0000000 0x40000000>; }; + aliases { + serial0 = &uart4; + }; + sd_switch: regulator-sd_switch { compatible = "regulator-gpio"; regulator-name = "sd_switch"; @@ -36,15 +40,8 @@ }; }; -&rng1 { - status = "okay"; -}; - -&timers6 { +&hwspinlock { status = "okay"; - timer@5 { - status = "okay"; - }; }; &i2c4 { @@ -54,8 +51,8 @@ i2c-scl-falling-time-ns = <20>; status = "okay"; - pmic: stpmu1@33 { - compatible = "st,stpmu1"; + pmic: stpmic1@33 { + compatible = "st,stpmic1"; reg = <0x33>; interrupts = <0 2>; interrupt-parent = <&gpioa>; @@ -68,7 +65,7 @@ st,usb_control_register = <0x30>; regulators { - compatible = "st,stpmu1-regulators"; + compatible = "st,stpmic1-regulators"; ldo1-supply = <&v3v3>; ldo2-supply = <&v3v3>; @@ -321,10 +318,27 @@ }; }; +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&pinctrl { + hwlocks = <&hwspinlock 0>; +}; + &pwr { pwr-supply = <&vdd>; }; +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + &sdmmc1 { pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; broken-cd; @@ -355,6 +369,13 @@ status = "okay"; }; +&timers6 { + status = "okay"; + timer@5 { + status = "okay"; + }; +}; + &uart4 { pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_a>; @@ -365,14 +386,6 @@ usb33d-supply = <&usb33>; }; -&hwspinlock { - status = "okay"; -}; - -&pinctrl { - hwlocks = <&hwspinlock 0>; -}; - &usbphyc_port0 { phy-supply = <&vdd_usb>; vdda1v1-supply = <®11>; diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi index 409f983..8b92b1f 100644 --- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi +++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi @@ -7,29 +7,23 @@ / { aliases { - spi0 = &qspi; + gpio26 = &stmfx_pinctrl; i2c1 = &i2c2; i2c4 = &i2c5; + pinctrl2 = &stmfx_pinctrl; + spi0 = &qspi; }; }; &flash0 { compatible = "jedec,spi-nor"; + u-boot,dm-spl; }; &flash1 { compatible = "jedec,spi-nor"; }; -&v3v3 { - regulator-always-on; -}; - -&usbotg_hs { - g-tx-fifo-size = <576>; -}; - -/* SPL part **************************************/ &qspi { u-boot,dm-spl; }; @@ -61,7 +55,10 @@ }; }; -&flash0 { - u-boot,dm-spl; +&usbotg_hs { + g-tx-fifo-size = <576>; }; +&v3v3 { + regulator-always-on; +}; diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts index 902a42b..a6ee379 100644 --- a/arch/arm/dts/stm32mp157c-ev1.dts +++ b/arch/arm/dts/stm32mp157c-ev1.dts @@ -11,6 +11,21 @@ model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = &uart4; + ethernet0 = ðernet0; + }; + + panel_backlight: panel-backlight { + compatible = "gpio-backlight"; + gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; + default-on; + status = "okay"; + }; }; &cec { @@ -19,12 +34,88 @@ status = "okay"; }; +&dsi { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <<dc_ep0_out>; + }; + }; + + port@1 { + reg = <1>; + dsi_out: endpoint { + remote-endpoint = <&dsi_panel_in>; + }; + }; + }; + + panel-dsi@0 { + compatible = "raydium,rm68200"; + reg = <0>; + reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; + backlight = <&panel_backlight>; + status = "okay"; + + port { + dsi_panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rgmii_pins_a>; + pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii"; + max-speed = <1000>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + &i2c2 { pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; + + stmfx: stmfx@42 { + compatible = "st,stmfx-0300"; + reg = <0x42>; + interrupts = <8 IRQ_TYPE_EDGE_RISING>; + interrupt-parent = <&gpioi>; + vdd-supply = <&v3v3>; + + stmfx_pinctrl: stmfx-pin-controller { + compatible = "st,stmfx-0300-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&stmfx_pinctrl 0 0 24>; + status = "disabled"; + }; + }; }; &i2c5 { @@ -35,6 +126,26 @@ status = "okay"; }; +<dc { + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + ltdc_ep0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&dsi_in>; + }; + }; +}; + +&m_can1 { + pinctrl-names = "default"; + pinctrl-0 = <&m_can1_pins_a>; + status = "okay"; +}; + &qspi { pinctrl-names = "default"; pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; @@ -60,6 +171,12 @@ }; }; +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins_a>; + status = "disabled"; +}; + &timers2 { status = "disabled"; pwm { @@ -106,6 +223,7 @@ &usbotg_hs { pinctrl-names = "default"; pinctrl-0 = <&usbotg_hs_pins_a>; + dr_mode = "peripheral"; phys = <&usbphyc_port1 0>; phy-names = "usb2-phy"; status = "okay"; diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index 37cadfa..7eb4bee 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -29,7 +29,7 @@ }; psci { - compatible = "arm,psci"; + compatible = "arm,psci-1.0"; method = "smc"; cpu_off = <0x84000002>; cpu_on = <0x84000003>; @@ -106,26 +106,6 @@ }; }; - pm_domain { - #address-cells = <1>; - #size-cells = <0>; - compatible = "st,stm32mp157c-pd"; - - pd_core_ret: core-ret-power-domain@1 { - #address-cells = <1>; - #size-cells = <0>; - reg = <1>; - #power-domain-cells = <0>; - label = "CORE-RETENTION"; - - pd_core: core-power-domain@2 { - reg = <2>; - #power-domain-cells = <0>; - label = "CORE"; - }; - }; - }; - soc { compatible = "simple-bus"; #address-cells = <1>; @@ -339,6 +319,34 @@ }; }; + spi2: spi@4000b000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x4000b000 0x400>; + interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI2_K>; + resets = <&rcc SPI2_R>; + dmas = <&dmamux1 39 0x400 0x05>, + <&dmamux1 40 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + spi3: spi@4000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x4000c000 0x400>; + interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI3_K>; + resets = <&rcc SPI3_R>; + dmas = <&dmamux1 61 0x400 0x05>, + <&dmamux1 62 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + usart2: serial@4000e000 { compatible = "st,stm32h7-uart"; reg = <0x4000e000 0x400>; @@ -522,6 +530,34 @@ status = "disabled"; }; + spi1: spi@44004000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x44004000 0x400>; + interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI1_K>; + resets = <&rcc SPI1_R>; + dmas = <&dmamux1 37 0x400 0x05>, + <&dmamux1 38 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + spi4: spi@44005000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x44005000 0x400>; + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI4_K>; + resets = <&rcc SPI4_R>; + dmas = <&dmamux1 83 0x400 0x05>, + <&dmamux1 84 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + timers15: timer@44006000 { #address-cells = <1>; #size-cells = <0>; @@ -584,6 +620,116 @@ }; }; + spi5: spi@44009000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x44009000 0x400>; + interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI5_K>; + resets = <&rcc SPI5_R>; + dmas = <&dmamux1 85 0x400 0x05>, + <&dmamux1 86 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + dfsdm: dfsdm@4400d000 { + compatible = "st,stm32mp1-dfsdm"; + reg = <0x4400d000 0x800>; + clocks = <&rcc DFSDM_K>; + clock-names = "dfsdm"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + dfsdm0: filter@0 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <0>; + interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&dmamux1 101 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm1: filter@1 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <1>; + interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&dmamux1 102 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm2: filter@2 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <2>; + interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&dmamux1 103 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm3: filter@3 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <3>; + interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&dmamux1 104 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm4: filter@4 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <4>; + interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&dmamux1 91 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm5: filter@5 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <5>; + interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&dmamux1 92 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + }; + + m_can1: can@4400e000 { + compatible = "bosch,m_can"; + reg = <0x4400e000 0x400>, <0x44011000 0x2800>; + reg-names = "m_can", "message_ram"; + interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "int0", "int1"; + clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; + status = "disabled"; + }; + + m_can2: can@4400f000 { + compatible = "bosch,m_can"; + reg = <0x4400f000 0x400>, <0x44011000 0x2800>; + reg-names = "m_can", "message_ram"; + interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "int0", "int1"; + clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; + status = "disabled"; + }; + dma1: dma@48000000 { compatible = "st,stm32-dma"; reg = <0x48000000 0x400>; @@ -647,6 +793,8 @@ reg = <0x0>; interrupt-parent = <&adc>; interrupts = <0>; + dmas = <&dmamux1 9 0x400 0x01>; + dma-names = "rx"; status = "disabled"; }; @@ -656,6 +804,8 @@ reg = <0x100>; interrupt-parent = <&adc>; interrupts = <1>; + dmas = <&dmamux1 10 0x400 0x01>; + dma-names = "rx"; status = "disabled"; }; }; @@ -675,7 +825,7 @@ }; usbotg_hs: usb-otg@49000000 { - compatible = "st,stm32mp1-hsotg", "snps,dwc2"; + compatible = "snps,dwc2"; reg = <0x49000000 0x10000>; clocks = <&rcc USBO_K>; clock-names = "otg"; @@ -686,7 +836,6 @@ g-np-tx-fifo-size = <32>; g-tx-fifo-size = <128 128 64 64 64 64 32 32>; dr_mode = "otg"; - power-domains = <&pd_core>; status = "disabled"; }; @@ -753,8 +902,8 @@ reg = <0x5000d000 0x400>; }; - syscfg: system-config@50020000 { - compatible = "st,stm32-syscfg", "syscon"; + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; reg = <0x50020000 0x400>; }; @@ -853,6 +1002,18 @@ status = "disabled"; }; + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0>; + dma-names = "in"; + dma-maxburst = <2>; + status = "disabled"; + }; + rng1: rng@54003000 { compatible = "st,stm32-rng"; reg = <0x54003000 0x400>; @@ -871,7 +1032,7 @@ dma-requests = <48>; }; - qspi: qspi@58003000 { + qspi: spi@58003000 { compatible = "st,stm32f469-qspi"; reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; reg-names = "qspi", "qspi_mm"; @@ -915,6 +1076,36 @@ status = "disabled"; }; + stmmac_axi_config_0: stmmac-axi-config { + snps,wr_osr_lmt = <0x7>; + snps,rd_osr_lmt = <0x7>; + snps,blen = <0 0 0 0 16 8 4>; + }; + + ethernet0: ethernet@5800a000 { + compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; + reg = <0x5800a000 0x2000>; + reg-names = "stmmaceth"; + interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + clock-names = "stmmaceth", + "mac-clk-tx", + "mac-clk-rx", + "ethstp", + "syscfg-clk"; + clocks = <&rcc ETHMAC>, + <&rcc ETHTX>, + <&rcc ETHRX>, + <&rcc ETHSTP>, + <&rcc SYSCFG>; + st,syscon = <&syscfg 0x4>; + snps,mixed-burst; + snps,pbl = <2>; + snps,axi-config = <&stmmac_axi_config_0>; + snps,tso; + status = "disabled"; + }; + usbh_ohci: usbh-ohci@5800c000 { compatible = "generic-ohci"; reg = <0x5800c000 0x1000>; @@ -955,6 +1146,14 @@ status = "disabled"; }; + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + usbphyc: usbphyc@5a006000 { #address-cells = <1>; #size-cells = <0>; @@ -983,6 +1182,20 @@ status = "disabled"; }; + spi6: spi@5c001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x5c001000 0x400>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc SPI6_K>; + resets = <&rcc SPI6_R>; + dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>, + <&mdma1 35 0x0 0x40002 0x0 0x0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + i2c4: i2c@5c002000 { compatible = "st,stm32f7-i2c"; reg = <0x5c002000 0x400>; @@ -996,6 +1209,22 @@ status = "disabled"; }; + rtc: rtc@5c004000 { + compatible = "st,stm32mp1-rtc"; + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + bsec: nvmem@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + }; + i2c6: i2c@5c009000 { compatible = "st,stm32f7-i2c"; reg = <0x5c009000 0x400>; diff --git a/arch/arm/dts/sun50i-a64-oceanic-5205-5inmfd.dts b/arch/arm/dts/sun50i-a64-oceanic-5205-5inmfd.dts new file mode 100644 index 0000000..6a21545 --- /dev/null +++ b/arch/arm/dts/sun50i-a64-oceanic-5205-5inmfd.dts @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2019 Oceanic Systems (UK) Ltd. + * Copyright (C) 2019 Amarula Solutions B.V. + * Author: Jagan Teki <jagan@amarulasolutions.com> + */ + +/dts-v1/; + +#include "sun50i-a64-sopine.dtsi" + +/ { + model = "Oceanic 5205 5inMFD"; + compatible = "oceanic,5205-5inmfd", "allwinner,sun50i-a64"; + + aliases { + ethernet0 = &emac; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&ehci0 { + status = "okay"; +}; + +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_dc1sw>; + allwinner,tx-delay-ps = <600>; + status = "okay"; +}; + +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + +&ohci0 { + status = "okay"; +}; + +®_dc1sw { + regulator-name = "vcc-phy"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "host"; + status = "okay"; +}; + +&usbphy { + status = "okay"; +}; diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h index d8ddecc0..15a5b64 100644 --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h @@ -84,6 +84,22 @@ #define MT41K128MJT187E_PHY_FIFO_WE 0x100 #define MT41K128MJT187E_IOCTRL_VALUE 0x18B +/* Micron MT41K128M16JT-125 IT:K (256 MB) at 400MHz */ +#define MT41K128M16JT125K_EMIF_READ_LATENCY 0x07 +#define MT41K128M16JT125K_EMIF_TIM1 0x0AAAD4DB +#define MT41K128M16JT125K_EMIF_TIM2 0x2A437FDA +#define MT41K128M16JT125K_EMIF_TIM3 0x501F83FF +#define MT41K128M16JT125K_EMIF_SDCFG 0x61A052B2 +#define MT41K128M16JT125K_EMIF_SDREF 0x00000C30 +#define MT41K128M16JT125K_ZQ_CFG 0x50074BE4 +#define MT41K128M16JT125K_RATIO 0x80 +#define MT41K128M16JT125K_INVERT_CLKOUT 0x0 +#define MT41K128M16JT125K_RD_DQS 0x38 +#define MT41K128M16JT125K_WR_DQS 0x46 +#define MT41K128M16JT125K_PHY_WR_DATA 0x7D +#define MT41K128M16JT125K_PHY_FIFO_WE 0x9B +#define MT41K128M16JT125K_IOCTRL_VALUE 0x18B + /* Micron MT41J64M16JT-125 */ #define MT41J64MJT125_EMIF_SDCFG 0x61C04A32 diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index 4baba38..8c916e8 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -28,6 +28,8 @@ #define SUNXI_BOOTED_FROM_NAND 1 #define SUNXI_BOOTED_FROM_MMC2 2 #define SUNXI_BOOTED_FROM_SPI 3 +#define SUNXI_BOOTED_FROM_MMC0_HIGH 0x10 +#define SUNXI_BOOTED_FROM_MMC2_HIGH 0x12 /* boot head definition from sun4i boot code */ struct boot_file_head { diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 3039e66..992a841 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,5 +1,6 @@ #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ - !defined(CONFIG_ARCH_K3) + !defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \ + !defined(CONFIG_ARCH_BCM63158) #include <asm/arch/gpio.h> #endif #include <asm-generic/gpio.h> diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c index a555319..77cd15f 100644 --- a/arch/arm/mach-k3/am6_init.c +++ b/arch/arm/mach-k3/am6_init.c @@ -83,10 +83,8 @@ void board_init_f(ulong dummy) #ifdef CONFIG_K3_AM654_DDRSS ret = uclass_get_device(UCLASS_RAM, 0, &dev); - if (ret) { - printf("DRAM init failed: %d\n", ret); - return; - } + if (ret) + panic("DRAM init failed: %d\n", ret); #endif } diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 5909bbf..03f01d0 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -11,6 +11,20 @@ #include "common.h" #include <dm.h> #include <remoteproc.h> +#include <linux/soc/ti/ti_sci_protocol.h> +#include <fdt_support.h> + +struct ti_sci_handle *get_ti_sci_handle(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_FIRMWARE, "dmsc", &dev); + if (ret) + panic("Failed to get SYSFW (%d)\n", ret); + + return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev); +} #ifdef CONFIG_SYS_K3_SPL_ATF void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) @@ -42,3 +56,77 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) asm volatile("wfe"); } #endif + +#if defined(CONFIG_OF_LIBFDT) +int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name) +{ + u64 msmc_start = 0, msmc_end = 0, msmc_size, reg[2]; + struct ti_sci_handle *ti_sci = get_ti_sci_handle(); + int ret, node, subnode, len, prev_node; + u32 range[4], addr, size; + const fdt32_t *sub_reg; + + ti_sci->ops.core_ops.query_msmc(ti_sci, &msmc_start, &msmc_end); + msmc_size = msmc_end - msmc_start + 1; + debug("%s: msmc_start = 0x%llx, msmc_size = 0x%llx\n", __func__, + msmc_start, msmc_size); + + /* find or create "msmc_sram node */ + ret = fdt_path_offset(blob, parent_path); + if (ret < 0) + return ret; + + node = fdt_find_or_add_subnode(blob, ret, node_name); + if (node < 0) + return node; + + ret = fdt_setprop_string(blob, node, "compatible", "mmio-sram"); + if (ret < 0) + return ret; + + reg[0] = cpu_to_fdt64(msmc_start); + reg[1] = cpu_to_fdt64(msmc_size); + ret = fdt_setprop(blob, node, "reg", reg, sizeof(reg)); + if (ret < 0) + return ret; + + fdt_setprop_cell(blob, node, "#address-cells", 1); + fdt_setprop_cell(blob, node, "#size-cells", 1); + + range[0] = 0; + range[1] = cpu_to_fdt32(msmc_start >> 32); + range[2] = cpu_to_fdt32(msmc_start & 0xffffffff); + range[3] = cpu_to_fdt32(msmc_size); + ret = fdt_setprop(blob, node, "ranges", range, sizeof(range)); + if (ret < 0) + return ret; + + subnode = fdt_first_subnode(blob, node); + prev_node = 0; + + /* Look for invalid subnodes and delete them */ + while (subnode >= 0) { + sub_reg = fdt_getprop(blob, subnode, "reg", &len); + addr = fdt_read_number(sub_reg, 1); + sub_reg++; + size = fdt_read_number(sub_reg, 1); + debug("%s: subnode = %d, addr = 0x%x. size = 0x%x\n", __func__, + subnode, addr, size); + if (addr + size > msmc_size || + !strncmp(fdt_get_name(blob, subnode, &len), "sysfw", 5) || + !strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) { + fdt_del_node(blob, subnode); + debug("%s: deleting subnode %d\n", __func__, subnode); + if (!prev_node) + subnode = fdt_first_subnode(blob, node); + else + subnode = fdt_next_subnode(blob, prev_node); + } else { + prev_node = subnode; + subnode = fdt_next_subnode(blob, prev_node); + } + } + + return 0; +} +#endif diff --git a/arch/arm/mach-k3/include/mach/sys_proto.h b/arch/arm/mach-k3/include/mach/sys_proto.h index 0b20079..018725b 100644 --- a/arch/arm/mach-k3/include/mach/sys_proto.h +++ b/arch/arm/mach-k3/include/mach/sys_proto.h @@ -10,5 +10,6 @@ void sdelay(unsigned long loops); u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr, u32 bound); - +struct ti_sci_handle *get_ti_sci_handle(void); +int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name); #endif diff --git a/arch/arm/mach-keystone/Kconfig b/arch/arm/mach-keystone/Kconfig index d24596e..e06eba5 100644 --- a/arch/arm/mach-keystone/Kconfig +++ b/arch/arm/mach-keystone/Kconfig @@ -9,18 +9,24 @@ config TARGET_K2HK_EVM select SPL_BOARD_INIT if SPL select CMD_DDR3 imply DM_I2C + imply SOC_TI + imply TI_KEYSTONE_SERDES config TARGET_K2E_EVM bool "TI Keystone 2 Edison EVM" select SPL_BOARD_INIT if SPL select CMD_DDR3 imply DM_I2C + imply SOC_TI + imply TI_KEYSTONE_SERDES config TARGET_K2L_EVM bool "TI Keystone 2 Lamar EVM" select SPL_BOARD_INIT if SPL select CMD_DDR3 imply DM_I2C + imply SOC_TI + imply TI_KEYSTONE_SERDES config TARGET_K2G_EVM bool "TI Keystone 2 Galileo EVM" @@ -29,6 +35,8 @@ config TARGET_K2G_EVM select TI_I2C_BOARD_DETECT select CMD_DDR3 imply DM_I2C + imply SOC_TI + imply TI_KEYSTONE_SERDES endchoice diff --git a/arch/arm/mach-keystone/include/mach/hardware-k2g.h b/arch/arm/mach-keystone/include/mach/hardware-k2g.h index 8b90264..971c081 100644 --- a/arch/arm/mach-keystone/include/mach/hardware-k2g.h +++ b/arch/arm/mach-keystone/include/mach/hardware-k2g.h @@ -69,9 +69,12 @@ #define K2G_GPIO0_BASE 0X02603000 #define K2G_GPIO1_BASE 0X0260a000 +#define K2G_GPIO0_BANK0_BASE K2G_GPIO0_BASE + 0x10 #define K2G_GPIO1_BANK2_BASE K2G_GPIO1_BASE + 0x38 #define K2G_GPIO_DIR_OFFSET 0x0 +#define K2G_GPIO_OUTDATA_OFFSET 0x4 #define K2G_GPIO_SETDATA_OFFSET 0x8 +#define K2G_GPIO_CLRDATA_OFFSET 0xC /* BOOTCFG RESETMUX8 */ #define KS2_RSTMUX8 (KS2_DEVICE_STATE_CTRL_BASE + 0x328) diff --git a/arch/arm/mach-keystone/include/mach/mux-k2g.h b/arch/arm/mach-keystone/include/mach/mux-k2g.h index 809b72d..67d47f8 100644 --- a/arch/arm/mach-keystone/include/mach/mux-k2g.h +++ b/arch/arm/mach-keystone/include/mach/mux-k2g.h @@ -27,6 +27,11 @@ #define PIN_PTU (1 << 17) /* pull up */ #define PIN_PTD (0 << 17) /* pull down */ +#define BUFFER_CLASS_B (0 << 19) +#define BUFFER_CLASS_C (1 << 19) +#define BUFFER_CLASS_D (2 << 19) +#define BUFFER_CLASS_E (3 << 19) + #define MODE(m) ((m) & 0x7) #define MAX_PIN_N 260 diff --git a/arch/arm/mach-kirkwood/cpu.c b/arch/arm/mach-kirkwood/cpu.c index d54de53..8f8e300 100644 --- a/arch/arm/mach-kirkwood/cpu.c +++ b/arch/arm/mach-kirkwood/cpu.c @@ -46,69 +46,31 @@ unsigned int kw_winctrl_calcsize(unsigned int sizeval) return (0x0000ffff & j); } -/* - * kw_config_adr_windows - Configure address Windows - * - * There are 8 address windows supported by Kirkwood Soc to addess different - * devices. Each window can be configured for size, BAR and remap addr - * Below configuration is standard for most of the cases - * - * If remap function not used, remap_lo must be set as base - * - * Reference Documentation: - * Mbus-L to Mbus Bridge Registers Configuration. - * (Sec 25.1 and 25.3 of Datasheet) - */ -int kw_config_adr_windows(void) -{ - struct kwwin_registers *winregs = - (struct kwwin_registers *)KW_CPU_WIN_BASE; - +static struct mbus_win windows[] = { /* Window 0: PCIE MEM address space */ - writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 256, KWCPU_TARGET_PCIE, - KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), &winregs[0].ctrl); - - writel(KW_DEFADR_PCI_MEM, &winregs[0].base); - writel(KW_DEFADR_PCI_MEM, &winregs[0].remap_lo); - writel(0x0, &winregs[0].remap_hi); + { KW_DEFADR_PCI_MEM, 1024 * 1024 * 256, + KWCPU_TARGET_PCIE, KWCPU_ATTR_PCIE_MEM }, /* Window 1: PCIE IO address space */ - writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_PCIE, - KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), &winregs[1].ctrl); - writel(KW_DEFADR_PCI_IO, &winregs[1].base); - writel(KW_DEFADR_PCI_IO_REMAP, &winregs[1].remap_lo); - writel(0x0, &winregs[1].remap_hi); + { KW_DEFADR_PCI_IO, 1024 * 64, + KWCPU_TARGET_PCIE, KWCPU_ATTR_PCIE_IO }, /* Window 2: NAND Flash address space */ - writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY, - KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), &winregs[2].ctrl); - writel(KW_DEFADR_NANDF, &winregs[2].base); - writel(KW_DEFADR_NANDF, &winregs[2].remap_lo); - writel(0x0, &winregs[2].remap_hi); + { KW_DEFADR_NANDF, 1024 * 1024 * 128, + KWCPU_TARGET_MEMORY, KWCPU_ATTR_NANDFLASH }, /* Window 3: SPI Flash address space */ - writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY, - KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), &winregs[3].ctrl); - writel(KW_DEFADR_SPIF, &winregs[3].base); - writel(KW_DEFADR_SPIF, &winregs[3].remap_lo); - writel(0x0, &winregs[3].remap_hi); + { KW_DEFADR_SPIF, 1024 * 1024 * 128, + KWCPU_TARGET_MEMORY, KWCPU_ATTR_SPIFLASH }, /* Window 4: BOOT Memory address space */ - writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY, - KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), &winregs[4].ctrl); - writel(KW_DEFADR_BOOTROM, &winregs[4].base); + { KW_DEFADR_BOOTROM, 1024 * 1024 * 128, + KWCPU_TARGET_MEMORY, KWCPU_ATTR_BOOTROM }, /* Window 5: Security SRAM address space */ - writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_SASRAM, - KWCPU_ATTR_SASRAM, KWCPU_WIN_ENABLE), &winregs[5].ctrl); - writel(KW_DEFADR_SASRAM, &winregs[5].base); - - /* Window 6-7: Disabled */ - writel(KWCPU_WIN_DISABLE, &winregs[6].ctrl); - writel(KWCPU_WIN_DISABLE, &winregs[7].ctrl); - - return 0; -} + { KW_DEFADR_SASRAM, 1024 * 64, + KWCPU_TARGET_SASRAM, KWCPU_ATTR_SASRAM }, +}; /* * SYSRSTn Duration Counter Support @@ -221,15 +183,13 @@ int arch_cpu_init(void) struct kwcpu_registers *cpureg = (struct kwcpu_registers *)KW_CPU_REG_BASE; - /* Linux expects` the internal registers to be at 0xf1000000 */ + /* Linux expects the internal registers to be at 0xf1000000 */ writel(KW_REGS_PHY_BASE, KW_OFFSET_REG); /* Enable and invalidate L2 cache in write through mode */ writel(readl(&cpureg->l2_cfg) | 0x18, &cpureg->l2_cfg); invalidate_l2_cache(); - kw_config_adr_windows(); - #ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8 /* * Configures the I/O voltage of the pads connected to Egigabit @@ -291,11 +251,13 @@ int arch_misc_init(void) temp |= (1 << 22); writefr_extra_feature_reg(temp); - icache_enable(); /* Change reset vector to address 0x0 */ temp = get_cr(); set_cr(temp & ~CR_V); + /* Configure mbus windows */ + mvebu_mbus_probe(windows, ARRAY_SIZE(windows)); + /* checks and execute resset to factory event */ kw_sysrst_check(); diff --git a/arch/arm/mach-kirkwood/include/mach/cpu.h b/arch/arm/mach-kirkwood/include/mach/cpu.h index 91d2151..ea42182 100644 --- a/arch/arm/mach-kirkwood/include/mach/cpu.h +++ b/arch/arm/mach-kirkwood/include/mach/cpu.h @@ -63,12 +63,18 @@ enum kwcpu_attrib { */ #define KW_DEFADR_PCI_MEM 0x90000000 #define KW_DEFADR_PCI_IO 0xC0000000 -#define KW_DEFADR_PCI_IO_REMAP 0xC0000000 #define KW_DEFADR_SASRAM 0xC8010000 #define KW_DEFADR_NANDF 0xD8000000 #define KW_DEFADR_SPIF 0xE8000000 #define KW_DEFADR_BOOTROM 0xF8000000 +struct mbus_win { + u32 base; + u32 size; + u8 target; + u8 attr; +}; + /* * read feroceon/sheeva core extra feature register * using co-proc instruction @@ -135,13 +141,16 @@ struct kwgpio_registers { u32 irq_level; }; +/* Needed for dynamic (board-specific) mbus configuration */ +extern struct mvebu_mbus_state mbus_state; + /* * functions */ unsigned int mvebu_sdram_bar(enum memory_bank bank); unsigned int mvebu_sdram_bs(enum memory_bank bank); void mvebu_sdram_size_adjust(enum memory_bank bank); -int kw_config_adr_windows(void); +int mvebu_mbus_probe(struct mbus_win windows[], int count); void mvebu_config_gpio(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val, unsigned int gpp0_oe, unsigned int gpp1_oe); int kw_config_mpp(unsigned int mpp0_7, unsigned int mpp8_15, diff --git a/arch/arm/mach-kirkwood/include/mach/soc.h b/arch/arm/mach-kirkwood/include/mach/soc.h index 227707a..1d7f282 100644 --- a/arch/arm/mach-kirkwood/include/mach/soc.h +++ b/arch/arm/mach-kirkwood/include/mach/soc.h @@ -31,7 +31,7 @@ #define KW_RTC_BASE (KW_REGISTER(0x10300)) #define KW_NANDF_BASE (KW_REGISTER(0x10418)) #define MVEBU_SPI_BASE (KW_REGISTER(0x10600)) -#define KW_CPU_WIN_BASE (KW_REGISTER(0x20000)) +#define MVEBU_CPU_WIN_BASE (KW_REGISTER(0x20000)) #define KW_CPU_REG_BASE (KW_REGISTER(0x20100)) #define MVEBU_TIMER_BASE (KW_REGISTER(0x20300)) #define KW_REG_PCIE_BASE (KW_REGISTER(0x40000)) diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 7dda04e..f5fd60d 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -9,10 +9,10 @@ config ARMADA_32BIT select ARCH_MISC_INIT select BOARD_EARLY_INIT_F select CPU_V7A - select SPL_DM - select SPL_DM_SEQ_ALIAS - select SPL_OF_CONTROL - select SPL_SIMPLE_BUS + select SPL_DM if SPL + select SPL_DM_SEQ_ALIAS if SPL + select SPL_OF_CONTROL if SPL + select SPL_SIMPLE_BUS if SPL select SUPPORT_SPL config ARMADA_64BIT @@ -46,7 +46,7 @@ config ARMADA_8K # Armada PLL frequency (used for NAND clock generation) config SYS_MVEBU_PLL_CLOCK int - default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K + default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K || ARMADA_MSYS default "1000000000" if ARMADA_38X || ARMADA_375 # Armada XP/38x SoC types... @@ -63,6 +63,22 @@ config MV78460 bool select ARMADA_XP +config ARMADA_MSYS + bool + select ARMADA_32BIT + +config 98DX4251 + bool + select ARMADA_MSYS + +config 98DX3336 + bool + select ARMADA_MSYS + +config 98DX3236 + bool + select ARMADA_MSYS + config 88F6820 bool select ARMADA_38X @@ -136,6 +152,10 @@ config TARGET_X530 bool "Support Allied Telesis x530" select 88F6820 +config TARGET_DB_XC3_24G4XG + bool "Support DB-XC3-24G4XG" + select 98DX3336 + endchoice config SYS_BOARD @@ -154,6 +174,7 @@ config SYS_BOARD default "theadorable" if TARGET_THEADORABLE default "a38x" if TARGET_CONTROLCENTERDC default "x530" if TARGET_X530 + default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG config SYS_CONFIG_NAME default "clearfog" if TARGET_CLEARFOG @@ -171,6 +192,7 @@ config SYS_CONFIG_NAME default "turris_mox" if TARGET_TURRIS_MOX default "controlcenterdc" if TARGET_CONTROLCENTERDC default "x530" if TARGET_X530 + default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG config SYS_VENDOR default "Marvell" if TARGET_DB_MV784MP_GP @@ -179,6 +201,8 @@ config SYS_VENDOR default "Marvell" if TARGET_DB_88F6820_GP default "Marvell" if TARGET_DB_88F6820_AMC default "Marvell" if TARGET_MVEBU_ARMADA_8K + default "Marvell" if TARGET_DB_XC3_24G4XG + default "Marvell" if TARGET_MVEBU_DB_88F7040 default "solidrun" if TARGET_CLEARFOG default "kobol" if TARGET_HELIOS4 default "Synology" if TARGET_DS414 diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index ee2eca9..02d3ce2 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -14,6 +14,7 @@ ifdef CONFIG_KIRKWOOD obj-y = dram.o obj-y += gpio.o +obj-y += mbus.o obj-y += timer.o else # CONFIG_KIRKWOOD @@ -24,6 +25,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o +obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o obj-$(CONFIG_MVEBU_EFUSE) += efuse.o extra-y += kwbimage.cfg diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 919d05c..c5b3df4 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -23,6 +23,11 @@ static struct mbus_win windows[] = { /* NOR */ { MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE, CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM }, + +#ifdef CONFIG_ARMADA_MSYS + /* DFX */ + { MBUS_DFX_BASE, MBUS_DFX_SIZE, CPU_TARGET_DFX, 0 }, +#endif }; void lowlevel_init(void) @@ -121,6 +126,14 @@ static const struct sar_freq_modes sar_freq_tab[] = { { 0x13, 0x0, 2000, 1000, 933 }, { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ }; +#elif defined(CONFIG_ARMADA_MSYS) +static const struct sar_freq_modes sar_freq_tab[] = { + { 0x0, 0x0, 400, 400, 400 }, + { 0x2, 0x0, 667, 333, 667 }, + { 0x3, 0x0, 800, 400, 800 }, + { 0x5, 0x0, 800, 400, 800 }, + { 0xff, 0xff, 0, 0, 0 } /* 0xff marks end of array */ +}; #else /* SAR frequency values for Armada XP */ static const struct sar_freq_modes sar_freq_tab[] = { @@ -144,7 +157,7 @@ void get_sar_freq(struct sar_freq_modes *sar_freq) u32 freq; int i; -#if defined(CONFIG_ARMADA_375) +#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_MSYS) val = readl(CONFIG_SAR2_REG); /* SAR - Sample At Reset */ #else val = readl(CONFIG_SAR_REG); /* SAR - Sample At Reset */ @@ -160,7 +173,7 @@ void get_sar_freq(struct sar_freq_modes *sar_freq) #endif for (i = 0; sar_freq_tab[i].val != 0xff; i++) { if (sar_freq_tab[i].val == freq) { -#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X) +#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS) *sar_freq = sar_freq_tab[i]; return; #else @@ -270,6 +283,20 @@ int print_cpuinfo(void) } } + if (mvebu_soc_family() == MVEBU_SOC_MSYS) { + switch (revid) { + case 3: + puts("A0"); + break; + case 4: + puts("A1"); + break; + default: + printf("?? (%x)", revid); + break; + } + } + get_sar_freq(&sar_freq); printf(" at %d MHz\n", sar_freq.p_clk); @@ -472,6 +499,8 @@ u32 mvebu_get_nand_clock(void) if (mvebu_soc_family() == MVEBU_SOC_A38X) reg = MVEBU_DFX_DIV_CLK_CTRL(1); + else if (mvebu_soc_family() == MVEBU_SOC_MSYS) + reg = MVEBU_DFX_DIV_CLK_CTRL(8); else reg = MVEBU_CORE_DIV_CLK_CTRL(1); @@ -501,7 +530,6 @@ int board_mmc_init(bd_t *bis) } #endif -#ifdef CONFIG_SCSI_AHCI_PLAT #define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 #define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 @@ -545,11 +573,19 @@ static void ahci_mvebu_regret_option(void __iomem *base) writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA); } -void scsi_init(void) +int board_ahci_enable(void) { - printf("MVEBU SATA INIT\n"); ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE); ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE); + + return 0; +} + +#ifdef CONFIG_SCSI_AHCI_PLAT +void scsi_init(void) +{ + printf("MVEBU SATA INIT\n"); + board_ahci_enable(); ahci_init((void __iomem *)MVEBU_SATA0_BASE); } #endif diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h index 71c4f70..bbcfcfd 100644 --- a/arch/arm/mach-mvebu/include/mach/config.h +++ b/arch/arm/mach-mvebu/include/mach/config.h @@ -17,7 +17,7 @@ #include <asm/arch/soc.h> #if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_375) \ - || defined(CONFIG_ARMADA_38X) + || defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS) /* * Set this for the common xor register definitions needed in dram.c * for A38x as well here. diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h index 9e23043..b9153d8 100644 --- a/arch/arm/mach-mvebu/include/mach/cpu.h +++ b/arch/arm/mach-mvebu/include/mach/cpu.h @@ -34,6 +34,7 @@ enum cpu_target { CPU_TARGET_PCIE02 = 0x4, CPU_TARGET_ETH01 = 0x7, CPU_TARGET_PCIE13 = 0x8, + CPU_TARGET_DFX = 0x8, CPU_TARGET_SASRAM = 0x9, CPU_TARGET_SATA01 = 0xa, /* A38X */ CPU_TARGET_NAND = 0xd, @@ -79,6 +80,8 @@ enum { #define MBUS_PCI_IO_SIZE (64 << 10) #define MBUS_SPI_BASE 0xF4000000 #define MBUS_SPI_SIZE (8 << 20) +#define MBUS_DFX_BASE 0xF6000000 +#define MBUS_DFX_SIZE (1 << 20) #define MBUS_BOOTROM_BASE 0xF8000000 #define MBUS_BOOTROM_SIZE (8 << 20) diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 01577f4..f666ee2 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -76,7 +76,11 @@ #define MVEBU_NAND_BASE (MVEBU_REGISTER(0xd0000)) #define MVEBU_SDIO_BASE (MVEBU_REGISTER(0xd8000)) #define MVEBU_LCD_BASE (MVEBU_REGISTER(0xe0000)) +#ifdef CONFIG_ARMADA_MSYS +#define MVEBU_DFX_BASE (MBUS_DFX_BASE) +#else #define MVEBU_DFX_BASE (MVEBU_REGISTER(0xe4000)) +#endif #define SOC_COHERENCY_FABRIC_CTRL_REG (MVEBU_REGISTER(0x20200)) #define MBUS_ERR_PROP_EN (1 << 8) @@ -96,9 +100,20 @@ #define SPI_PUP_EN BIT(5) #define MVEBU_CORE_DIV_CLK_CTRL(i) (MVEBU_CLOCK_BASE + ((i) * 0x8)) +#ifdef CONFIG_ARMADA_MSYS +#define MVEBU_DFX_DIV_CLK_CTRL(i) (MVEBU_DFX_BASE + 0xf8000 + 0x250 + ((i) * 0x4)) +#define NAND_ECC_DIVCKL_RATIO_OFFS 6 +#define NAND_ECC_DIVCKL_RATIO_MASK (0xF << NAND_ECC_DIVCKL_RATIO_OFFS) +#else #define MVEBU_DFX_DIV_CLK_CTRL(i) (MVEBU_DFX_BASE + 0x250 + ((i) * 0x4)) +#endif +#ifdef CONFIG_ARMADA_MSYS +#define NAND_ECC_DIVCKL_RATIO_OFFS 6 +#define NAND_ECC_DIVCKL_RATIO_MASK (0xF << NAND_ECC_DIVCKL_RATIO_OFFS) +#else #define NAND_ECC_DIVCKL_RATIO_OFFS 8 #define NAND_ECC_DIVCKL_RATIO_MASK (0x3F << NAND_ECC_DIVCKL_RATIO_OFFS) +#endif #define SDRAM_MAX_CS 4 #define SDRAM_ADDR_MASK 0xFF000000 @@ -149,6 +164,22 @@ #define BOOT_FROM_SPI 0x32 #define BOOT_FROM_MMC 0x30 #define BOOT_FROM_MMC_ALT 0x31 +#elif defined(CONFIG_ARMADA_MSYS) +/* SAR values for MSYS */ +#define CONFIG_SAR_REG (MBUS_DFX_BASE + 0xf8200) +#define CONFIG_SAR2_REG (MBUS_DFX_BASE + 0xf8204) + +#define SAR_CPU_FREQ_OFFS 18 +#define SAR_CPU_FREQ_MASK (0x7 << SAR_CPU_FREQ_OFFS) +#define SAR_BOOT_DEVICE_OFFS 11 +#define SAR_BOOT_DEVICE_MASK (0x7 << SAR_BOOT_DEVICE_OFFS) + +#define BOOT_DEV_SEL_OFFS 11 +#define BOOT_DEV_SEL_MASK (0x7 << BOOT_DEV_SEL_OFFS) + +#define BOOT_FROM_NAND 0x1 +#define BOOT_FROM_UART 0x2 +#define BOOT_FROM_SPI 0x3 #else /* SAR values for Armada XP */ #define CONFIG_SAR_REG (MVEBU_REGISTER(0x18230)) diff --git a/arch/arm/mach-mvebu/mbus.c b/arch/arm/mach-mvebu/mbus.c index df4c5cb..c68e93b 100644 --- a/arch/arm/mach-mvebu/mbus.c +++ b/arch/arm/mach-mvebu/mbus.c @@ -344,6 +344,11 @@ static void mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) } } mbus_dram_info.num_cs = cs; + +#if defined(CONFIG_ARMADA_MSYS) + /* Disable MBUS Err Prop - in order to avoid data aborts */ + clrbits_le32(mbus->mbuswins_base + 0x200, BIT(8)); +#endif } static const struct mvebu_mbus_soc_data @@ -405,6 +410,7 @@ int mvebu_mbus_del_window(phys_addr_t base, size_t size) return 0; } +#ifndef CONFIG_KIRKWOOD static void mvebu_mbus_get_lowest_base(struct mvebu_mbus_state *mbus, phys_addr_t *base) { @@ -451,6 +457,7 @@ static void mvebu_config_mbus_bridge(struct mvebu_mbus_state *mbus) val = (size / (64 << 10)) - 1; writel((val << 16) | 0x1, MBUS_BRIDGE_WIN_CTRL_REG); } +#endif int mbus_dt_setup_win(struct mvebu_mbus_state *mbus, u32 base, u32 size, u8 target, u8 attr) @@ -471,12 +478,14 @@ int mbus_dt_setup_win(struct mvebu_mbus_state *mbus, return -ENOMEM; } +#ifndef CONFIG_KIRKWOOD /* * Re-configure the mbus bridge registers each time this function * is called. Since it may get called from the board code in * later boot stages as well. */ mvebu_config_mbus_bridge(mbus); +#endif return 0; } diff --git a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c index 569840f..c8c9298 100644 --- a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c +++ b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c @@ -35,7 +35,7 @@ int pex_local_dev_num_set(u32 pex_if, u32 dev_num); #define ETM_MODULE_DETECT 2 #define PEX_MODE_GET(satr) ((satr & 0x6) >> 1) -#define PEX_CAPABILITY_GET(satr) (satr & 1) +#define PEX_CAPABILITY_GET(satr, port) ((satr >> port) & 1) #define MV_PEX_UNIT_TO_IF(pex_unit) ((pex_unit < 3) ? (pex_unit * 4) : 9) /* Static parametes */ @@ -176,7 +176,7 @@ u8 board_cpu_freq_get(void) return ((sar_msb & 0x100000) >> 17) | ((sar & 0xe00000) >> 21); } -__weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) +__weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(void) { u32 board_id; u32 serdes_cfg_val = 0; /* default */ @@ -352,7 +352,7 @@ int serdes_phy_config(void) DEBUG_WR_REG(CPU_AVS_CONTROL2_REG, cpu_avs); } - info = board_serdes_cfg_get(PEX_MODE_GET(satr11)); + info = board_serdes_cfg_get(); if (info == NULL) { DEBUG_INIT_S("Hight speed PHY Error #1\n"); @@ -675,7 +675,7 @@ int serdes_phy_config(void) tmp |= (0x1 << 4); if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4) tmp |= (0x4 << 4); - if (0 == PEX_CAPABILITY_GET(satr11)) + if (0 == PEX_CAPABILITY_GET(satr11, pex_unit)) tmp |= 0x1; else tmp |= 0x2; diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1cac443..d29f1ca 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -167,21 +167,6 @@ config TI_SECURE_EMIF_PROTECTED_REGION_SIZE using hardware memory firewalls. This value must be smaller than the TI_SECURE_EMIF_TOTAL_REGION_SIZE value. -if AM43XX || AM33XX || OMAP54XX -config ISW_ENTRY_ADDR - hex "Address in memory or XIP address of bootloader entry point" - default 0x402F4000 if AM43XX - default 0x402F0400 if AM33XX - default 0x40301350 if OMAP54XX - help - After any reset, the boot ROM searches the boot media for a valid - boot image. For non-XIP devices, the ROM then copies the image into - internal memory. For all boot modes, after the ROM processes the - boot image it eventually computes the entry point address depending - on the device type (secure/non-secure), boot media (xip/non-xip) and - image headers. -endif - source "arch/arm/mach-omap2/omap3/Kconfig" source "arch/arm/mach-omap2/omap4/Kconfig" diff --git a/arch/arm/mach-omap2/am33xx/Kconfig b/arch/arm/mach-omap2/am33xx/Kconfig index 85ea894..500df1a 100644 --- a/arch/arm/mach-omap2/am33xx/Kconfig +++ b/arch/arm/mach-omap2/am33xx/Kconfig @@ -87,6 +87,13 @@ config TARGET_AM335X_SHC imply CMD_DM imply CMD_SPL +config TARGET_AM335X_GUARDIAN + bool "Support am335x based guardian board from bosch" + select DM + select DM_SERIAL + select DM_GPIO + select DM_USB + config TARGET_AM335X_SL50 bool "Support am335x_sl50" select BOARD_LATE_INIT diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 8a929fa..73aa382 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -17,7 +17,7 @@ config SPL select SPL_DM_RESET select SPL_SERIAL_SUPPORT select SPL_SYSCON - select SPL_DRIVERS_MISC_SUPPORT + imply SPL_DISPLAY_PRINT imply SPL_LIBDISK_SUPPORT config SYS_SOC @@ -25,18 +25,31 @@ config SYS_SOC config TARGET_STM32MP1 bool "Support stm32mp1xx" - select ARCH_SUPPORT_PSCI + select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED select CPU_V7A - select CPU_V7_HAS_NONSEC + select CPU_V7_HAS_NONSEC if !STM32MP1_TRUSTED select CPU_V7_HAS_VIRT select PINCTRL_STM32 select STM32_RCC select STM32_RESET select SYS_ARCH_TIMER - select SYSRESET_SYSCON + imply SYSRESET_PSCI if STM32MP1_TRUSTED + imply SYSRESET_SYSCON if !STM32MP1_TRUSTED help target STMicroelectronics SOC STM32MP1 family + STM32MP157, STM32MP153 or STM32MP151 STMicroelectronics MPU with core ARMv7 + dual core A7 for STM32MP157/3, monocore for STM32MP151 + +config STM32MP1_TRUSTED + bool "Support trusted boot with TF-A" + default y if !SPL + select ARM_SMCCC + help + Say Y here to enable boot with TF-A + Trusted boot chain is : + BootRom => TF-A.stm32 (clock & DDR) => U-Boot.stm32 + TF-A monitor provides proprietary smc to manage secure devices config SYS_TEXT_BASE prompt "U-Boot base address" @@ -46,6 +59,9 @@ config SYS_TEXT_BASE when DDR driver is used: DDR + 1MB (0xC0100000) +config NR_DRAM_BANKS + default 1 + config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2 hex "Partition on MMC2 to use to load U-Boot from" depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION @@ -54,9 +70,6 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2 Partition on the second MMC to load U-Boot from when the MMC is being used in raw mode -source "board/st/stm32mp1/Kconfig" - -# currently activated for debug / should be deactivated for real product if DEBUG_UART config DEBUG_UART_BOARD_INIT @@ -71,4 +84,6 @@ config DEBUG_UART_CLOCK default 64000000 endif +source "board/st/stm32mp1/Kconfig" + endif diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile index f59ced5..1493914 100644 --- a/arch/arm/mach-stm32mp/Makefile +++ b/arch/arm/mach-stm32mp/Makefile @@ -11,6 +11,9 @@ ifdef CONFIG_SPL_BUILD obj-y += spl.o else obj-y += bsec.o +ifndef CONFIG_STM32MP1_TRUSTED +obj-$(CONFIG_SYSRESET) += cmd_poweroff.o +endif endif obj-$(CONFIG_ARMV7_PSCI) += psci.o obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c index d087a31..9ed8d8c 100644 --- a/arch/arm/mach-stm32mp/bsec.c +++ b/arch/arm/mach-stm32mp/bsec.c @@ -8,9 +8,12 @@ #include <misc.h> #include <asm/io.h> #include <linux/iopoll.h> +#include <asm/arch/stm32mp1_smc.h> +#include <linux/arm-smccc.h> #define BSEC_OTP_MAX_VALUE 95 +#ifndef CONFIG_STM32MP1_TRUSTED #define BSEC_TIMEOUT_US 10000 /* BSEC REGISTER OFFSET (base relative) */ @@ -168,7 +171,7 @@ static int bsec_shadow_register(u32 base, u32 otp) ret = bsec_power_safmem(base, true); if (ret) return ret; - power_up = 1; + power_up = true; } /* set BSEC_OTP_CTRL_OFF with the otp value*/ writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF); @@ -270,6 +273,7 @@ static int bsec_program_otp(long base, u32 val, u32 otp) return ret; } +#endif /* CONFIG_STM32MP1_TRUSTED */ /* BSEC MISC driver *******************************************************/ struct stm32mp_bsec_platdata { @@ -278,6 +282,11 @@ struct stm32mp_bsec_platdata { static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp) { +#ifdef CONFIG_STM32MP1_TRUSTED + return stm32_smc(STM32_SMC_BSEC, + STM32_SMC_READ_OTP, + otp, 0, val); +#else struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); u32 tmp_data = 0; int ret; @@ -299,27 +308,46 @@ static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp) /* restore shadow value */ ret = bsec_write_shadow(plat->base, tmp_data, otp); return ret; +#endif } static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp) { +#ifdef CONFIG_STM32MP1_TRUSTED + return stm32_smc(STM32_SMC_BSEC, + STM32_SMC_READ_SHADOW, + otp, 0, val); +#else struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); return bsec_read_shadow(plat->base, val, otp); +#endif } static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp) { +#ifdef CONFIG_STM32MP1_TRUSTED + return stm32_smc_exec(STM32_SMC_BSEC, + STM32_SMC_PROG_OTP, + otp, val); +#else struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); return bsec_program_otp(plat->base, val, otp); +#endif } static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp) { +#ifdef CONFIG_STM32MP1_TRUSTED + return stm32_smc_exec(STM32_SMC_BSEC, + STM32_SMC_WRITE_SHADOW, + otp, val); +#else struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); return bsec_write_shadow(plat->base, val, otp); +#endif } static int stm32mp_bsec_read(struct udevice *dev, int offset, @@ -405,8 +433,23 @@ static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev) return 0; } +#ifndef CONFIG_STM32MP1_TRUSTED +static int stm32mp_bsec_probe(struct udevice *dev) +{ + int otp; + struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev); + + /* update unlocked shadow for OTP cleared by the rom code */ + for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++) + if (!bsec_read_SR_lock(plat->base, otp)) + bsec_shadow_register(plat->base, otp); + + return 0; +} +#endif + static const struct udevice_id stm32mp_bsec_ids[] = { - { .compatible = "st,stm32mp-bsec" }, + { .compatible = "st,stm32mp15-bsec" }, {} }; @@ -417,14 +460,7 @@ U_BOOT_DRIVER(stm32mp_bsec) = { .ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata), .ops = &stm32mp_bsec_ops, -}; - -/* bsec IP is not present in device tee, manage IP address by platdata */ -static struct stm32mp_bsec_platdata stm32_bsec_platdata = { - .base = STM32_BSEC_BASE, -}; - -U_BOOT_DEVICE(stm32mp_bsec) = { - .name = "stm32mp_bsec", - .platdata = &stm32_bsec_platdata, +#ifndef CONFIG_STM32MP1_TRUSTED + .probe = stm32mp_bsec_probe, +#endif }; diff --git a/arch/arm/mach-stm32mp/cmd_poweroff.c b/arch/arm/mach-stm32mp/cmd_poweroff.c new file mode 100644 index 0000000..f54dd1d --- /dev/null +++ b/arch/arm/mach-stm32mp/cmd_poweroff.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2019, STMicroelectronics - All Rights Reserved + */ + +#include <common.h> +#include <command.h> +#include <sysreset.h> + +int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret; + + puts("poweroff ...\n"); + mdelay(100); + + ret = sysreset_walk(SYSRESET_POWER); + + if (ret == -EINPROGRESS) + mdelay(1000); + + /*NOTREACHED when power off*/ + return CMD_RET_FAILURE; +} diff --git a/arch/arm/mach-stm32mp/config.mk b/arch/arm/mach-stm32mp/config.mk index f371aac..403af2a 100644 --- a/arch/arm/mach-stm32mp/config.mk +++ b/arch/arm/mach-stm32mp/config.mk @@ -3,7 +3,20 @@ # Copyright (C) 2018, STMicroelectronics - All Rights Reserved # -ALL-$(CONFIG_SPL_BUILD) += u-boot-spl.stm32 +ifndef CONFIG_SPL +ALL-y += u-boot.stm32 +else +ifdef CONFIG_SPL_BUILD +ALL-y += u-boot-spl.stm32 +endif +endif + +MKIMAGEFLAGS_u-boot.stm32 = -T stm32image -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE) + +u-boot.stm32: MKIMAGEOUTPUT = u-boot.stm32.log + +u-boot.stm32: u-boot.bin FORCE + $(call if_changed,mkimage) MKIMAGEFLAGS_u-boot-spl.stm32 = -T stm32image -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index b893358..7b4431c 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -18,6 +18,7 @@ #define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C) #define RCC_BDCR (STM32_RCC_BASE + 0x0140) #define RCC_MP_APB5ENSETR (STM32_RCC_BASE + 0x0208) +#define RCC_MP_AHB5ENSETR (STM32_RCC_BASE + 0x0210) #define RCC_BDCR_VSWRST BIT(31) #define RCC_BDCR_RTCSRC GENMASK(17, 16) #define RCC_DBGCFGR_DBGCKEN BIT(8) @@ -44,6 +45,9 @@ #define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16) #define DBGMCU_IDC_REV_ID_SHIFT 16 +/* GPIOZ registers */ +#define GPIOZ_SECCFGR 0x54004030 + /* boot interface from Bootrom * - boot instance = bit 31:16 * - boot device = bit 15:0 @@ -55,10 +59,32 @@ #define BOOTROM_INSTANCE_SHIFT 16 /* BSEC OTP index */ +#define BSEC_OTP_RPN 1 #define BSEC_OTP_SERIAL 13 +#define BSEC_OTP_PKG 16 #define BSEC_OTP_MAC 57 +/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */ +#define RPN_SHIFT 0 +#define RPN_MASK GENMASK(7, 0) + +/* Package = bit 27:29 of OTP16 + * - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm + * - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm + * - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm + * - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm + * - others: Reserved + */ +#define PKG_SHIFT 27 +#define PKG_MASK GENMASK(2, 0) + +#define PKG_AA_LBGA448 4 +#define PKG_AB_LBGA354 3 +#define PKG_AC_TFBGA361 2 +#define PKG_AD_TFBGA257 1 + #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) +#ifndef CONFIG_STM32MP1_TRUSTED static void security_init(void) { /* Disable the backup domain write protection */ @@ -113,7 +139,12 @@ static void security_init(void) * Bit 16 ITAMP1E: RTC power domain supply monitoring */ writel(0x0, TAMP_CR1); + + /* GPIOZ: deactivate the security */ + writel(BIT(0), RCC_MP_AHB5ENSETR); + writel(0x0, GPIOZ_SECCFGR); } +#endif /* CONFIG_STM32MP1_TRUSTED */ /* * Debug init @@ -127,13 +158,19 @@ static void dbgmcu_init(void) } #endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */ -static u32 get_bootmode(void) +#if !defined(CONFIG_STM32MP1_TRUSTED) && \ + (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) +/* get bootmode from ROM code boot context: saved in TAMP register */ +static void update_bootmode(void) { u32 boot_mode; -#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR); u32 bootrom_device, bootrom_instance; + /* enable TAMP clock = RTCAPBEN */ + writel(BIT(8), RCC_MP_APB5ENSETR); + + /* read bootrom context */ bootrom_device = (bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT; bootrom_instance = @@ -147,12 +184,14 @@ static u32 get_bootmode(void) clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_MODE_MASK, boot_mode << TAMP_BOOT_MODE_SHIFT); -#else - /* read TAMP backup register */ - boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >> - TAMP_BOOT_MODE_SHIFT; +} #endif - return boot_mode; + +u32 get_bootmode(void) +{ + /* read bootmode from TAMP backup register */ + return (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >> + TAMP_BOOT_MODE_SHIFT; } /* @@ -167,16 +206,18 @@ int arch_cpu_init(void) #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) dbgmcu_init(); - +#ifndef CONFIG_STM32MP1_TRUSTED security_init(); + update_bootmode(); +#endif #endif - /* get bootmode from BootRom context: saved in TAMP register */ boot_mode = get_bootmode(); if ((boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART) gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE; #if defined(CONFIG_DEBUG_UART) && \ + !defined(CONFIG_STM32MP1_TRUSTED) && \ (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) else debug_uart_init(); @@ -203,25 +244,94 @@ u32 get_cpu_rev(void) return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT; } +static u32 get_otp(int index, int shift, int mask) +{ + int ret; + struct udevice *dev; + u32 otp = 0; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + + if (!ret) + ret = misc_read(dev, STM32_BSEC_SHADOW(index), + &otp, sizeof(otp)); + + return (otp >> shift) & mask; +} + +/* Get Device Part Number (RPN) from OTP */ +static u32 get_cpu_rpn(void) +{ + return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK); +} + u32 get_cpu_type(void) { - return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT; + u32 id; + + id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT; + + return (id << 16) | get_cpu_rpn(); +} + +/* Get Package options from OTP */ +static u32 get_cpu_package(void) +{ + return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK); } #if defined(CONFIG_DISPLAY_CPUINFO) int print_cpuinfo(void) { - char *cpu_s, *cpu_r; + char *cpu_s, *cpu_r, *pkg; + /* MPUs Part Numbers */ switch (get_cpu_type()) { - case CPU_STMP32MP15x: - cpu_s = "15x"; + case CPU_STM32MP157Cxx: + cpu_s = "157C"; + break; + case CPU_STM32MP157Axx: + cpu_s = "157A"; + break; + case CPU_STM32MP153Cxx: + cpu_s = "153C"; + break; + case CPU_STM32MP153Axx: + cpu_s = "153A"; + break; + case CPU_STM32MP151Cxx: + cpu_s = "151C"; + break; + case CPU_STM32MP151Axx: + cpu_s = "151A"; + break; + default: + cpu_s = "????"; + break; + } + + /* Package */ + switch (get_cpu_package()) { + case PKG_AA_LBGA448: + pkg = "AA"; + break; + case PKG_AB_LBGA354: + pkg = "AB"; + break; + case PKG_AC_TFBGA361: + pkg = "AC"; + break; + case PKG_AD_TFBGA257: + pkg = "AD"; break; default: - cpu_s = "?"; + pkg = "??"; break; } + /* REVISION */ switch (get_cpu_rev()) { case CPU_REVA: cpu_r = "A"; @@ -234,7 +344,7 @@ int print_cpuinfo(void) break; } - printf("CPU: STM32MP%s.%s\n", cpu_s, cpu_r); + printf("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r); return 0; } @@ -242,20 +352,48 @@ int print_cpuinfo(void) static void setup_boot_mode(void) { + const u32 serial_addr[] = { + STM32_USART1_BASE, + STM32_USART2_BASE, + STM32_USART3_BASE, + STM32_UART4_BASE, + STM32_UART5_BASE, + STM32_USART6_BASE, + STM32_UART7_BASE, + STM32_UART8_BASE + }; char cmd[60]; u32 boot_ctx = readl(TAMP_BOOT_CONTEXT); u32 boot_mode = (boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT; int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1; + u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK); + struct udevice *dev; + int alias; - pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d\n", - __func__, boot_ctx, boot_mode, instance); - + pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d forced=%x\n", + __func__, boot_ctx, boot_mode, instance, forced_mode); switch (boot_mode & TAMP_BOOT_DEVICE_MASK) { case BOOT_SERIAL_UART: - sprintf(cmd, "%d", instance); - env_set("boot_device", "uart"); + if (instance > ARRAY_SIZE(serial_addr)) + break; + /* serial : search associated alias in devicetree */ + sprintf(cmd, "serial@%x", serial_addr[instance]); + if (uclass_get_device_by_name(UCLASS_SERIAL, cmd, &dev)) + break; + if (fdtdec_get_alias_seq(gd->fdt_blob, "serial", + dev_of_offset(dev), &alias)) + break; + sprintf(cmd, "%d", alias); + env_set("boot_device", "serial"); env_set("boot_instance", cmd); + + /* restore console on uart when not used */ + if (gd->cur_serial_dev != dev) { + gd->flags &= ~(GD_FLG_SILENT | + GD_FLG_DISABLE_CONSOLE); + printf("serial boot with console enabled!\n"); + } break; case BOOT_SERIAL_USB: env_set("boot_device", "usb"); @@ -279,6 +417,36 @@ static void setup_boot_mode(void) pr_debug("unexpected boot mode = %x\n", boot_mode); break; } + + switch (forced_mode) { + case BOOT_FASTBOOT: + printf("Enter fastboot!\n"); + env_set("preboot", "env set preboot; fastboot 0"); + break; + case BOOT_STM32PROG: + env_set("boot_device", "usb"); + env_set("boot_instance", "0"); + break; + case BOOT_UMS_MMC0: + case BOOT_UMS_MMC1: + case BOOT_UMS_MMC2: + printf("Enter UMS!\n"); + instance = forced_mode - BOOT_UMS_MMC0; + sprintf(cmd, "env set preboot; ums 0 mmc %d", instance); + env_set("preboot", cmd); + break; + case BOOT_RECOVERY: + env_set("preboot", "env set preboot; run altbootcmd"); + break; + case BOOT_NORMAL: + break; + default: + pr_debug("unexpected forced boot mode = %x\n", forced_mode); + break; + } + + /* clear TAMP for next reboot */ + clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_NORMAL); } /* @@ -304,7 +472,7 @@ static int setup_mac_address(void) if (ret) return ret; - ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET, + ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_MAC), otp, sizeof(otp)); if (ret < 0) return ret; @@ -342,12 +510,12 @@ static int setup_serial_number(void) if (ret) return ret; - ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET, + ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_SERIAL), otp, sizeof(otp)); if (ret < 0) return ret; - sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]); + sprintf(serial_string, "%08X%08X%08X", otp[0], otp[1], otp[2]); env_set("serial#", serial_string); return 0; diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 5d0bdca..c526c88 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -13,13 +13,10 @@ #define STM32_RCC_BASE 0x50000000 #define STM32_PWR_BASE 0x50001000 #define STM32_DBGMCU_BASE 0x50081000 -#define STM32_BSEC_BASE 0x5C005000 #define STM32_TZC_BASE 0x5C006000 #define STM32_ETZPC_BASE 0x5C007000 #define STM32_TAMP_BASE 0x5C00A000 -#ifdef CONFIG_DEBUG_UART_BASE -/* hardcoded value can be only used for DEBUG UART */ #define STM32_USART1_BASE 0x5C000000 #define STM32_USART2_BASE 0x4000E000 #define STM32_USART3_BASE 0x4000F000 @@ -28,7 +25,6 @@ #define STM32_USART6_BASE 0x44003000 #define STM32_UART7_BASE 0x40018000 #define STM32_UART8_BASE 0x40019000 -#endif #define STM32_SYSRAM_BASE 0x2FFC0000 #define STM32_SYSRAM_SIZE SZ_256K @@ -40,8 +36,10 @@ /* enumerated used to identify the SYSCON driver instance */ enum { STM32MP_SYSCON_UNKNOWN, - STM32MP_SYSCON_STGEN, + STM32MP_SYSCON_ETZPC, STM32MP_SYSCON_PWR, + STM32MP_SYSCON_STGEN, + STM32MP_SYSCON_SYSCFG, }; /* @@ -95,10 +93,25 @@ enum boot_device { #define TAMP_BOOT_MODE_SHIFT 8 #define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4) #define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0) +#define TAMP_BOOT_FORCED_MASK GENMASK(7, 0) + +enum forced_boot_mode { + BOOT_NORMAL = 0x00, + BOOT_FASTBOOT = 0x01, + BOOT_RECOVERY = 0x02, + BOOT_STM32PROG = 0x03, + BOOT_UMS_MMC0 = 0x10, + BOOT_UMS_MMC1 = 0x11, + BOOT_UMS_MMC2 = 0x12, +}; /* offset used for BSEC driver: misc_read and misc_write */ #define STM32_BSEC_SHADOW_OFFSET 0x0 +#define STM32_BSEC_SHADOW(id) (STM32_BSEC_SHADOW_OFFSET + (id) * 4) #define STM32_BSEC_OTP_OFFSET 0x80000000 +#define STM32_BSEC_OTP(id) (STM32_BSEC_OTP_OFFSET + (id) * 4) + +#define BSEC_OTP_BOARD 59 #endif /* __ASSEMBLY__*/ #endif /* _MACH_STM32_H_ */ diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h new file mode 100644 index 0000000..8130546 --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2019, STMicroelectronics - All Rights Reserved + */ + +#ifndef __STM32MP1_SMC_H__ +#define __STM32MP1_SMC_H__ + +#include <linux/arm-smccc.h> + +/* + * SMC function IDs for STM32 Service queries + * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF + * like this is defined in SMC calling Convention by ARM + * for SiP (silicon Partner) + * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + */ +#define STM32_SMC_VERSION 0x82000000 + +/* Secure Service access from Non-secure */ +#define STM32_SMC_BSEC 0x82001003 + +/* Service for BSEC */ +#define STM32_SMC_READ_SHADOW 0x01 +#define STM32_SMC_PROG_OTP 0x02 +#define STM32_SMC_WRITE_SHADOW 0x03 +#define STM32_SMC_READ_OTP 0x04 +#define STM32_SMC_READ_ALL 0x05 +#define STM32_SMC_WRITE_ALL 0x06 + +/* SMC error codes */ +#define STM32_SMC_OK 0x0 +#define STM32_SMC_NOT_SUPPORTED -1 +#define STM32_SMC_FAILED -2 +#define STM32_SMC_INVALID_PARAMS -3 + +#define stm32_smc_exec(svc, op, data1, data2) \ + stm32_smc(svc, op, data1, data2, NULL) + +#ifdef CONFIG_ARM_SMCCC +static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result) +{ + struct arm_smccc_res res; + + arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res); + + if (res.a0) { + pr_err("%s: Failed to exec in secure mode (err = %ld)\n", + __func__, res.a0); + return -EINVAL; + } + if (result) + *result = (u32)res.a1; + + return 0; +} +#else +static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result) +{ + return 0; +} +#endif + +#endif /* __STM32MP1_SMC_H__ */ diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h index 41d4b40..71a3ba7 100644 --- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h +++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h @@ -3,9 +3,15 @@ * Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved */ -#define CPU_STMP32MP15x 0x500 +/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/ +#define CPU_STM32MP157Cxx 0x05000000 +#define CPU_STM32MP157Axx 0x05000001 +#define CPU_STM32MP153Cxx 0x05000024 +#define CPU_STM32MP153Axx 0x05000025 +#define CPU_STM32MP151Cxx 0x0500002E +#define CPU_STM32MP151Axx 0x0500002F -/* return CPU_STMP32MPxx constants */ +/* return CPU_STMP32MP...Xxx constants */ u32 get_cpu_type(void); #define CPU_REVA 0x1000 @@ -13,3 +19,5 @@ u32 get_cpu_type(void); /* return CPU_REV constants */ u32 get_cpu_rev(void); +/* return boot mode */ +u32 get_bootmode(void); diff --git a/arch/arm/mach-stm32mp/psci.c b/arch/arm/mach-stm32mp/psci.c index 6ed2482..c2dff38 100644 --- a/arch/arm/mach-stm32mp/psci.c +++ b/arch/arm/mach-stm32mp/psci.c @@ -103,7 +103,13 @@ int __secure psci_affinity_info(u32 function_id, u32 target_affinity, int __secure psci_migrate_info_type(u32 function_id) { - /* Trusted OS is either not present or does not require migration */ + /* + * in Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf + * return 2 = Trusted OS is either not present or does not require + * migration, system of this type does not require the caller + * to use the MIGRATE function. + * MIGRATE function calls return NOT_SUPPORTED. + */ return 2; } diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c index 790973e..a3b0d6f 100644 --- a/arch/arm/mach-stm32mp/spl.c +++ b/arch/arm/mach-stm32mp/spl.c @@ -7,13 +7,14 @@ #include <dm.h> #include <spl.h> #include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <linux/libfdt.h> u32 spl_boot_device(void) { u32 boot_mode; - boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >> - TAMP_BOOT_MODE_SHIFT; + boot_mode = get_bootmode(); switch (boot_mode) { case BOOT_FLASH_SD_1: @@ -22,6 +23,21 @@ u32 spl_boot_device(void) case BOOT_FLASH_SD_2: case BOOT_FLASH_EMMC_2: return BOOT_DEVICE_MMC2; + case BOOT_SERIAL_UART_1: + case BOOT_SERIAL_UART_2: + case BOOT_SERIAL_UART_3: + case BOOT_SERIAL_UART_4: + case BOOT_SERIAL_UART_5: + case BOOT_SERIAL_UART_6: + case BOOT_SERIAL_UART_7: + case BOOT_SERIAL_UART_8: + return BOOT_DEVICE_UART; + case BOOT_SERIAL_USB_OTG: + return BOOT_DEVICE_USB; + case BOOT_FLASH_NAND_FMC: + return BOOT_DEVICE_NAND; + case BOOT_FLASH_NOR_QSPI: + return BOOT_DEVICE_SPI; } return BOOT_DEVICE_MMC1; @@ -44,6 +60,21 @@ int spl_boot_partition(const u32 boot_device) } } +#ifdef CONFIG_SPL_DISPLAY_PRINT +void spl_display_print(void) +{ + DECLARE_GLOBAL_DATA_PTR; + const char *model; + + /* same code than show_board_info() but not compiled for SPL + * see CONFIG_DISPLAY_BOARDINFO & common/board_info.c + */ + model = fdt_getprop(gd->fdt_blob, 0, "model", NULL); + if (model) + printf("Model: %s\n", model); +} +#endif + void board_init_f(ulong dummy) { struct udevice *dev; @@ -80,7 +111,7 @@ void board_init_f(ulong dummy) ret = uclass_get_device(UCLASS_RAM, 0, &dev); if (ret) { - debug("DRAM init failed: %d\n", ret); - return; + printf("DRAM init failed: %d\n", ret); + hang(); } } diff --git a/arch/arm/mach-stm32mp/syscon.c b/arch/arm/mach-stm32mp/syscon.c index eb7f435..242f834 100644 --- a/arch/arm/mach-stm32mp/syscon.c +++ b/arch/arm/mach-stm32mp/syscon.c @@ -9,10 +9,11 @@ #include <asm/arch/stm32.h> static const struct udevice_id stm32mp_syscon_ids[] = { - { .compatible = "st,stm32-stgen", - .data = STM32MP_SYSCON_STGEN }, - { .compatible = "st,stm32mp1-pwr", - .data = STM32MP_SYSCON_PWR }, + { .compatible = "st,stm32mp1-etzpc", .data = STM32MP_SYSCON_ETZPC }, + { .compatible = "st,stm32mp1-pwr", .data = STM32MP_SYSCON_PWR }, + { .compatible = "st,stm32-stgen", .data = STM32MP_SYSCON_STGEN }, + { .compatible = "st,stm32mp157-syscfg", + .data = STM32MP_SYSCON_SYSCFG }, { } }; diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 152deb0..8110f23 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -426,10 +426,11 @@ endif config DRAM_ZQ int "sunxi dram zq value" - default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I + default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \ + MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_A83T default 127 if MACH_SUN7I default 14779 if MACH_SUN8I_V3S - default 3881979 if MACH_SUN8I_R40 || MACH_SUN50I_H6 + default 3881979 if MACH_SUNXI_H3_H5 || MACH_SUN8I_R40 || MACH_SUN50I_H6 default 4145117 if MACH_SUN9I default 3881915 if MACH_SUN50I ---help--- @@ -438,6 +439,7 @@ config DRAM_ZQ config DRAM_ODT_EN bool "sunxi dram odt enable" default y if MACH_SUN8I_A23 + default y if MACH_SUNXI_H3_H5 default y if MACH_SUN8I_R40 default y if MACH_SUN50I default y if MACH_SUN50I_H6 diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index b74eaf2..c6dd7b8 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -240,10 +240,12 @@ uint32_t sunxi_get_boot_device(void) boot_source = readb(SPL_ADDR + 0x28); switch (boot_source) { case SUNXI_BOOTED_FROM_MMC0: + case SUNXI_BOOTED_FROM_MMC0_HIGH: return BOOT_DEVICE_MMC1; case SUNXI_BOOTED_FROM_NAND: return BOOT_DEVICE_NAND; case SUNXI_BOOTED_FROM_MMC2: + case SUNXI_BOOTED_FROM_MMC2_HIGH: return BOOT_DEVICE_MMC2; case SUNXI_BOOTED_FROM_SPI: return BOOT_DEVICE_SPI; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c index 1da2727..5da0192 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a33.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c @@ -152,7 +152,7 @@ static void auto_set_timing_para(struct dram_para *para) reg_val &= ~(0xff << 8); reg_val &= ~(0xff << 0); reg_val |= (0x33 << 8); - reg_val |= (0x8 << 0); + reg_val |= (0x10 << 0); writel(reg_val, &mctl_ctl->dramtmg8); /* Set phy interface time */ reg_val = (0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index 665d3cc..3522e6c 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -5,6 +5,7 @@ dtb-$(CONFIG_ARCH_MT7620) += \ linkit-smart-7688.dtb dtb-$(CONFIG_TARGET_AP121) += ap121.dtb dtb-$(CONFIG_TARGET_AP143) += ap143.dtb +dtb-$(CONFIG_TARGET_AP152) += ap152.dtb dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb diff --git a/arch/mips/dts/ap143.dts b/arch/mips/dts/ap143.dts index 82bf637..93a0980 100644 --- a/arch/mips/dts/ap143.dts +++ b/arch/mips/dts/ap143.dts @@ -40,3 +40,8 @@ reg = <0>; }; }; + +&gmac1 { + status = "okay"; + phy-mode = "rgmii"; +}; diff --git a/arch/mips/dts/ap152.dts b/arch/mips/dts/ap152.dts new file mode 100644 index 0000000..1722290 --- /dev/null +++ b/arch/mips/dts/ap152.dts @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com> + */ + +/dts-v1/; +#include "qca956x.dtsi" + +/ { + model = "AP152 Reference Board"; + compatible = "qca,ap152", "qca,qca956x"; + + aliases { + spi0 = &spi0; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&gmac0 { + phy-mode = "sgmii"; + status = "okay"; +}; + +&xtal { + clock-frequency = <25000000>; +}; + +&uart0 { + clock-frequency = <25000000>; + status = "okay"; +}; + +&spi0 { + spi-max-frequency = <25000000>; + status = "okay"; + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-flash"; + memory-map = <0x9f000000 0x01000000>; + spi-max-frequency = <25000000>; + reg = <0>; + }; +}; diff --git a/arch/mips/dts/brcm,bcm6838.dtsi b/arch/mips/dts/brcm,bcm6838.dtsi index b6f9559..c060802 100644 --- a/arch/mips/dts/brcm,bcm6838.dtsi +++ b/arch/mips/dts/brcm,bcm6838.dtsi @@ -98,5 +98,32 @@ status = "disabled"; }; + + gpio_lo: gpio-controller@14e00100 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x14e00100 0x4>, <0x14e0012c 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio_mid0: gpio-controller@14e00104 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x14e00104 0x4>, <0x14e00130 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; + + gpio_mid1: gpio-controller@14e00108 { + compatible = "brcm,bcm6345-gpio"; + reg = <0x14e00108 0x4>, <0x14e00134 0x4>; + gpio-controller; + #gpio-cells = <2>; + + status = "disabled"; + }; }; }; diff --git a/arch/mips/dts/brcm,bcm968380gerg.dts b/arch/mips/dts/brcm,bcm968380gerg.dts index 513045e..98471e3 100644 --- a/arch/mips/dts/brcm,bcm968380gerg.dts +++ b/arch/mips/dts/brcm,bcm968380gerg.dts @@ -38,3 +38,15 @@ label = "bcm968380gerg:green:usb"; }; }; + +&gpio_lo { + status = "okay"; +}; + +&gpio_mid0 { + status = "okay"; +}; + +&gpio_mid1 { + status = "okay"; +}; diff --git a/arch/mips/dts/gardena-smart-gateway-mt7688.dts b/arch/mips/dts/gardena-smart-gateway-mt7688.dts index 2f2cfdd..eedde89 100644 --- a/arch/mips/dts/gardena-smart-gateway-mt7688.dts +++ b/arch/mips/dts/gardena-smart-gateway-mt7688.dts @@ -10,7 +10,7 @@ / { compatible = "gardena,smart-gateway-mt7688", "ralink,mt7628a-soc"; - model = "Gardena smart-Gateway-MT7688"; + model = "GARDENA smart Gateway (MT7688)"; aliases { serial0 = &uart0; diff --git a/arch/mips/dts/jr2_pcb110.dts b/arch/mips/dts/jr2_pcb110.dts index 1e12397..6562221 100644 --- a/arch/mips/dts/jr2_pcb110.dts +++ b/arch/mips/dts/jr2_pcb110.dts @@ -5,6 +5,7 @@ /dts-v1/; #include "mscc,jr2.dtsi" +#include <dt-bindings/mscc/jr2_data.h> / { model = "Jaguar2 Cu8-Sfp16 PCB110 Reference Board"; @@ -72,3 +73,78 @@ sgpio-ports = <0x3f00ffff>; gpio-ranges = <&sgpio2 0 0 96>; }; + +&mdio1 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + phy1: ethernet-phy@1 { + reg = <1>; + }; + phy2: ethernet-phy@2 { + reg = <2>; + }; + phy3: ethernet-phy@3 { + reg = <3>; + }; + phy4: ethernet-phy@4 { + reg = <4>; + }; + phy5: ethernet-phy@5 { + reg = <5>; + }; + phy6: ethernet-phy@6 { + reg = <6>; + }; + phy7: ethernet-phy@7 { + reg = <7>; + }; +}; + +&switch { + ethernet-ports { + + port0: port@0 { + reg = <0>; + phy-handle = <&phy0>; + phys = <&serdes_hsio 0 SERDES1G(1) PHY_MODE_SGMII>; + }; + port1: port@1 { + reg = <1>; + phy-handle = <&phy1>; + phys = <&serdes_hsio 1 SERDES1G(2) PHY_MODE_SGMII>; + }; + port2: port@2 { + reg = <2>; + phy-handle = <&phy2>; + phys = <&serdes_hsio 2 SERDES1G(3) PHY_MODE_SGMII>; + }; + port3: port@3 { + reg = <3>; + phy-handle = <&phy3>; + phys = <&serdes_hsio 3 SERDES1G(4) PHY_MODE_SGMII>; + }; + port4: port@4 { + reg = <4>; + phy-handle = <&phy4>; + phys = <&serdes_hsio 4 SERDES1G(5) PHY_MODE_SGMII>; + }; + port5: port@5 { + reg = <5>; + phy-handle = <&phy5>; + phys = <&serdes_hsio 5 SERDES1G(6) PHY_MODE_SGMII>; + }; + port6: port@6 { + reg = <6>; + phy-handle = <&phy6>; + phys = <&serdes_hsio 6 SERDES1G(7) PHY_MODE_SGMII>; + }; + port7: port@7 { + reg = <7>; + phy-handle = <&phy7>; + phys = <&serdes_hsio 7 SERDES1G(8) PHY_MODE_SGMII>; + }; + }; +}; diff --git a/arch/mips/dts/jr2_pcb111.dts b/arch/mips/dts/jr2_pcb111.dts index fcd8455..74305a8 100644 --- a/arch/mips/dts/jr2_pcb111.dts +++ b/arch/mips/dts/jr2_pcb111.dts @@ -5,6 +5,7 @@ /dts-v1/; #include "mscc,jr2.dtsi" +#include <dt-bindings/mscc/jr2_data.h> / { model = "Jaguar2 Cu48 PCB111 Reference Board"; @@ -72,3 +73,402 @@ sgpio-ports = <0xff000000>; gpio-ranges = <&sgpio2 0 0 96>; }; + +&mdio1 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + phy1: ethernet-phy@1 { + reg = <1>; + }; + phy2: ethernet-phy@2 { + reg = <2>; + }; + phy3: ethernet-phy@3 { + reg = <3>; + }; + phy4: ethernet-phy@4 { + reg = <4>; + }; + phy5: ethernet-phy@5 { + reg = <5>; + }; + phy6: ethernet-phy@6 { + reg = <6>; + }; + phy7: ethernet-phy@7 { + reg = <7>; + }; + phy8: ethernet-phy@8 { + reg = <8>; + }; + phy9: ethernet-phy@9 { + reg = <9>; + }; + phy10: ethernet-phy@10 { + reg = <10>; + }; + phy11: ethernet-phy@11 { + reg = <11>; + }; + phy12: ethernet-phy@12 { + reg = <12>; + }; + phy13: ethernet-phy@13 { + reg = <13>; + }; + phy14: ethernet-phy@14 { + reg = <14>; + }; + phy15: ethernet-phy@15 { + reg = <15>; + }; + phy16: ethernet-phy@16 { + reg = <16>; + }; + phy17: ethernet-phy@17 { + reg = <17>; + }; + phy18: ethernet-phy@18 { + reg = <18>; + }; + phy19: ethernet-phy@19 { + reg = <19>; + }; + phy20: ethernet-phy@20 { + reg = <20>; + }; + phy21: ethernet-phy@21 { + reg = <21>; + }; + phy22: ethernet-phy@22 { + reg = <22>; + }; + phy23: ethernet-phy@23 { + reg = <23>; + }; +}; + +&mdio2 { + status = "okay"; + + phy24: ethernet-phy@24 { + reg = <0>; + }; + phy25: ethernet-phy@25 { + reg = <1>; + }; + phy26: ethernet-phy@26 { + reg = <2>; + }; + phy27: ethernet-phy@27 { + reg = <3>; + }; + phy28: ethernet-phy@28 { + reg = <4>; + }; + phy29: ethernet-phy@29 { + reg = <5>; + }; + phy30: ethernet-phy@30 { + reg = <6>; + }; + phy31: ethernet-phy@31 { + reg = <7>; + }; + phy32: ethernet-phy@32 { + reg = <8>; + }; + phy33: ethernet-phy@33 { + reg = <9>; + }; + phy34: ethernet-phy@34 { + reg = <10>; + }; + phy35: ethernet-phy@35 { + reg = <11>; + }; + phy36: ethernet-phy@36 { + reg = <12>; + }; + phy37: ethernet-phy@37 { + reg = <13>; + }; + phy38: ethernet-phy@38 { + reg = <14>; + }; + phy39: ethernet-phy@39 { + reg = <15>; + }; + phy40: ethernet-phy@40 { + reg = <16>; + }; + phy41: ethernet-phy@41 { + reg = <17>; + }; + phy42: ethernet-phy@42 { + reg = <18>; + }; + phy43: ethernet-phy@43 { + reg = <19>; + }; + phy44: ethernet-phy@44 { + reg = <20>; + }; + phy45: ethernet-phy@45 { + reg = <21>; + }; + phy46: ethernet-phy@46 { + reg = <22>; + }; + phy47: ethernet-phy@47 { + reg = <23>; + }; +}; + +&switch { + ethernet-ports { + port0: port@0 { + reg = <0>; + phy-handle = <&phy0>; + phys = <&serdes_hsio 0 SERDES6G(4) PHY_MODE_QSGMII>; + }; + port1: port@1 { + reg = <1>; + phy-handle = <&phy1>; + phys = <&serdes_hsio 1 0xff PHY_MODE_QSGMII>; + }; + port2: port@2 { + reg = <2>; + phy-handle = <&phy2>; + phys = <&serdes_hsio 2 0xff PHY_MODE_QSGMII>; + }; + port3: port@3 { + reg = <3>; + phy-handle = <&phy3>; + phys = <&serdes_hsio 3 0xff PHY_MODE_QSGMII>; + }; + port4: port@4 { + reg = <4>; + phy-handle = <&phy4>; + phys = <&serdes_hsio 4 SERDES6G(5) PHY_MODE_QSGMII>; + }; + port5: port@5 { + reg = <5>; + phy-handle = <&phy5>; + phys = <&serdes_hsio 5 0xff PHY_MODE_QSGMII>; + }; + port6: port@6 { + reg = <6>; + phy-handle = <&phy6>; + phys = <&serdes_hsio 6 0xff PHY_MODE_QSGMII>; + }; + port7: port@7 { + reg = <7>; + phy-handle = <&phy7>; + phys = <&serdes_hsio 7 0xff PHY_MODE_QSGMII>; + }; + port8: port@8 { + reg = <8>; + phy-handle = <&phy8>; + phys = <&serdes_hsio 8 SERDES6G(6) PHY_MODE_QSGMII>; + }; + port9: port@9 { + reg = <9>; + phy-handle = <&phy9>; + phys = <&serdes_hsio 9 0xff PHY_MODE_QSGMII>; + }; + port10: port@10 { + reg = <10>; + phy-handle = <&phy10>; + phys = <&serdes_hsio 10 0xff PHY_MODE_QSGMII>; + }; + port11: port@11 { + reg = <11>; + phy-handle = <&phy11>; + phys = <&serdes_hsio 11 0xff PHY_MODE_QSGMII>; + }; + port12: port@12 { + reg = <12>; + phy-handle = <&phy12>; + phys = <&serdes_hsio 12 SERDES6G(7) PHY_MODE_QSGMII>; + }; + port13: port@13 { + reg = <13>; + phy-handle = <&phy13>; + phys = <&serdes_hsio 13 0xff PHY_MODE_QSGMII>; + }; + port14: port@14 { + reg = <14>; + phy-handle = <&phy14>; + phys = <&serdes_hsio 14 0xff PHY_MODE_QSGMII>; + }; + port15: port@15 { + reg = <15>; + phy-handle = <&phy15>; + phys = <&serdes_hsio 15 0xff PHY_MODE_QSGMII>; + }; + port16: port@16 { + reg = <16>; + phy-handle = <&phy16>; + phys = <&serdes_hsio 16 SERDES6G(8) PHY_MODE_QSGMII>; + }; + port17: port@17 { + reg = <17>; + phy-handle = <&phy17>; + phys = <&serdes_hsio 17 0xff PHY_MODE_QSGMII>; + }; + port18: port@18 { + reg = <18>; + phy-handle = <&phy18>; + phys = <&serdes_hsio 18 0xff PHY_MODE_QSGMII>; + }; + port19: port@19 { + reg = <19>; + phy-handle = <&phy19>; + phys = <&serdes_hsio 19 0xff PHY_MODE_QSGMII>; + }; + port20: port@20 { + reg = <20>; + phy-handle = <&phy20>; + phys = <&serdes_hsio 20 SERDES6G(9) PHY_MODE_QSGMII>; + }; + port21: port@21 { + reg = <21>; + phy-handle = <&phy21>; + phys = <&serdes_hsio 21 0xff PHY_MODE_QSGMII>; + }; + port22: port@22 { + reg = <22>; + phy-handle = <&phy22>; + phys = <&serdes_hsio 22 0xff PHY_MODE_QSGMII>; + }; + port23: port@23 { + reg = <23>; + phy-handle = <&phy23>; + phys = <&serdes_hsio 23 0xff PHY_MODE_QSGMII>; + }; + port24: port@24 { + reg = <24>; + phy-handle = <&phy24>; + phys = <&serdes_hsio 24 SERDES6G(10) PHY_MODE_QSGMII>; + }; + port25: port@25 { + reg = <25>; + phy-handle = <&phy25>; + phys = <&serdes_hsio 25 0xff PHY_MODE_QSGMII>; + }; + port26: port@26 { + reg = <26>; + phy-handle = <&phy26>; + phys = <&serdes_hsio 26 0xff PHY_MODE_QSGMII>; + }; + port27: port@27 { + reg = <27>; + phy-handle = <&phy27>; + phys = <&serdes_hsio 27 0xff PHY_MODE_QSGMII>; + }; + port28: port@28 { + reg = <28>; + phy-handle = <&phy28>; + phys = <&serdes_hsio 28 SERDES6G(11) PHY_MODE_QSGMII>; + }; + port29: port@29 { + reg = <29>; + phy-handle = <&phy29>; + phys = <&serdes_hsio 29 0xff PHY_MODE_QSGMII>; + }; + port30: port@30 { + reg = <30>; + phy-handle = <&phy30>; + phys = <&serdes_hsio 30 0xff PHY_MODE_QSGMII>; + }; + port31: port@31 { + reg = <31>; + phy-handle = <&phy31>; + phys = <&serdes_hsio 31 0xff PHY_MODE_QSGMII>; + }; + port32: port@32 { + reg = <32>; + phy-handle = <&phy32>; + phys = <&serdes_hsio 32 SERDES6G(12) PHY_MODE_QSGMII>; + }; + port33: port@33 { + reg = <33>; + phy-handle = <&phy33>; + phys = <&serdes_hsio 33 0xff PHY_MODE_QSGMII>; + }; + port34: port@34 { + reg = <34>; + phy-handle = <&phy34>; + phys = <&serdes_hsio 34 0xff PHY_MODE_QSGMII>; + }; + port35: port@35 { + reg = <35>; + phy-handle = <&phy35>; + phys = <&serdes_hsio 35 0xff PHY_MODE_QSGMII>; + }; + port36: port@36 { + reg = <36>; + phy-handle = <&phy36>; + phys = <&serdes_hsio 36 SERDES6G(13) PHY_MODE_QSGMII>; + }; + port37: port@37 { + reg = <37>; + phy-handle = <&phy37>; + phys = <&serdes_hsio 37 0xff PHY_MODE_QSGMII>; + }; + port38: port@38 { + reg = <38>; + phy-handle = <&phy38>; + phys = <&serdes_hsio 38 0xff PHY_MODE_QSGMII>; + }; + port39: port@39 { + reg = <39>; + phy-handle = <&phy39>; + phys = <&serdes_hsio 39 0xff PHY_MODE_QSGMII>; + }; + port40: port@40 { + reg = <40>; + phy-handle = <&phy40>; + phys = <&serdes_hsio 40 SERDES6G(14) PHY_MODE_QSGMII>; + }; + port41: port@41 { + reg = <41>; + phy-handle = <&phy41>; + phys = <&serdes_hsio 41 0xff PHY_MODE_QSGMII>; + }; + port42: port@42 { + reg = <42>; + phy-handle = <&phy42>; + phys = <&serdes_hsio 42 0xff PHY_MODE_QSGMII>; + }; + port43: port@43 { + reg = <43>; + phy-handle = <&phy43>; + phys = <&serdes_hsio 43 0xff PHY_MODE_QSGMII>; + }; + port44: port@44 { + reg = <44>; + phy-handle = <&phy44>; + phys = <&serdes_hsio 44 SERDES6G(15) PHY_MODE_QSGMII>; + }; + port45: port@45 { + reg = <45>; + phy-handle = <&phy45>; + phys = <&serdes_hsio 45 0xff PHY_MODE_QSGMII>; + }; + port46: port@46 { + reg = <46>; + phy-handle = <&phy46>; + phys = <&serdes_hsio 46 0xff PHY_MODE_QSGMII>; + }; + port47: port@47 { + reg = <47>; + phy-handle = <&phy47>; + phys = <&serdes_hsio 47 0xff PHY_MODE_QSGMII>; + }; + }; +}; diff --git a/arch/mips/dts/mscc,jr2.dtsi b/arch/mips/dts/mscc,jr2.dtsi index 0900926..7f5a96f 100644 --- a/arch/mips/dts/mscc,jr2.dtsi +++ b/arch/mips/dts/mscc,jr2.dtsi @@ -183,5 +183,121 @@ gpio-bank-name = "sgpio2_"; sgpio-clock = <0x14>; }; + + switch: switch@1010000 { + compatible = "mscc,vsc7454-switch"; + reg = <0x01040000 0x0100>, // VTSS_TO_DEV_0 + <0x01050000 0x0100>, // VTSS_TO_DEV_1 + <0x01060000 0x0100>, // VTSS_TO_DEV_2 + <0x01070000 0x0100>, // VTSS_TO_DEV_3 + <0x01080000 0x0100>, // VTSS_TO_DEV_4 + <0x01090000 0x0100>, // VTSS_TO_DEV_5 + <0x010a0000 0x0100>, // VTSS_TO_DEV_6 + <0x010b0000 0x0100>, // VTSS_TO_DEV_7 + <0x010c0000 0x0100>, // VTSS_TO_DEV_8 + <0x010d0000 0x0100>, // VTSS_TO_DEV_9 + <0x010e0000 0x0100>, // VTSS_TO_DEV_10 + <0x010f0000 0x0100>, // VTSS_TO_DEV_11 + <0x01100000 0x0100>, // VTSS_TO_DEV_12 + <0x01110000 0x0100>, // VTSS_TO_DEV_13 + <0x01120000 0x0100>, // VTSS_TO_DEV_14 + <0x01130000 0x0100>, // VTSS_TO_DEV_15 + <0x01140000 0x0100>, // VTSS_TO_DEV_16 + <0x01150000 0x0100>, // VTSS_TO_DEV_17 + <0x01160000 0x0100>, // VTSS_TO_DEV_18 + <0x01170000 0x0100>, // VTSS_TO_DEV_19 + <0x01180000 0x0100>, // VTSS_TO_DEV_20 + <0x01190000 0x0100>, // VTSS_TO_DEV_21 + <0x011a0000 0x0100>, // VTSS_TO_DEV_22 + <0x011b0000 0x0100>, // VTSS_TO_DEV_23 + <0x011c0000 0x0100>, // VTSS_TO_DEV_24 + <0x011d0000 0x0100>, // VTSS_TO_DEV_25 + <0x011e0000 0x0100>, // VTSS_TO_DEV_26 + <0x011f0000 0x0100>, // VTSS_TO_DEV_27 + <0x01200000 0x0100>, // VTSS_TO_DEV_28 + <0x01210000 0x0100>, // VTSS_TO_DEV_29 + <0x01220000 0x0100>, // VTSS_TO_DEV_30 + <0x01230000 0x0100>, // VTSS_TO_DEV_31 + <0x01240000 0x0100>, // VTSS_TO_DEV_32 + <0x01250000 0x0100>, // VTSS_TO_DEV_33 + <0x01260000 0x0100>, // VTSS_TO_DEV_34 + <0x01270000 0x0100>, // VTSS_TO_DEV_35 + <0x01280000 0x0100>, // VTSS_TO_DEV_36 + <0x01290000 0x0100>, // VTSS_TO_DEV_37 + <0x012a0000 0x0100>, // VTSS_TO_DEV_38 + <0x012b0000 0x0100>, // VTSS_TO_DEV_39 + <0x012c0000 0x0100>, // VTSS_TO_DEV_40 + <0x012d0000 0x0100>, // VTSS_TO_DEV_41 + <0x012e0000 0x0100>, // VTSS_TO_DEV_42 + <0x012f0000 0x0100>, // VTSS_TO_DEV_43 + <0x01300000 0x0100>, // VTSS_TO_DEV_44 + <0x01310000 0x0100>, // VTSS_TO_DEV_45 + <0x01320000 0x0100>, // VTSS_TO_DEV_46 + <0x01330000 0x0100>, // VTSS_TO_DEV_47 + <0x01f00000 0x100000>, // ANA_AC + <0x01d00000 0x100000>, // ANA_CL + <0x01e00000 0x100000>, // ANA_L2 + <0x01410000 0x10000>, // ASM + <0x01460000 0x10000>, // HSIO + <0x01420000 0x00000>, // LRN + <0x017d0000 0x10000>, // QFWD + <0x01020000 0x20000>, // QS + <0x017e0000 0x10000>, // QSYS + <0x01b00000 0x80000>; // REW + reg-names = "port0", "port1", "port2", "port3", "port4", + "port5", "port6", "port7", "port8", "port9", + "port10", "port11", "port12", "port13", + "port14", "port15", "port16", "port17", + "port18", "port19", "port20", "port21", + "port22", "port23", "port24", "port25", + "port26", "port27", "port28", "port29", + "port30", "port31", "port32", "port33", + "port34", "port35", "port36", "port37", + "port38", "port39", "port40", "port41", + "port42", "port43", "port44", "port45", + "port46", "port47", "ana_ac", "ana_cl", + "ana_l2", "asm", "hsio", "lrn", "qfwd", + "qs", "qsys", "rew"; + status = "okay"; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + mdio0: mdio@010100c8 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x010100c8 0x24>; + status = "disabled"; + }; + + mdio1: mdio@010100ec { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x010100ec 0x24>; + status = "disabled"; + }; + + mdio2: mdio@01010110 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x01010110 0x24>; + status = "disabled"; + }; + + hsio: syscon@10d0000 { + compatible = "mscc,jr2-hsio", "syscon", "simple-mfd"; + reg = <0x10d0000 0x10000>; + + serdes_hsio: serdes_hsio { + compatible = "mscc,vsc7454-serdes"; + #phy-cells = <3>; + }; + }; }; }; diff --git a/arch/mips/dts/mscc,servalt.dtsi b/arch/mips/dts/mscc,servalt.dtsi index 4beb7a3..45ae2de 100644 --- a/arch/mips/dts/mscc,servalt.dtsi +++ b/arch/mips/dts/mscc,servalt.dtsi @@ -145,5 +145,45 @@ #gpio-cells = <2>; gpio-ranges = <&sgpio 0 0 128>; }; + + switch: switch@1010000 { + compatible = "mscc,vsc7437-switch"; + reg = <0x01030000 0x0100>, // VTSS_TO_DEV_0 + <0x01040000 0x0100>, // VTSS_TO_DEV_1 + <0x01f00000 0x100000>, // ANA_AC + <0x01d00000 0x100000>, // ANA_CL + <0x01e00000 0x100000>, // ANA_L2 + <0x01120000 0x10000>, // ASM + <0x01130000 0x00000>, // LRN + <0x017d0000 0x10000>, // QFWD + <0x01020000 0x20000>, // QS + <0x017e0000 0x10000>, // QSYS + <0x01b00000 0x80000>; // REW + reg-names = "port0", "port1", + "ana_ac", "ana_cl", "ana_l2", "asm", "lrn", + "qfwd", "qs", "qsys", "rew"; + status = "okay"; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + mdio0: mdio@010100c4 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x010100c4 0x24>; + status = "disabled"; + }; + + mdio1: mdio@010100e8 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "mscc,jr2-miim"; + reg = <0x010100e8 0x24>; + status = "disabled"; + }; }; }; diff --git a/arch/mips/dts/qca953x.dtsi b/arch/mips/dts/qca953x.dtsi index ba29ea2..90d34dd 100644 --- a/arch/mips/dts/qca953x.dtsi +++ b/arch/mips/dts/qca953x.dtsi @@ -65,6 +65,37 @@ status = "disabled"; }; + + gmac0: eth0@0x19000000 { + compatible = "qca,ag953x-mac"; + reg = <0x19000000 0x200>; + phy = <&phy4>; + phy-mode = "rmii"; + + status = "disabled"; + }; + + gmac1: eth1@0x1a000000 { + compatible = "qca,ag953x-mac"; + reg = <0x1a000000 0x200>; + phy = <&phy0>; + phy-mode = "rgmii"; + + status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "rmii"; + }; + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rmii"; + }; + }; + }; }; spi0: spi@1f000000 { diff --git a/arch/mips/dts/qca956x.dtsi b/arch/mips/dts/qca956x.dtsi new file mode 100644 index 0000000..6cb360b --- /dev/null +++ b/arch/mips/dts/qca956x.dtsi @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com> + */ + +#include "skeleton.dtsi" + +/ { + compatible = "qca,qca956x"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips74Kc"; + reg = <0>; + }; + }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + xtal: xtal { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-output-names = "xtal"; + }; + }; + + ahb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + apb { + compatible = "simple-bus"; + ranges; + + #address-cells = <1>; + #size-cells = <1>; + + uart0: uart@18020000 { + compatible = "ns16550"; + reg = <0x18020000 0x20>; + reg-shift = <2>; + + status = "disabled"; + }; + + gmac0: eth@0x19000000 { + compatible = "qca,ag956x-mac"; + reg = <0x19000000 0x200>; + phy = <&phy0>; + phy-mode = "sgmii"; + + status = "disabled"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + }; + + spi0: spi@1f000000 { + compatible = "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; diff --git a/arch/mips/dts/serval2_pcb112.dts b/arch/mips/dts/serval2_pcb112.dts index 2921c44..5777a77 100644 --- a/arch/mips/dts/serval2_pcb112.dts +++ b/arch/mips/dts/serval2_pcb112.dts @@ -5,6 +5,7 @@ /dts-v1/; #include "mscc,jr2.dtsi" +#include <dt-bindings/mscc/jr2_data.h> / { model = "Serval2 NID PCB112 Reference Board"; @@ -58,3 +59,46 @@ status = "okay"; sgpio-ports = <0x3fe0ffff>; }; + +&mdio0 { + status = "okay"; + + phy16: ethernet-phy@16 { + reg = <16>; + }; + phy17: ethernet-phy@17 { + reg = <17>; + }; + phy18: ethernet-phy@18 { + reg = <18>; + }; + phy19: ethernet-phy@19 { + reg = <19>; + }; +}; + +&switch { + ethernet-ports { + + port0: port@0 { + reg = <24>; + phy-handle = <&phy16>; + phys = <&serdes_hsio 24 SERDES6G(0) PHY_MODE_SGMII>; + }; + port1: port@1 { + reg = <25>; + phy-handle = <&phy17>; + phys = <&serdes_hsio 25 SERDES6G(1) PHY_MODE_SGMII>; + }; + port2: port@2 { + reg = <26>; + phy-handle = <&phy18>; + phys = <&serdes_hsio 26 SERDES6G(2) PHY_MODE_SGMII>; + }; + port3: port@3 { + reg = <27>; + phy-handle = <&phy19>; + phys = <&serdes_hsio 27 SERDES6G(3) PHY_MODE_SGMII>; + }; + }; +}; diff --git a/arch/mips/dts/servalt_pcb116.dts b/arch/mips/dts/servalt_pcb116.dts index 4de3e25..313b099 100644 --- a/arch/mips/dts/servalt_pcb116.dts +++ b/arch/mips/dts/servalt_pcb116.dts @@ -54,3 +54,28 @@ status = "okay"; sgpio-ports = <0x0000fe7f>; }; + +&mdio0 { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + phy1: ethernet-phy@1 { + reg = <1>; + }; +}; + +&switch { + ethernet-ports { + + port0: port@0 { + reg = <0>; + phy-handle = <&phy0>; + }; + port1: port@1 { + reg = <1>; + phy-handle = <&phy1>; + }; + }; +}; diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c index deca518..35152cb 100644 --- a/arch/mips/lib/bootm.c +++ b/arch/mips/lib/bootm.c @@ -215,23 +215,6 @@ static void linux_env_legacy(bootm_headers_t *images) } } -static int boot_reloc_ramdisk(bootm_headers_t *images) -{ - ulong rd_len = images->rd_end - images->rd_start; - - /* - * In case of legacy uImage's, relocation of ramdisk is already done - * by do_bootm_states() and should not repeated in 'bootm prep'. - */ - if (images->state & BOOTM_STATE_RAMDISK) { - debug("## Ramdisk already relocated\n"); - return 0; - } - - return boot_ramdisk_high(&images->lmb, images->rd_start, - rd_len, &images->initrd_start, &images->initrd_end); -} - static int boot_reloc_fdt(bootm_headers_t *images) { /* @@ -270,8 +253,6 @@ static int boot_setup_fdt(bootm_headers_t *images) static void boot_prep_linux(bootm_headers_t *images) { - boot_reloc_ramdisk(images); - if (CONFIG_IS_ENABLED(MIPS_BOOT_FDT) && images->ft_len) { boot_reloc_fdt(images); boot_setup_fdt(images); diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index bc86f59..bdb23b5 100644 --- a/arch/mips/mach-ath79/Kconfig +++ b/arch/mips/mach-ath79/Kconfig @@ -33,6 +33,15 @@ config SOC_QCA953X help This supports QCA/Atheros qca953x family SOCs. +config SOC_QCA956X + bool + select MIPS_TUNE_74KC + select SUPPORTS_BIG_ENDIAN + select SUPPORTS_CPU_MIPS32_R1 + select SUPPORTS_CPU_MIPS32_R2 + help + This supports QCA/Atheros qca956x family SOCs. + choice prompt "Board select" @@ -44,6 +53,10 @@ config TARGET_AP143 bool "AP143 Reference Board" select SOC_QCA953X +config TARGET_AP152 + bool "AP152 Reference Board" + select SOC_QCA956X + config BOARD_TPLINK_WDR4300 bool "TP-Link WDR4300 Board" select SOC_AR934X @@ -52,6 +65,7 @@ endchoice source "board/qca/ap121/Kconfig" source "board/qca/ap143/Kconfig" +source "board/qca/ap152/Kconfig" source "board/tplink/wdr4300/Kconfig" endmenu diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile index 7aa40c6..fbd40c0 100644 --- a/arch/mips/mach-ath79/Makefile +++ b/arch/mips/mach-ath79/Makefile @@ -7,3 +7,4 @@ obj-y += dram.o obj-$(CONFIG_SOC_AR933X) += ar933x/ obj-$(CONFIG_SOC_AR934X) += ar934x/ obj-$(CONFIG_SOC_QCA953X) += qca953x/ +obj-$(CONFIG_SOC_QCA956X) += qca956x/ diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h index 5d371bb..5888f6e 100644 --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -194,6 +194,9 @@ #define QCA956X_WMAC_BASE \ (AR71XX_APB_BASE + 0x00100000) #define QCA956X_WMAC_SIZE 0x20000 +#define QCA956X_RTC_BASE \ + (AR71XX_APB_BASE + 0x00107000) +#define QCA956X_RTC_SIZE 0x1000 #define QCA956X_EHCI0_BASE 0x1b000000 #define QCA956X_EHCI1_BASE 0x1b400000 #define QCA956X_EHCI_SIZE 0x200 @@ -201,6 +204,10 @@ (AR71XX_APB_BASE + 0x00070000) #define QCA956X_GMAC_SIZE 0x64 +#define QCA956X_SRIF_BASE \ + (AR71XX_APB_BASE + 0x00116000) +#define QCA956X_SRIF_SIZE 0x1000 + /* * DDR_CTRL block */ @@ -278,6 +285,18 @@ #define QCA953X_DDR_REG_CTL_CONF 0x108 #define QCA953X_DDR_REG_CONFIG3 0x15c +#define QCA956X_DDR_REG_TAP_CTRL2 0x24 +#define QCA956X_DDR_REG_TAP_CTRL3 0x28 +#define QCA956X_DDR_REG_DDR2_CONFIG 0xb8 +#define QCA956X_DDR_REG_DDR2_EMR2 0xbc +#define QCA956X_DDR_REG_DDR2_EMR3 0xc0 +#define QCA956X_DDR_REG_BURST 0xc4 +#define QCA956X_DDR_REG_BURST2 0xc8 +#define QCA956X_DDR_REG_TIMEOUT_MAX 0xcc +#define QCA956X_DDR_REG_FSM_WAIT_CTRL 0xe4 +#define QCA956X_DDR_REG_CTL_CONF 0x108 +#define QCA956X_DDR_REG_DDR3_CONFIG 0x15c + /* * PLL block */ @@ -519,6 +538,13 @@ #define QCA956X_PLL_DDR_CONFIG_REG 0x08 #define QCA956X_PLL_DDR_CONFIG1_REG 0x0c #define QCA956X_PLL_CLK_CTRL_REG 0x10 +#define QCA956X_PLL_SWITCH_CLK_CTRL_REG 0x28 +#define QCA956X_PLL_ETH_XMII_CTRL_REG 0x30 +#define QCA956X_PLL_DDR_DIT_FRAC_REG 0x38 +#define QCA956X_PLL_DDR_DIT2_FRAC_REG 0x3c +#define QCA956X_PLL_CPU_DIT_FRAC_REG 0x40 +#define QCA956X_PLL_CPU_DIT2_FRAC_REG 0x44 +#define QCA956X_PLL_ETH_SGMII_SERDES_REG 0x4c #define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT 12 #define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f @@ -528,7 +554,7 @@ #define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT 0 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK 0x1f #define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT 5 -#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x3fff +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x1fff #define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT 18 #define QCA956X_PLL_CPU_CONFIG1_NINT_MASK 0x1ff @@ -540,7 +566,7 @@ #define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT 0 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK 0x1f #define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT 5 -#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x3fff +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x1fff #define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT 18 #define QCA956X_PLL_DDR_CONFIG1_NINT_MASK 0x1ff @@ -756,6 +782,17 @@ #define QCA955X_RESET_MBOX BIT(1) #define QCA955X_RESET_I2S BIT(0) +#define QCA956X_RESET_EXTERNAL BIT(28) +#define QCA956X_RESET_FULL_CHIP BIT(24) +#define QCA956X_RESET_GE1_MDIO BIT(23) /* Reserved in datasheet */ +#define QCA956X_RESET_GE0_MDIO BIT(22) +#define QCA956X_RESET_GE1_MAC BIT(13) /* Reserved in datasheet */ +#define QCA956X_RESET_SGMII_ASSERT BIT(12) +#define QCA956X_RESET_GE0_MAC BIT(9) +#define QCA956X_RESET_SGMII BIT(8) +#define QCA956X_RESET_SGMII_ANALOG BIT(2) +#define QCA956X_RESET_SWITCH BIT(0) + #define AR933X_BOOTSTRAP_MDIO_GPIO_EN BIT(18) #define AR933X_BOOTSTRAP_DDR2 BIT(13) #define AR933X_BOOTSTRAP_EEPBUSY BIT(4) @@ -1099,8 +1136,12 @@ #define QCA953X_GPIO_IN_MUX_UART0_SIN 9 #define QCA953X_GPIO_IN_MUX_SPI_DATA_IN 8 +#define QCA956X_GPIO(x) BIT(x) +#define QCA956X_GPIO_MUX_MASK(x) (0xff << (x)) #define QCA956X_GPIO_OUT_MUX_GE0_MDO 32 #define QCA956X_GPIO_OUT_MUX_GE0_MDC 33 +#define QCA956X_GPIO_IN_MUX_UART0_SIN 0x12 +#define QCA956X_GPIO_OUT_MUX_UART0_SOUT 0x16 #define AR71XX_GPIO_COUNT 16 #define AR7240_GPIO_COUNT 18 @@ -1179,6 +1220,25 @@ #define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT 13 #define QCA953X_SRIF_DPLL2_OUTDIV_MASK 0x7 +#define QCA956X_SRIF_BB_DPLL1_REG 0x180 +#define QCA956X_SRIF_BB_DPLL2_REG 0x184 +#define QCA956X_SRIF_BB_DPLL3_REG 0x188 + +#define QCA956X_SRIF_CPU_DPLL1_REG 0xf00 +#define QCA956X_SRIF_CPU_DPLL2_REG 0xf04 +#define QCA956X_SRIF_CPU_DPLL3_REG 0xf08 + +#define QCA956X_SRIF_DDR_DPLL1_REG 0xec0 +#define QCA956X_SRIF_DDR_DPLL2_REG 0xec4 +#define QCA956X_SRIF_DDR_DPLL3_REG 0xec8 + +#define QCA956X_SRIF_PCIE_DPLL1_REG 0xc80 +#define QCA956X_SRIF_PCIE_DPLL2_REG 0xc84 +#define QCA956X_SRIF_PCIE_DPLL3_REG 0xc88 + +#define QCA956X_SRIF_PMU1_REG 0xcc0 +#define QCA956X_SRIF_PMU2_REG 0xcc4 + /* * MII_CTRL block */ @@ -1261,4 +1321,17 @@ #define QCA955X_ETH_CFG_RGMII_EN BIT(0) #define QCA955X_ETH_CFG_GE0_SGMII BIT(6) +/* + * QCA956X GMAC Interface + */ + +#define QCA956X_GMAC_REG_ETH_CFG 0x00 +#define QCA956X_GMAC_REG_SGMII_RESET 0x14 +#define QCA956X_GMAC_REG_SGMII_SERDES 0x18 +#define QCA956X_GMAC_REG_MR_AN_CTRL 0x1c +#define QCA956X_GMAC_REG_SGMII_CONFIG 0x34 +#define QCA956X_GMAC_REG_SGMII_DEBUG 0x58 + +#define QCA956X_ETH_CFG_GE0_SGMII BIT(6) + #endif /* __ASM_AR71XX_H */ diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h index 5de7a43..0fde507 100644 --- a/arch/mips/mach-ath79/include/mach/ath79.h +++ b/arch/mips/mach-ath79/include/mach/ath79.h @@ -2,6 +2,7 @@ /* * Atheros AR71XX/AR724X/AR913X common definitions * + * Copyright (C) 2018-2019 Rosy Song <rosysong@rosinson.com> * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> @@ -146,4 +147,6 @@ int ath79_usb_reset(void); void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz); void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz); +void qca956x_pll_init(void); +void qca956x_ddr_init(void); #endif /* __ASM_MACH_ATH79_H */ diff --git a/arch/mips/mach-ath79/qca956x/Makefile b/arch/mips/mach-ath79/qca956x/Makefile new file mode 100644 index 0000000..3f5fc03 --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += cpu.o +obj-y += clk.o +obj-y += ddr.o qca956x-ddr-tap.o diff --git a/arch/mips/mach-ath79/qca956x/clk.c b/arch/mips/mach-ath79/qca956x/clk.c new file mode 100644 index 0000000..33a44cf --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/clk.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/addrspace.h> +#include <asm/types.h> +#include <mach/ar71xx_regs.h> +#include <mach/ath79.h> +#include <wait_bit.h> + +#define PLL_SRIF_DPLL2_KI_LSB 29 +#define PLL_SRIF_DPLL2_KI_MASK 0x60000000 +#define PLL_SRIF_DPLL2_KI_SET(x) \ + (((x) << PLL_SRIF_DPLL2_KI_LSB) & PLL_SRIF_DPLL2_KI_MASK) +#define PLL_SRIF_DPLL2_KD_LSB 25 +#define PLL_SRIF_DPLL2_KD_MASK 0x1e000000 +#define PLL_SRIF_DPLL2_KD_SET(x) \ + (((x) << PLL_SRIF_DPLL2_KD_LSB) & PLL_SRIF_DPLL2_KD_MASK) +#define PLL_SRIF_DPLL2_PLL_PWD_LSB 22 +#define PLL_SRIF_DPLL2_PLL_PWD_MASK 0x00400000 +#define PLL_SRIF_DPLL2_PLL_PWD_SET(x) \ + (((x) << PLL_SRIF_DPLL2_PLL_PWD_LSB) & PLL_SRIF_DPLL2_PLL_PWD_MASK) +#define PLL_SRIF_DPLL2_OUTDIV_LSB 19 +#define PLL_SRIF_DPLL2_OUTDIV_MASK 0x00380000 +#define PLL_SRIF_DPLL2_OUTDIV_SET(x) \ + (((x) << PLL_SRIF_DPLL2_OUTDIV_LSB) & PLL_SRIF_DPLL2_OUTDIV_MASK) +#define PLL_SRIF_DPLL2_PHASE_SHIFT_LSB 12 +#define PLL_SRIF_DPLL2_PHASE_SHIFT_MASK 0x0007f000 +#define PLL_SRIF_DPLL2_PHASE_SHIFT_SET(x) \ + (((x) << PLL_SRIF_DPLL2_PHASE_SHIFT_LSB) & PLL_SRIF_DPLL2_PHASE_SHIFT_MASK) +#define CPU_PLL_CONFIG_PLLPWD_LSB 30 +#define CPU_PLL_CONFIG_PLLPWD_MASK 0x40000000 +#define CPU_PLL_CONFIG_PLLPWD_SET(x) \ + (((x) << CPU_PLL_CONFIG_PLLPWD_LSB) & CPU_PLL_CONFIG_PLLPWD_MASK) +#define CPU_PLL_CONFIG_OUTDIV_LSB 19 +#define CPU_PLL_CONFIG_OUTDIV_MASK 0x00380000 +#define CPU_PLL_CONFIG_OUTDIV_SET(x) \ + (((x) << CPU_PLL_CONFIG_OUTDIV_LSB) & CPU_PLL_CONFIG_OUTDIV_MASK) +#define CPU_PLL_CONFIG_RANGE_LSB 17 +#define CPU_PLL_CONFIG_RANGE_MASK 0x00060000 +#define CPU_PLL_CONFIG_RANGE_SET(x) \ + (((x) << CPU_PLL_CONFIG_RANGE_LSB) & CPU_PLL_CONFIG_RANGE_MASK) +#define CPU_PLL_CONFIG_REFDIV_LSB 12 +#define CPU_PLL_CONFIG_REFDIV_MASK 0x0001f000 +#define CPU_PLL_CONFIG_REFDIV_SET(x) \ + (((x) << CPU_PLL_CONFIG_REFDIV_LSB) & CPU_PLL_CONFIG_REFDIV_MASK) +#define CPU_PLL_CONFIG1_NINT_LSB 18 +#define CPU_PLL_CONFIG1_NINT_MASK 0x07fc0000 +#define CPU_PLL_CONFIG1_NINT_SET(x) \ + (((x) << CPU_PLL_CONFIG1_NINT_LSB) & CPU_PLL_CONFIG1_NINT_MASK) +#define CPU_PLL_DITHER1_DITHER_EN_LSB 31 +#define CPU_PLL_DITHER1_DITHER_EN_MASK 0x80000000 +#define CPU_PLL_DITHER1_DITHER_EN_SET(x) \ + (((x) << CPU_PLL_DITHER1_DITHER_EN_LSB) & CPU_PLL_DITHER1_DITHER_EN_MASK) +#define CPU_PLL_DITHER1_UPDATE_COUNT_LSB 24 +#define CPU_PLL_DITHER1_UPDATE_COUNT_MASK 0x3f000000 +#define CPU_PLL_DITHER1_UPDATE_COUNT_SET(x) \ + (((x) << CPU_PLL_DITHER1_UPDATE_COUNT_LSB) & CPU_PLL_DITHER1_UPDATE_COUNT_MASK) +#define CPU_PLL_DITHER1_NFRAC_STEP_LSB 18 +#define CPU_PLL_DITHER1_NFRAC_STEP_MASK 0x00fc0000 +#define CPU_PLL_DITHER1_NFRAC_STEP_SET(x) \ + (((x) << CPU_PLL_DITHER1_NFRAC_STEP_LSB) & CPU_PLL_DITHER1_NFRAC_STEP_MASK) +#define CPU_PLL_DITHER1_NFRAC_MIN_LSB 0 +#define CPU_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff +#define CPU_PLL_DITHER1_NFRAC_MIN_SET(x) \ + (((x) << CPU_PLL_DITHER1_NFRAC_MIN_LSB) & CPU_PLL_DITHER1_NFRAC_MIN_MASK) +#define CPU_PLL_DITHER2_NFRAC_MAX_LSB 0 +#define CPU_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff +#define CPU_PLL_DITHER2_NFRAC_MAX_SET(x) \ + (((x) << CPU_PLL_DITHER2_NFRAC_MAX_LSB) & CPU_PLL_DITHER2_NFRAC_MAX_MASK) +#define DDR_PLL_CONFIG_PLLPWD_LSB 30 +#define DDR_PLL_CONFIG_PLLPWD_MASK 0x40000000 +#define DDR_PLL_CONFIG_PLLPWD_SET(x) \ + (((x) << DDR_PLL_CONFIG_PLLPWD_LSB) & DDR_PLL_CONFIG_PLLPWD_MASK) +#define DDR_PLL_CONFIG_OUTDIV_LSB 23 +#define DDR_PLL_CONFIG_OUTDIV_MASK 0x03800000 +#define DDR_PLL_CONFIG_OUTDIV_SET(x) \ + (((x) << DDR_PLL_CONFIG_OUTDIV_LSB) & DDR_PLL_CONFIG_OUTDIV_MASK) +#define DDR_PLL_CONFIG_RANGE_LSB 21 +#define DDR_PLL_CONFIG_RANGE_MASK 0x00600000 +#define DDR_PLL_CONFIG_RANGE_SET(x) \ + (((x) << DDR_PLL_CONFIG_RANGE_LSB) & DDR_PLL_CONFIG_RANGE_MASK) +#define DDR_PLL_CONFIG_REFDIV_LSB 16 +#define DDR_PLL_CONFIG_REFDIV_MASK 0x001f0000 +#define DDR_PLL_CONFIG_REFDIV_SET(x) \ + (((x) << DDR_PLL_CONFIG_REFDIV_LSB) & DDR_PLL_CONFIG_REFDIV_MASK) +#define DDR_PLL_CONFIG1_NINT_LSB 18 +#define DDR_PLL_CONFIG1_NINT_MASK 0x07fc0000 +#define DDR_PLL_CONFIG1_NINT_SET(x) \ + (((x) << DDR_PLL_CONFIG1_NINT_LSB) & DDR_PLL_CONFIG1_NINT_MASK) +#define DDR_PLL_DITHER1_DITHER_EN_LSB 31 +#define DDR_PLL_DITHER1_DITHER_EN_MASK 0x80000000 +#define DDR_PLL_DITHER1_DITHER_EN_SET(x) \ + (((x) << DDR_PLL_DITHER1_DITHER_EN_LSB) & DDR_PLL_DITHER1_DITHER_EN_MASK) +#define DDR_PLL_DITHER1_UPDATE_COUNT_LSB 27 +#define DDR_PLL_DITHER1_UPDATE_COUNT_MASK 0x78000000 +#define DDR_PLL_DITHER1_UPDATE_COUNT_SET(x) \ + (((x) << DDR_PLL_DITHER1_UPDATE_COUNT_LSB) & DDR_PLL_DITHER1_UPDATE_COUNT_MASK) +#define DDR_PLL_DITHER1_NFRAC_STEP_LSB 20 +#define DDR_PLL_DITHER1_NFRAC_STEP_MASK 0x07f00000 +#define DDR_PLL_DITHER1_NFRAC_STEP_SET(x) \ + (((x) << DDR_PLL_DITHER1_NFRAC_STEP_LSB) & DDR_PLL_DITHER1_NFRAC_STEP_MASK) +#define DDR_PLL_DITHER1_NFRAC_MIN_LSB 0 +#define DDR_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff +#define DDR_PLL_DITHER1_NFRAC_MIN_SET(x) \ + (((x) << DDR_PLL_DITHER1_NFRAC_MIN_LSB) & DDR_PLL_DITHER1_NFRAC_MIN_MASK) +#define DDR_PLL_DITHER2_NFRAC_MAX_LSB 0 +#define DDR_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff +#define DDR_PLL_DITHER2_NFRAC_MAX_SET(x) \ + (((x) << DDR_PLL_DITHER2_NFRAC_MAX_LSB) & DDR_PLL_DITHER2_NFRAC_MAX_MASK) +#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB 24 +#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK 0x01000000 +#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB) & CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK) +#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB 21 +#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK 0x00200000 +#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK) +#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB 20 +#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK 0x00100000 +#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK) +#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB 15 +#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK 0x000f8000 +#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK) +#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB 10 +#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK 0x00007c00 +#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK) +#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB 5 +#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK 0x000003e0 +#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK) +#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB 4 +#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK 0x00000010 +#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK) +#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB 3 +#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK 0x00000008 +#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK) +#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB 2 +#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK 0x00000004 +#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(x) \ + (((x) << CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK) + +#define CPU_PLL_CONFIG1_NINT_VAL CPU_PLL_CONFIG1_NINT_SET(0x1f) +#define CPU_PLL_CONFIG_REF_DIV_VAL CPU_PLL_CONFIG_REFDIV_SET(0x1) +#define CPU_PLL_CONFIG_RANGE_VAL CPU_PLL_CONFIG_RANGE_SET(0) +#define CPU_PLL_CONFIG_OUT_DIV_VAL1 CPU_PLL_CONFIG_OUTDIV_SET(0) +#define CPU_PLL_CONFIG_OUT_DIV_VAL2 CPU_PLL_CONFIG_OUTDIV_SET(0) +#define CPU_PLL_DITHER1_VAL CPU_PLL_DITHER1_DITHER_EN_SET(0) | \ + CPU_PLL_DITHER1_NFRAC_MIN_SET(0) | \ + CPU_PLL_DITHER1_NFRAC_STEP_SET(0) | \ + CPU_PLL_DITHER1_UPDATE_COUNT_SET(0x0) +#define CPU_PLL_DITHER2_VAL CPU_PLL_DITHER2_NFRAC_MAX_SET(0x0) +#define DDR_PLL_CONFIG1_NINT_VAL DDR_PLL_CONFIG1_NINT_SET(0x1a) +#define DDR_PLL_CONFIG_REF_DIV_VAL DDR_PLL_CONFIG_REFDIV_SET(0x1) +#define DDR_PLL_CONFIG_RANGE_VAL DDR_PLL_CONFIG_RANGE_SET(0) +#define DDR_PLL_CONFIG_OUT_DIV_VAL1 DDR_PLL_CONFIG_OUTDIV_SET(0) +#define DDR_PLL_CONFIG_OUT_DIV_VAL2 DDR_PLL_CONFIG_OUTDIV_SET(0) +#define DDR_PLL_DITHER1_VAL DDR_PLL_DITHER1_DITHER_EN_SET(0) | \ + DDR_PLL_DITHER1_NFRAC_MIN_SET(0) | \ + DDR_PLL_DITHER1_NFRAC_STEP_SET(0) | \ + DDR_PLL_DITHER1_UPDATE_COUNT_SET(0x0) +#define DDR_PLL_DITHER2_VAL DDR_PLL_DITHER2_NFRAC_MAX_SET(0x0) +#define AHB_CLK_FROM_DDR CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(0) +#define CPU_AND_DDR_CLK_FROM_DDR \ + CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(0) +#define CPU_AND_DDR_CLK_FROM_CPU \ + CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(0) +#define CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL \ + CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(0x2) +#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV \ + CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(0) +#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV \ + CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(0) + +static inline void set_val(u32 _reg, u32 _mask, u32 _val) +{ + void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE, + AR71XX_PLL_SIZE, MAP_NOCACHE); + writel((readl(pll_regs + _reg) & (~(_mask))) | _val, pll_regs + _reg); +} + +#define cpu_pll_set(_mask, _val) \ + set_val(QCA956X_PLL_CPU_CONFIG_REG, _mask, _val) + +#define ddr_pll_set(_mask, _val) \ + set_val(QCA956X_PLL_DDR_CONFIG_REG, _mask, _val) + +#define cpu_ddr_control_set(_mask, _val) \ + set_val(QCA956X_PLL_CLK_CTRL_REG, _mask, _val) + +DECLARE_GLOBAL_DATA_PTR; + +static u32 qca956x_get_xtal(void) +{ + u32 val; + + val = ath79_get_bootstrap(); + if (val & QCA956X_BOOTSTRAP_REF_CLK_40) + return 40000000; + else + return 25000000; +} + +int get_serial_clock(void) +{ + return qca956x_get_xtal(); +} + +void qca956x_pll_init(void) +{ + void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE, + QCA956X_SRIF_SIZE, MAP_NOCACHE); + void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE, + AR71XX_PLL_SIZE, MAP_NOCACHE); + + /* 8.16.2 Baseband DPLL2 */ + writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) | + PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(1) | + PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + QCA956X_SRIF_BB_DPLL2_REG); + + /* 8.16.2 PCIE DPLL2 */ + writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) | + PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(3) | + PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + QCA956X_SRIF_PCIE_DPLL2_REG); + + /* 8.16.2 DDR DPLL2 */ + writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) | + PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), + srif_regs + QCA956X_SRIF_DDR_DPLL2_REG); + + /* 8.16.2 CPU DPLL2 */ + writel(PLL_SRIF_DPLL2_KI_SET(1) | PLL_SRIF_DPLL2_KD_SET(7) | + PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), + srif_regs + QCA956X_SRIF_CPU_DPLL2_REG); + + /* pll_bypass_set */ + cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK, + CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1)); + cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK, + CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1)); + cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK, + CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1)); + + /* init_cpu_pll */ + cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK, CPU_PLL_CONFIG_PLLPWD_SET(1)); + cpu_pll_set(CPU_PLL_CONFIG_REFDIV_MASK, CPU_PLL_CONFIG_REF_DIV_VAL); + cpu_pll_set(CPU_PLL_CONFIG_RANGE_MASK, CPU_PLL_CONFIG_RANGE_VAL); + cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL1); + set_val(QCA956X_PLL_CPU_CONFIG1_REG, CPU_PLL_CONFIG1_NINT_MASK, \ + CPU_PLL_CONFIG1_NINT_VAL); + + /* init_ddr_pll */ + ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK, DDR_PLL_CONFIG_PLLPWD_SET(1)); + ddr_pll_set(DDR_PLL_CONFIG_REFDIV_MASK, DDR_PLL_CONFIG_REF_DIV_VAL); + ddr_pll_set(DDR_PLL_CONFIG_RANGE_MASK, DDR_PLL_CONFIG_RANGE_VAL); + ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL1); + set_val(QCA956X_PLL_DDR_CONFIG1_REG, DDR_PLL_CONFIG1_NINT_MASK, + DDR_PLL_CONFIG1_NINT_VAL); + + /* init_ahb_pll */ + writel(CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL | AHB_CLK_FROM_DDR | + CPU_AND_DDR_CLK_FROM_DDR | CPU_AND_DDR_CLK_FROM_CPU | + CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV | CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV | + CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1) | + CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1) | + CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1), pll_regs + QCA956X_PLL_CLK_CTRL_REG); + + /* ddr_pll_dither_unset */ + writel(DDR_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_DDR_DIT_FRAC_REG); + writel(DDR_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_DDR_DIT2_FRAC_REG); + + /* cpu_pll_dither_unset */ + writel(CPU_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_CPU_DIT_FRAC_REG); + writel(CPU_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_CPU_DIT2_FRAC_REG); + + /* pll_pwd_unset */ + cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK, CPU_PLL_CONFIG_PLLPWD_SET(0)); + ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK, DDR_PLL_CONFIG_PLLPWD_SET(0)); + + /* outdiv_unset */ + cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL2); + ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL2); + + /* pll_bypass_unset */ + cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK, + CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(0)); + cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK, + CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(0)); + cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK, + CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(0)); + + while (readl(pll_regs + QCA956X_PLL_CPU_CONFIG_REG) & 0x8000000) + /* NOP */; + + while (readl(pll_regs + QCA956X_PLL_DDR_CONFIG_REG) & 0x8000000) + /* NOP */; +} + +int get_clocks(void) +{ + void __iomem *regs; + u32 ref_rate, cpu_rate, ddr_rate, ahb_rate; + u32 out_div, ref_div, postdiv, nint, hfrac, lfrac, clk_ctrl; + u32 pll, cpu_pll, ddr_pll, misc; + + /* + * QCA956x timer init workaround has to be applied right before setting + * up the clock. Else, there will be no jiffies + */ + regs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + misc = readl(regs + AR71XX_RESET_REG_MISC_INT_ENABLE); + misc |= MISC_INT_MIPS_SI_TIMERINT_MASK; + writel(misc, regs + AR71XX_RESET_REG_MISC_INT_ENABLE); + + regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + pll = readl(regs + QCA956X_PLL_CPU_CONFIG_REG); + out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & + QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) & + QCA956X_PLL_CPU_CONFIG_REFDIV_MASK; + + pll = readl(regs + QCA956X_PLL_CPU_CONFIG1_REG); + nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) & + QCA956X_PLL_CPU_CONFIG1_NINT_MASK; + hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) & + QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK; + lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) & + QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK; + + ref_rate = qca956x_get_xtal(); + + cpu_pll = nint * ref_rate / ref_div; + cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); + cpu_pll += (hfrac >> 13) * ref_rate / ref_div; + cpu_pll /= (1 << out_div); + + pll = readl(regs + QCA956X_PLL_DDR_CONFIG_REG); + out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) & + QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK; + ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) & + QCA956X_PLL_DDR_CONFIG_REFDIV_MASK; + pll = readl(regs + QCA956X_PLL_DDR_CONFIG1_REG); + nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) & + QCA956X_PLL_DDR_CONFIG1_NINT_MASK; + hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) & + QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK; + lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) & + QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK; + + ddr_pll = nint * ref_rate / ref_div; + ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13); + ddr_pll += (hfrac >> 13) * ref_rate / ref_div; + ddr_pll /= (1 << out_div); + + clk_ctrl = readl(regs + QCA956X_PLL_CLK_CTRL_REG); + + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) & + QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK; + + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS) + cpu_rate = ref_rate; + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL) + cpu_rate = ddr_pll / (postdiv + 1); + else + cpu_rate = cpu_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) & + QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK; + + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS) + ddr_rate = ref_rate; + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL) + ddr_rate = cpu_pll / (postdiv + 1); + else + ddr_rate = ddr_pll / (postdiv + 1); + + postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) & + QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK; + + if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS) + ahb_rate = ref_rate; + else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL) + ahb_rate = ddr_pll / (postdiv + 1); + else + ahb_rate = cpu_pll / (postdiv + 1); + + gd->cpu_clk = cpu_rate; + gd->mem_clk = ddr_rate; + gd->bus_clk = ahb_rate; + + debug("cpu_clk=%u, ddr_clk=%u, bus_clk=%u\n", + cpu_rate, ddr_rate, ahb_rate); + + return 0; +} + +ulong get_bus_freq(ulong dummy) +{ + if (!gd->bus_clk) + get_clocks(); + return gd->bus_clk; +} + +ulong get_ddr_freq(ulong dummy) +{ + if (!gd->mem_clk) + get_clocks(); + return gd->mem_clk; +} diff --git a/arch/mips/mach-ath79/qca956x/cpu.c b/arch/mips/mach-ath79/qca956x/cpu.c new file mode 100644 index 0000000..08a8c84 --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/cpu.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com> + */ + +#include <common.h> + +/* The lowlevel_init() is not needed on QCA956X */ +void lowlevel_init(void) {} diff --git a/arch/mips/mach-ath79/qca956x/ddr.c b/arch/mips/mach-ath79/qca956x/ddr.c new file mode 100644 index 0000000..fb22304 --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/ddr.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com> + * + * Based on QSDK + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/addrspace.h> +#include <asm/types.h> +#include <mach/ar71xx_regs.h> +#include <mach/ath79.h> + +#define DDR_FSM_WAIT_CTRL_VAL 0xa12 +#define DDR_CTL_CONFIG_SRAM_TSEL_LSB 30 +#define DDR_CTL_CONFIG_SRAM_TSEL_MASK 0xc0000000 +#define DDR_CTL_CONFIG_SRAM_TSEL_SET(x) \ + (((x) << DDR_CTL_CONFIG_SRAM_TSEL_LSB) & DDR_CTL_CONFIG_SRAM_TSEL_MASK) +#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB 20 +#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK 0x00100000 +#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB 19 +#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK 0x00080000 +#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB 18 +#define DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK 0x00040000 +#define DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB 17 +#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK 0x00020000 +#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB 16 +#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK 0x00010000 +#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB 15 +#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK 0x00008000 +#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB 14 +#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK 0x00004000 +#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK) +#define DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB 6 +#define DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK 0x00000040 +#define DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(x) \ + (((x) << DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB) & DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK) +#define DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB 2 +#define DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK 0x00000004 +#define DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(x) \ + (((x) << DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB) & DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK) +#define DDR_CTL_CONFIG_HALF_WIDTH_LSB 1 +#define DDR_CTL_CONFIG_HALF_WIDTH_MASK 0x00000002 +#define DDR_CTL_CONFIG_HALF_WIDTH_SET(x) \ + (((x) << DDR_CTL_CONFIG_HALF_WIDTH_LSB) & DDR_CTL_CONFIG_HALF_WIDTH_MASK) +#define DDR_CONFIG_CAS_LATENCY_MSB_LSB 31 +#define DDR_CONFIG_CAS_LATENCY_MSB_MASK 0x80000000 +#define DDR_CONFIG_CAS_LATENCY_MSB_SET(x) \ + (((x) << DDR_CONFIG_CAS_LATENCY_MSB_LSB) & DDR_CONFIG_CAS_LATENCY_MSB_MASK) +#define DDR_CONFIG_OPEN_PAGE_LSB 30 +#define DDR_CONFIG_OPEN_PAGE_MASK 0x40000000 +#define DDR_CONFIG_OPEN_PAGE_SET(x) \ + (((x) << DDR_CONFIG_OPEN_PAGE_LSB) & DDR_CONFIG_OPEN_PAGE_MASK) +#define DDR_CONFIG_CAS_LATENCY_LSB 27 +#define DDR_CONFIG_CAS_LATENCY_MASK 0x38000000 +#define DDR_CONFIG_CAS_LATENCY_SET(x) \ + (((x) << DDR_CONFIG_CAS_LATENCY_LSB) & DDR_CONFIG_CAS_LATENCY_MASK) +#define DDR_CONFIG_TMRD_LSB 23 +#define DDR_CONFIG_TMRD_MASK 0x07800000 +#define DDR_CONFIG_TMRD_SET(x) \ + (((x) << DDR_CONFIG_TMRD_LSB) & DDR_CONFIG_TMRD_MASK) +#define DDR_CONFIG_TRFC_LSB 17 +#define DDR_CONFIG_TRFC_MASK 0x007e0000 +#define DDR_CONFIG_TRFC_SET(x) \ + (((x) << DDR_CONFIG_TRFC_LSB) & DDR_CONFIG_TRFC_MASK) +#define DDR_CONFIG_TRRD_LSB 13 +#define DDR_CONFIG_TRRD_MASK 0x0001e000 +#define DDR_CONFIG_TRRD_SET(x) \ + (((x) << DDR_CONFIG_TRRD_LSB) & DDR_CONFIG_TRRD_MASK) +#define DDR_CONFIG_TRP_LSB 9 +#define DDR_CONFIG_TRP_MASK 0x00001e00 +#define DDR_CONFIG_TRP_SET(x) \ + (((x) << DDR_CONFIG_TRP_LSB) & DDR_CONFIG_TRP_MASK) +#define DDR_CONFIG_TRCD_LSB 5 +#define DDR_CONFIG_TRCD_MASK 0x000001e0 +#define DDR_CONFIG_TRCD_SET(x) \ + (((x) << DDR_CONFIG_TRCD_LSB) & DDR_CONFIG_TRCD_MASK) +#define DDR_CONFIG_TRAS_LSB 0 +#define DDR_CONFIG_TRAS_MASK 0x0000001f +#define DDR_CONFIG_TRAS_SET(x) \ + (((x) << DDR_CONFIG_TRAS_LSB) & DDR_CONFIG_TRAS_MASK) +#define DDR_CONFIG2_HALF_WIDTH_LOW_LSB 31 +#define DDR_CONFIG2_HALF_WIDTH_LOW_MASK 0x80000000 +#define DDR_CONFIG2_HALF_WIDTH_LOW_SET(x) \ + (((x) << DDR_CONFIG2_HALF_WIDTH_LOW_LSB) & DDR_CONFIG2_HALF_WIDTH_LOW_MASK) +#define DDR_CONFIG2_SWAP_A26_A27_LSB 30 +#define DDR_CONFIG2_SWAP_A26_A27_MASK 0x40000000 +#define DDR_CONFIG2_SWAP_A26_A27_SET(x) \ + (((x) << DDR_CONFIG2_SWAP_A26_A27_LSB) & DDR_CONFIG2_SWAP_A26_A27_MASK) +#define DDR_CONFIG2_GATE_OPEN_LATENCY_LSB 26 +#define DDR_CONFIG2_GATE_OPEN_LATENCY_MASK 0x3c000000 +#define DDR_CONFIG2_GATE_OPEN_LATENCY_SET(x) \ + (((x) << DDR_CONFIG2_GATE_OPEN_LATENCY_LSB) & DDR_CONFIG2_GATE_OPEN_LATENCY_MASK) +#define DDR_CONFIG2_TWTR_LSB 21 +#define DDR_CONFIG2_TWTR_MASK 0x03e00000 +#define DDR_CONFIG2_TWTR_SET(x) \ + (((x) << DDR_CONFIG2_TWTR_LSB) & DDR_CONFIG2_TWTR_MASK) +#define DDR_CONFIG2_TRTP_LSB 17 +#define DDR_CONFIG2_TRTP_MASK 0x001e0000 +#define DDR_CONFIG2_TRTP_SET(x) \ + (((x) << DDR_CONFIG2_TRTP_LSB) & DDR_CONFIG2_TRTP_MASK) +#define DDR_CONFIG2_TRTW_LSB 12 +#define DDR_CONFIG2_TRTW_MASK 0x0001f000 +#define DDR_CONFIG2_TRTW_SET(x) \ + (((x) << DDR_CONFIG2_TRTW_LSB) & DDR_CONFIG2_TRTW_MASK) +#define DDR_CONFIG2_TWR_LSB 8 +#define DDR_CONFIG2_TWR_MASK 0x00000f00 +#define DDR_CONFIG2_TWR_SET(x) \ + (((x) << DDR_CONFIG2_TWR_LSB) & DDR_CONFIG2_TWR_MASK) +#define DDR_CONFIG2_CKE_LSB 7 +#define DDR_CONFIG2_CKE_MASK 0x00000080 +#define DDR_CONFIG2_CKE_SET(x) \ + (((x) << DDR_CONFIG2_CKE_LSB) & DDR_CONFIG2_CKE_MASK) +#define DDR_CONFIG2_CNTL_OE_EN_LSB 5 +#define DDR_CONFIG2_CNTL_OE_EN_MASK 0x00000020 +#define DDR_CONFIG2_CNTL_OE_EN_SET(x) \ + (((x) << DDR_CONFIG2_CNTL_OE_EN_LSB) & DDR_CONFIG2_CNTL_OE_EN_MASK) +#define DDR_CONFIG2_BURST_LENGTH_LSB 0 +#define DDR_CONFIG2_BURST_LENGTH_MASK 0x0000000f +#define DDR_CONFIG2_BURST_LENGTH_SET(x) \ + (((x) << DDR_CONFIG2_BURST_LENGTH_LSB) & DDR_CONFIG2_BURST_LENGTH_MASK) +#define RST_BOOTSTRAP_ADDRESS 0x180600b0 +#define PMU2_SWREGMSB_LSB 22 +#define PMU2_SWREGMSB_MASK 0xffc00000 +#define PMU2_SWREGMSB_SET(x) \ + (((x) << PMU2_SWREGMSB_LSB) & PMU2_SWREGMSB_MASK) +#define PMU2_PGM_LSB 21 +#define PMU2_PGM_MASK 0x00200000 +#define PMU2_PGM_SET(x) \ + (((x) << PMU2_PGM_LSB) & PMU2_PGM_MASK) + +#define CPU_DDR_SYNC_MODE DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(0) + +/* +* DDR2 DDR1 +* 0x40c3 25MHz 0x4186 25Mhz +* 0x4138 40MHz 0x4270 40Mhz +*/ +#define CFG_DDR2_REFRESH_VAL 0x40c3 +#define CFG_DDR2_CONFIG_VAL DDR_CONFIG_CAS_LATENCY_MSB_SET(0x1) | \ + DDR_CONFIG_OPEN_PAGE_SET(0x1) | DDR_CONFIG_CAS_LATENCY_SET(0x4) | \ + DDR_CONFIG_TMRD_SET(0x6) | DDR_CONFIG_TRFC_SET(0x16) | \ + DDR_CONFIG_TRRD_SET(0x7) | DDR_CONFIG_TRP_SET(0xb) | \ + DDR_CONFIG_TRCD_SET(0xb) | DDR_CONFIG_TRAS_SET(0) +#define CFG_DDR2_CONFIG2_VAL DDR_CONFIG2_HALF_WIDTH_LOW_SET(0x1) | \ + DDR_CONFIG2_SWAP_A26_A27_SET(0x0) | DDR_CONFIG2_GATE_OPEN_LATENCY_SET(0xa) | \ + DDR_CONFIG2_TWTR_SET(0x16) | DDR_CONFIG2_TRTP_SET(0xa) | \ + DDR_CONFIG2_TRTW_SET(0xe) | DDR_CONFIG2_TWR_SET(0x2) | \ + DDR_CONFIG2_CKE_SET(0x1) | DDR_CONFIG2_CNTL_OE_EN_SET(0x1) | \ + DDR_CONFIG2_BURST_LENGTH_SET(0x8) + +#define CFG_DDR2_CONFIG3_VAL 0x0000000e +#define CFG_DDR2_EXT_MODE_VAL1 0x782 +#define CFG_DDR2_EXT_MODE_VAL2 0x402 +#define CFG_DDR2_MODE_VAL_INIT 0xb53 +#define CFG_DDR2_MODE_VAL 0xa53 +#define CFG_DDR2_TAP_VAL 0x10 +#define CFG_DDR2_EN_TWL_VAL 0x00001e91 +#define CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16 0xffff + +#define CFG_DDR_CTL_CONFIG DDR_CTL_CONFIG_SRAM_TSEL_SET(0x1) | \ + DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(0x1) | \ + DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(0x1) | \ + DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(0x1) | \ + DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(0x1) | \ + DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(0x1) | \ + DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(0x1) | \ + DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(0x1) + +DECLARE_GLOBAL_DATA_PTR; + +void qca956x_ddr_init(void) +{ + u32 ddr_config, ddr_config2, ddr_config3, mod_val, \ + mod_val_init, cycle_val, tap_val, ctl_config; + void __iomem *ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE, + MAP_NOCACHE); + void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE, QCA956X_SRIF_SIZE, + MAP_NOCACHE); + + ddr_config = CFG_DDR2_CONFIG_VAL; + ddr_config2 = CFG_DDR2_CONFIG2_VAL; + ddr_config3 = CFG_DDR2_CONFIG3_VAL; + mod_val_init = CFG_DDR2_MODE_VAL_INIT; + mod_val = CFG_DDR2_MODE_VAL; + tap_val = CFG_DDR2_TAP_VAL; + cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16; + ctl_config = CFG_DDR_CTL_CONFIG | DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(0x1) | + DDR_CTL_CONFIG_HALF_WIDTH_SET(0x1) | CPU_DDR_SYNC_MODE; + + writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL); + udelay(10); + + writel(ctl_config, ddr_regs + QCA956X_DDR_REG_CTL_CONF); + udelay(10); + + writel(cycle_val, ddr_regs + AR71XX_DDR_REG_RD_CYCLE); + udelay(100); + + writel(0x74444444, ddr_regs + QCA956X_DDR_REG_BURST); + udelay(100); + + writel(0x44444444, ddr_regs + QCA956X_DDR_REG_BURST2); + udelay(100); + + writel(DDR_FSM_WAIT_CTRL_VAL, ddr_regs + QCA956X_DDR_REG_FSM_WAIT_CTRL); + udelay(100); + + writel(0xfffff, ddr_regs + QCA956X_DDR_REG_TIMEOUT_MAX); + udelay(100); + + writel(ddr_config, ddr_regs + AR71XX_DDR_REG_CONFIG); + udelay(100); + + writel(ddr_config2, ddr_regs + AR71XX_DDR_REG_CONFIG2); + udelay(100); + + writel(ddr_config3, ddr_regs + QCA956X_DDR_REG_DDR3_CONFIG); + udelay(100); + + writel(CFG_DDR2_EN_TWL_VAL, ddr_regs + QCA956X_DDR_REG_DDR2_CONFIG); + udelay(100); + + writel(ddr_config2 | 0x80, ddr_regs + AR71XX_DDR_REG_CONFIG2); /* CKE Enable */ + udelay(100); + + writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */ + udelay(10); + + writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR2); + writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR2 */ + udelay(10); + + writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR3); + writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR3 */ + udelay(10); + + /* EMR DLL enable, Reduced Driver Impedance control, Differential DQS disabled */ + writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR); + udelay(100); + + writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */ + udelay(10); + + writel(mod_val_init, ddr_regs + AR71XX_DDR_REG_MODE); + udelay(1000); + + writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR Write */ + udelay(10); + + writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */ + udelay(10); + + writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Auto Refresh */ + udelay(10); + + writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Auto Refresh */ + udelay(10); + + /* Issue MRS to remove DLL out-of-reset */ + writel(mod_val, ddr_regs + AR71XX_DDR_REG_MODE); + udelay(100); + + writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR write */ + udelay(100); + + writel(CFG_DDR2_EXT_MODE_VAL1, ddr_regs + AR71XX_DDR_REG_EMR); + udelay(100); + + writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */ + udelay(100); + + writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR); + udelay(100); + + writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */ + udelay(100); + + writel(CFG_DDR2_REFRESH_VAL, ddr_regs + AR71XX_DDR_REG_REFRESH); + udelay(100); + + writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0); + writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1); + writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL2); + writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL3); + + writel(0x633c8176, srif_regs + QCA956X_SRIF_PMU1_REG); + /* Set DDR2 Voltage to 1.8 volts */ + writel(PMU2_SWREGMSB_SET(0x40) | PMU2_PGM_SET(0x1), + srif_regs + QCA956X_SRIF_PMU2_REG); +} diff --git a/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S new file mode 100644 index 0000000..db54b57 --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com> + * + * Based on QSDK + */ + +#include <config.h> +#include <asm/asm.h> +#include <asm/regdef.h> +#include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <mach/ar71xx_regs.h> + + .set noreorder + +LEAF(ddr_tap_tuning) + li a0, 0xbd001f00 + sw zero, 0x0(a0) /* Place where the tap values are saved and used for SWEEP */ + sw zero, 0x4(a0) /* Place where the number of passing taps are saved. */ + sw zero, 0x14(a0) /* Place where the last pass tap value is stored */ + li a1, 0xaa55aa55 /* Indicates that the First pass tap value is not found */ + sw a1, 0x10(a0) /* Place where the First pass tap value is stored */ + nop + + li a0, CKSEG1ADDR(AR71XX_RESET_BASE) /* RESET_BASE_ADDRESS */ + lw a1, 0x1c(a0) /* Reading the RST_RESET_ADDRESS */ + li a2, 0x08000000 /* Setting the RST_RESET_RTC_RESET */ + or a1, a1, a2 + sw a1, 0x1c(a0) + + li a3, 0xffffffff + xor a2, a2, a3 + and a1, a1, a2 + sw a1, 0x1c(a0) /* Taking the RTC out of RESET */ + nop + + li a0, CKSEG1ADDR(QCA956X_RTC_BASE) /* RTC_BASE_ADDRESS */ + li a1, 0x1 + sw a1, 0x0040(a0) /* RTC_SYNC_RESET_ADDRESS */ + + li a2, 0x2 + +_poll_for_RTC_ON: + lw a1, 0x0044(a0) /* RTC_SYNC_STATUS_ADDRESS */ + and a1, a2, a1 + bne a1, a2, _poll_for_RTC_ON + nop + +_CHANGE_TAPS: + li t0, 0xbd001f00 /* Read the current value of the TAP for programming */ + lw t1, 0x0(t0) + li t2, 0x00000000 + or t3, t1, t2 + + li t0, 0xb8000000 /* DDR_BASE_ADDRESS */ + sw t3, 0x1c(t0) /* TAP_CONTROL_0_ADDRESS */ + sw t3, 0x20(t0) /* TAP_CONTROL_1_ADDRESS */ + sw t3, 0x24(t0) /* TAP_CONTROL_2_ADDRESS */ + sw t3, 0x28(t0) /* TAP_CONTROL_3_ADDRESS */ + + li t1, 0x00000010 /* Running the test 8 times */ + sw t1, 0x0068(t0) /* PERF_COMP_ADDR_1_ADDRESS */ + + li t1, 0xfa5de83f /* 4 Row Address Bits, 4 Column Address Bits, 2 BA bits */ + sw t1, 0x002c(t0) /* PERF_MASK_ADDR_0_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x0070(t0) /* PERF_COMP_AHB_GE0_1_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x0040(t0) /* PERF_COMP_AHB_GE1_0_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x0078(t0) /* PERF_COMP_AHB_GE1_1_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x0034(t0) /* PERF_MASK_AHB_GE0_0_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x006c(t0) /* PERF_MASK_AHB_GE0_1_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x003c(t0) /* PERF_MASK_AHB_GE1_0_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x0074(t0) /* PERF_MASK_AHB_GE1_1_ADDRESS */ + + li t1, 0x0000ffff + sw t1, 0x0038(t0) /* PERF_COMP_AHB_GE0_0_ADDRESS */ + + li t1, 0x00000001 + sw t1, 0x011c(t0) /* DDR_BIST_ADDRESS */ + + li t2, 0x1 + +_bist_done_poll: + lw t1, 0x0120(t0) /* DDR_BIST_STATUS_ADDRESS */ + and t1, t1, t2 + bne t1, t2, _bist_done_poll + nop + + lw t1, 0x0120(t0) /* DDR_BIST_STATUS_ADDRESS */ + li t4, 0x000001fe + and t2, t1, t4 + srl t2, t2, 0x1 /* no. of Pass Runs */ + + li t5, 0x00000000 + sw t5, 0x011c(t0) /* DDR_BIST_ADDRESS - Stop the DDR BIST test */ + + li t5, 0x0001fe00 + and t5, t5, t1 + bnez t5, _iterate_tap /* This is a redundant compare but nevertheless - Comparing the FAILS */ + nop + + lw t1, 0x0068(t0) /* PERF_COMP_ADDR_1_ADDRESS */ + li t3, 0x000001fe + and t3, t3, t1 + srl t3, t3, 0x1 /* No. of runs in the config register. */ + bne t3, t2, _iterate_tap + nop + +pass_tap: + li t0, 0xbd001f00 + lw t1, 0x4(t0) + addiu t1, t1, 0x1 + sw t1, 0x4(t0) + + li t0, 0xbd001f10 + lw t1, 0x0(t0) + li t2, 0xaa55aa55 + beq t1, t2, _first_pass + nop + + li t0, 0xbd001f00 + lw t1, 0x0(t0) + li t0, 0xbd001f10 + sw t1, 0x4(t0) + nop + b _iterate_tap + nop + +_first_pass: + li t0, 0xbd001f00 + lw t1, 0x0(t0) + li t0, 0xbd001f10 + sw t1, 0x0(t0) + sw t1, 0x4(t0) + nop + +_iterate_tap: + li t0, 0xbd001f00 + lw t1, 0x0(t0) + li t2, 0x3f + beq t1, t2, _STOP_TEST + nop + + addiu t1, t1, 0x1 + sw t1, 0x0(t0) + nop + b _CHANGE_TAPS + nop + +_STOP_TEST: + li t0, 0xbd001f00 + lw t1, 0x4(t0) + bnez t1, _load_center_tap + nop + + li t3, 0x8 /* Default Tap to be used */ + b _load_tap_into_reg + nop + +_load_center_tap: + li t0, 0xbd001f10 + lw t1, 0x0(t0) + lw t2, 0x4(t0) + add t3, t1, t2 + srl t3, t3, 0x1 + li t4, 0x3f + and t3, t3, t4 + +_load_tap_into_reg: + li t0, 0xb8000000 + sw t3, 0x1c(t0) /* TAP_CONTROL_0_ADDRESS */ + sw t3, 0x20(t0) /* TAP_CONTROL_1_ADDRESS */ + sw t3, 0x24(t0) /* TAP_CONTROL_2_ADDRESS */ + sw t3, 0x28(t0) /* TAP_CONTROL_3_ADDRESS */ + + nop + jr ra + nop + END(ddr_tap_tuning) diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c index 6a94d88..0ab3ab6 100644 --- a/arch/mips/mach-ath79/reset.c +++ b/arch/mips/mach-ath79/reset.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> + * Copyright (C) 2018-2019 Rosy Song <rosysong@rosinson.com> */ #include <common.h> @@ -11,6 +12,44 @@ #include <mach/ath79.h> #include <mach/ar71xx_regs.h> +/* QCA956X ETH_SGMII_SERDES Registers */ +#define SGMII_SERDES_RES_CALIBRATION_LSB 23 +#define SGMII_SERDES_RES_CALIBRATION_MASK 0x07800000 +#define SGMII_SERDES_RES_CALIBRATION_SET(x) \ + (((x) << SGMII_SERDES_RES_CALIBRATION_LSB) & SGMII_SERDES_RES_CALIBRATION_MASK) +#define SGMII_SERDES_CDR_BW_LSB 1 +#define SGMII_SERDES_CDR_BW_MASK 0x00000006 +#define SGMII_SERDES_CDR_BW_SET(x) \ + (((x) << SGMII_SERDES_CDR_BW_LSB) & SGMII_SERDES_CDR_BW_MASK) +#define SGMII_SERDES_TX_DR_CTRL_LSB 4 +#define SGMII_SERDES_TX_DR_CTRL_MASK 0x00000070 +#define SGMII_SERDES_TX_DR_CTRL_SET(x) \ + (((x) << SGMII_SERDES_TX_DR_CTRL_LSB) & SGMII_SERDES_TX_DR_CTRL_MASK) +#define SGMII_SERDES_PLL_BW_LSB 8 +#define SGMII_SERDES_PLL_BW_MASK 0x00000100 +#define SGMII_SERDES_PLL_BW_SET(x) \ + (((x) << SGMII_SERDES_PLL_BW_LSB) & SGMII_SERDES_PLL_BW_MASK) +#define SGMII_SERDES_EN_SIGNAL_DETECT_LSB 16 +#define SGMII_SERDES_EN_SIGNAL_DETECT_MASK 0x00010000 +#define SGMII_SERDES_EN_SIGNAL_DETECT_SET(x) \ + (((x) << SGMII_SERDES_EN_SIGNAL_DETECT_LSB) & SGMII_SERDES_EN_SIGNAL_DETECT_MASK) +#define SGMII_SERDES_FIBER_SDO_LSB 17 +#define SGMII_SERDES_FIBER_SDO_MASK 0x00020000 +#define SGMII_SERDES_FIBER_SDO_SET(x) \ + (((x) << SGMII_SERDES_FIBER_SDO_LSB) & SGMII_SERDES_FIBER_SDO_MASK) +#define SGMII_SERDES_VCO_REG_LSB 27 +#define SGMII_SERDES_VCO_REG_MASK 0x78000000 +#define SGMII_SERDES_VCO_REG_SET(x) \ + (((x) << SGMII_SERDES_VCO_REG_LSB) & SGMII_SERDES_VCO_REG_MASK) +#define SGMII_SERDES_VCO_FAST_LSB 9 +#define SGMII_SERDES_VCO_FAST_MASK 0x00000200 +#define SGMII_SERDES_VCO_FAST_GET(x) \ + (((x) & SGMII_SERDES_VCO_FAST_MASK) >> SGMII_SERDES_VCO_FAST_LSB) +#define SGMII_SERDES_VCO_SLOW_LSB 10 +#define SGMII_SERDES_VCO_SLOW_MASK 0x00000400 +#define SGMII_SERDES_VCO_SLOW_GET(x) \ + (((x) & SGMII_SERDES_VCO_SLOW_MASK) >> SGMII_SERDES_VCO_SLOW_LSB) + void _machine_restart(void) { void __iomem *base; @@ -152,6 +191,236 @@ static int eth_init_qca953x(void) return 0; } +static int qca956x_sgmii_cal(void) +{ + int i; + u32 reg, rev_sgmii_val; + u32 vco_fast, vco_slow; + u32 start_val = 0, end_val = 0; + void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE, + MAP_NOCACHE); + void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII; + + writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG); + + reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES); + vco_fast = SGMII_SERDES_VCO_FAST_GET(reg); + vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg); + + /* Set resistor calibration from 0000 to 1111 */ + for (i = 0; i < 0x10; i++) { + reg = (readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) & + ~SGMII_SERDES_RES_CALIBRATION_MASK) | + SGMII_SERDES_RES_CALIBRATION_SET(i); + writel(reg, gregs + QCA956X_GMAC_REG_SGMII_SERDES); + + udelay(50); + + reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES); + if (vco_fast != SGMII_SERDES_VCO_FAST_GET(reg) || + vco_slow != SGMII_SERDES_VCO_SLOW_GET(reg)) { + if (start_val == 0) { + start_val = i; + end_val = i; + } else { + end_val = i; + } + } + vco_fast = SGMII_SERDES_VCO_FAST_GET(reg); + vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg); + } + + if (start_val == 0) + rev_sgmii_val = 0x7; + else + rev_sgmii_val = (start_val + end_val) >> 1; + + writel((readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) & + ~SGMII_SERDES_RES_CALIBRATION_MASK) | + SGMII_SERDES_RES_CALIBRATION_SET(rev_sgmii_val), + gregs + QCA956X_GMAC_REG_SGMII_SERDES); + + writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG); + + reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES); + writel(SGMII_SERDES_CDR_BW_SET(3) | SGMII_SERDES_TX_DR_CTRL_SET(1) | + SGMII_SERDES_PLL_BW_SET(1) | SGMII_SERDES_EN_SIGNAL_DETECT_SET(1) | + SGMII_SERDES_FIBER_SDO_SET(1) | SGMII_SERDES_VCO_REG_SET(3) | reg, + gregs + QCA956X_GMAC_REG_SGMII_SERDES); + + setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + + while (!(readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) & BIT(15))) + /* NOP */; + + return 0; +} + +static int qca956x_sgmii_setup(void) +{ + int i; + u32 s = 0, reg = 0; + u32 _regs[] = { + BIT(4), /* HW_RX_125M_N */ + BIT(2), /* RX_125M_N */ + BIT(3), /* TX_125M_N */ + BIT(0), /* RX_CLK_N */ + BIT(1), /* TX_CLK_N */ + }; + void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE, + MAP_NOCACHE); + + /* Force sgmii mode */ + writel(BIT(6) | BIT(15) | BIT(8), gregs + QCA956X_GMAC_REG_MR_AN_CTRL); + udelay(10); + writel(0x2 | BIT(5) | (0x2 << 6), gregs + QCA956X_GMAC_REG_SGMII_CONFIG); + + /* SGMII reset sequence sugguest by qca systems team. */ + writel(0, gregs + QCA956X_GMAC_REG_SGMII_RESET); + for (i = 0; i < ARRAY_SIZE(_regs); i++) { + reg |= _regs[i]; + writel(reg, gregs + QCA956X_GMAC_REG_SGMII_RESET); + } + + writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15), + gregs + QCA956X_GMAC_REG_MR_AN_CTRL); + + /* + * WARNING: Across resets SGMII link status goes to weird state. + * if 0xb8070058 (SGMII_DEBUG Register) reads other than 0xf or 0x10 + * for sure we are in bad state. + * Issue a PHY RESET in MR_AN_CONTROL_ADDRESS to keep going. + */ + i = 0; + s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff); + while (!(s == 0xf || s == 0x10)) { + writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) | BIT(15), + gregs + QCA956X_GMAC_REG_MR_AN_CTRL); + udelay(100); + writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15), + gregs + QCA956X_GMAC_REG_MR_AN_CTRL); + if (i++ == 10) + break; + s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff); + } + + return 0; +} + +static int qca956x_s17_reset(void) +{ + void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, + MAP_NOCACHE); + void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII | + QCA956X_RESET_EXTERNAL | QCA956X_RESET_SGMII_ANALOG | + QCA956X_RESET_SWITCH; + /* Bits(Reserved in datasheet) should be set to 1 */ + const u32 mask_r = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII | + QCA956X_RESET_EXTERNAL; + + setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask_r); + mdelay(1); + + /* Reset s17 switch(GPIO11) SYS_RST_L */ + writel(readl(regs + AR71XX_GPIO_REG_OE) & ~BIT(11), + regs + AR71XX_GPIO_REG_OE); + udelay(100); + + writel(readl(regs + AR71XX_GPIO_REG_OUT) & ~BIT(11), + regs + AR71XX_GPIO_REG_OUT); + udelay(100); + writel(readl(regs + AR71XX_GPIO_REG_OUT) | BIT(11), + regs + AR71XX_GPIO_REG_OUT); + + return 0; +} + +static int qca956x_init_mdio(void) +{ + u32 reg; + void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, + MAP_NOCACHE); + void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE, + MAP_NOCACHE); + const u32 mask = QCA956X_RESET_GE0_MDIO | QCA956X_RESET_GE0_MAC | + QCA956X_RESET_GE1_MDIO | QCA956X_RESET_GE1_MAC; + + setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask); + mdelay(1); + + /* GPIO4 as MDI */ + reg = readl(regs + QCA956X_GPIO_REG_IN_ENABLE3); + reg &= ~(0xff << 16); + reg |= (0x4 << 16); + writel(reg, regs + QCA956X_GPIO_REG_IN_ENABLE3); + + /* GPIO4 as MDO */ + reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC1); + reg &= ~0xff; + reg |= 0x20; + writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC1); + + /* Init MDC(GPIO3) / MDIO(GPIO4) */ + reg = readl(regs + AR71XX_GPIO_REG_OE); + reg &= ~BIT(4); + writel(reg, regs + AR71XX_GPIO_REG_OE); + udelay(100); + + reg = readl(regs + AR71XX_GPIO_REG_OE); + reg &= ~BIT(3); + writel(reg, regs + AR71XX_GPIO_REG_OE); + udelay(100); + + /* GPIO3 as MDI */ + reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC0); + reg &= ~(0xff << 24); + reg |= (0x21 << 24); + writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC0); + + return 0; +} + +static int eth_init_qca956x(void) +{ + void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE, + MAP_NOCACHE); + void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE, + MAP_NOCACHE); + + qca956x_sgmii_cal(); + qca956x_s17_reset(); + qca956x_init_mdio(); + + if (ath79_get_bootstrap() & QCA956X_BOOTSTRAP_REF_CLK_40) + writel(0x45500, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG); + else + writel(0xc5200, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG); + + qca956x_sgmii_setup(); + + writel((3 << 16) | (3 << 14) | (1 << 0) | (1 << 6), + gregs + QCA956X_GMAC_REG_ETH_CFG); + + writel((1 << 31) | (2 << 28) | (2 << 26) | (1 << 25), + pregs + QCA956X_PLL_ETH_XMII_CTRL_REG); + mdelay(1); + + return 0; +} + int ath79_eth_reset(void) { /* @@ -164,6 +433,8 @@ int ath79_eth_reset(void) return eth_init_ar934x(); if (soc_is_qca953x()) return eth_init_qca953x(); + if (soc_is_qca956x()) + return eth_init_qca956x(); return -EINVAL; } diff --git a/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h index f6e7245..493eaad 100644 --- a/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h +++ b/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h @@ -17,4 +17,6 @@ #define GPIO_GPIO_ALT(x) (0x74 + 4 * (x)) #define GPIO_GPIO_ALT1(x) (0x7c + 4 * (x)) +#define GCB_PHY_CFG 0x118 + #endif diff --git a/arch/mips/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig index 4ebcb4b..a983443 100644 --- a/arch/mips/mach-mt7620/Kconfig +++ b/arch/mips/mach-mt7620/Kconfig @@ -22,12 +22,12 @@ choice prompt "Board select" config BOARD_GARDENA_SMART_GATEWAY_MT7688 - bool "Gardena Smart Gateway" + bool "GARDENA smart Gateway" depends on SOC_MT7620 select BOARD_LATE_INIT select SUPPORTS_BOOT_RAM help - Gardena Smart Gateway boards have a MT7688 SoC with 128 MiB of RAM + GARDENA smart Gateway boards have a MT7688 SoC with 128 MiB of RAM and 8 MiB of flash (SPI NOR) and additional SPI NAND storage. config BOARD_LINKIT_SMART_7688 diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 54c4c19..8b2d645 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -493,6 +493,7 @@ compatible = "denx,u-boot-probe-test"; first-syscon = <&syscon0>; second-sys-ctrl = <&another_system_controller>; + third-syscon = <&syscon2>; }; }; @@ -597,7 +598,7 @@ 0x38 8>; }; - syscon@2 { + syscon2: syscon@2 { compatible = "simple-mfd", "syscon"; reg = <0x40 5 0x48 6 diff --git a/arch/sandbox/include/asm/sdl.h b/arch/sandbox/include/asm/sdl.h index 1027b59..c45dbdd 100644 --- a/arch/sandbox/include/asm/sdl.h +++ b/arch/sandbox/include/asm/sdl.h @@ -104,7 +104,7 @@ static inline int sandbox_sdl_sound_start(uint frequency) return -ENODEV; } -int sandbox_sdl_sound_play(const void *data, uint count) +static inline int sandbox_sdl_sound_play(const void *data, uint count) { return -ENODEV; } @@ -114,7 +114,7 @@ static inline int sandbox_sdl_sound_stop(void) return -ENODEV; } -int sandbox_sdl_sound_init(int rate, int channels) +static inline int sandbox_sdl_sound_init(int rate, int channels) { return -ENODEV; } diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h index 7cd56b4..c1a5d2a 100644 --- a/arch/sandbox/include/asm/types.h +++ b/arch/sandbox/include/asm/types.h @@ -18,21 +18,21 @@ typedef unsigned short umode_t; /* * Number of bits in a C 'long' on this architecture. */ -#ifdef CONFIG_PHYS64 +#ifdef CONFIG_PHYS_64BIT #define BITS_PER_LONG 64 -#else /* CONFIG_PHYS64 */ +#else /* CONFIG_PHYS_64BIT */ #define BITS_PER_LONG 32 -#endif /* CONFIG_PHYS64 */ +#endif /* CONFIG_PHYS_64BIT */ -#ifdef CONFIG_PHYS64 +#ifdef CONFIG_PHYS_64BIT typedef unsigned long long dma_addr_t; typedef u64 phys_addr_t; typedef u64 phys_size_t; -#else /* CONFIG_PHYS64 */ +#else /* CONFIG_PHYS_64BIT */ typedef unsigned long dma_addr_t; typedef u32 phys_addr_t; typedef u32 phys_size_t; -#endif /* CONFIG_PHYS64 */ +#endif /* CONFIG_PHYS_64BIT */ #endif /* __KERNEL__ */ diff --git a/arch/sandbox/lib/pci_io.c b/arch/sandbox/lib/pci_io.c index 5039973..01822c6 100644 --- a/arch/sandbox/lib/pci_io.c +++ b/arch/sandbox/lib/pci_io.c @@ -34,7 +34,7 @@ int pci_map_physmem(phys_addr_t paddr, unsigned long *lenp, return 0; } - debug("%s: failed: addr=%x\n", __func__, paddr); + debug("%s: failed: addr=%pap\n", __func__, &paddr); return -ENOSYS; } diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index c7f6479..c21d2f3 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -379,7 +379,7 @@ int board_init(void) puts("Cannot find Armada 385 watchdog!\n"); } else { puts("Enabling Armada 385 watchdog.\n"); - wdt_start(watchdog_dev, (u32) 25000000 * 120, 0); + wdt_start(watchdog_dev, 120000, 0); } # endif diff --git a/board/Marvell/db-xc3-24g4xg/.gitignore b/board/Marvell/db-xc3-24g4xg/.gitignore new file mode 100644 index 0000000..775b934 --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/.gitignore @@ -0,0 +1 @@ +kwbimage.cfg diff --git a/board/Marvell/db-xc3-24g4xg/MAINTAINERS b/board/Marvell/db-xc3-24g4xg/MAINTAINERS new file mode 100644 index 0000000..2b27e48 --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/MAINTAINERS @@ -0,0 +1,7 @@ +DB-XC3-24G4XG BOARD +M: Chris Packham <chris.packham@alliedtelesis.co.nz> +S: Maintained +F: board/Marvell/db-xc3-24g4xg/ +F: include/configs/db-xc3-24g4xg.h +F: configs/db-xc3-24g4xg_defconfig +F: arch/arm/dts/armada-xp-db-xc3-24g4xg.dts diff --git a/board/Marvell/db-xc3-24g4xg/Makefile b/board/Marvell/db-xc3-24g4xg/Makefile new file mode 100644 index 0000000..4dd5790 --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2015 Stefan Roese <sr@denx.de> + +obj-y := db-xc3-24g4xg.o +extra-y := kwbimage.cfg + +quiet_cmd_sed = SED $@ + cmd_sed = sed $(SEDFLAGS_$(@F)) $< >$(dir $<)$(@F) + +SEDFLAGS_kwbimage.cfg =-e "s|^BINARY.*|BINARY $(srctree)/$(@D)/binary.0 0000005b 00000068|" +$(src)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \ + include/config/auto.conf + $(call if_changed,sed) diff --git a/board/Marvell/db-xc3-24g4xg/README b/board/Marvell/db-xc3-24g4xg/README new file mode 100644 index 0000000..5e479b4 --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/README @@ -0,0 +1,4 @@ +To generate binary.0 from Marvell's bin_hdr.elf use the following command + + arm-softfloat-linux-gnueabi-objcopy -S -O binary bin_hdr.elf \ + board/Marvell/db-xc3-24g4xg/binary.0 diff --git a/board/Marvell/db-xc3-24g4xg/binary.0 b/board/Marvell/db-xc3-24g4xg/binary.0 new file mode 100644 index 0000000..8dd6872 --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/binary.0 @@ -0,0 +1,11 @@ +-------- +WARNING: +-------- +This file should contain the bin_hdr generated by the original Marvell +U-Boot implementation. As this is currently not included in this +U-Boot version, we have added this placeholder, so that the U-Boot +image can be generated without errors. + +If you have a known to be working bin_hdr for your board, then you +just need to replace this text file here with the binary header +and recompile U-Boot. diff --git a/board/Marvell/db-xc3-24g4xg/db-xc3-24g4xg.c b/board/Marvell/db-xc3-24g4xg/db-xc3-24g4xg.c new file mode 100644 index 0000000..cae428f --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/db-xc3-24g4xg.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Stefan Roese <sr@denx.de> + */ + +#include <common.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <linux/mbus.h> +#include <linux/io.h> +#include <asm/arch/cpu.h> +#include <asm/arch/soc.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * These values and defines are taken from the Marvell U-Boot version + * "u-boot-2013.01-2016_T1.0.eng_drop_v6" + */ +#define DB_DX_AC3_GPP_OUT_ENA_LOW (~(BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(6) | BIT(12) \ + | BIT(13) | BIT(16) | BIT(17) | BIT(20) | BIT(29) | BIT(30))) +#define DB_DX_AC3_GPP_OUT_ENA_MID (~(0)) +#define DB_DX_AC3_GPP_OUT_VAL_LOW (BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(6) | BIT(12) \ + | BIT(13) | BIT(16) | BIT(17) | BIT(20) | BIT(29) | BIT(30)) +#define DB_DX_AC3_GPP_OUT_VAL_MID 0x0 +#define DB_DX_AC3_GPP_POL_LOW 0x0 +#define DB_DX_AC3_GPP_POL_MID 0x0 + +int board_early_init_f(void) +{ + /* Configure MPP */ + writel(0x00142222, MVEBU_MPP_BASE + 0x00); + writel(0x11122000, MVEBU_MPP_BASE + 0x04); + writel(0x44444004, MVEBU_MPP_BASE + 0x08); + writel(0x14444444, MVEBU_MPP_BASE + 0x0c); + writel(0x00000001, MVEBU_MPP_BASE + 0x10); + + /* Set GPP Out value */ + writel(DB_DX_AC3_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00); + writel(DB_DX_AC3_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00); + + /* Set GPP Polarity */ + writel(DB_DX_AC3_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c); + writel(DB_DX_AC3_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c); + + /* Set GPP Out Enable */ + writel(DB_DX_AC3_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04); + writel(DB_DX_AC3_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04); + + return 0; +} + +int board_init(void) +{ + /* address of boot parameters */ + gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100; + + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + puts("Board: " CONFIG_SYS_BOARD "\n"); + + return 0; +} +#endif diff --git a/board/Marvell/db-xc3-24g4xg/kwbimage.cfg.in b/board/Marvell/db-xc3-24g4xg/kwbimage.cfg.in new file mode 100644 index 0000000..b8bb7a6 --- /dev/null +++ b/board/Marvell/db-xc3-24g4xg/kwbimage.cfg.in @@ -0,0 +1,12 @@ +# +# Copyright (C) 2014 Stefan Roese <sr@denx.de> +# + +# Armada XP uses version 1 image format +VERSION 1 + +# Boot Media configurations +BOOT_FROM spi + +# Binary Header (bin_hdr) with DDR3 training code +BINARY board/Marvell/db-xc3-24g4xg/binary.0 0000005b 00000068 diff --git a/board/Synology/ds414/ds414.c b/board/Synology/ds414/ds414.c index eb3694e..d23e97c 100644 --- a/board/Synology/ds414/ds414.c +++ b/board/Synology/ds414/ds414.c @@ -115,14 +115,14 @@ MV_DRAM_MODES *ddr3_get_static_ddr_mode(void) return &ds414_ddr_modes[0]; } -MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) +MV_BIN_SERDES_CFG *board_serdes_cfg_get(void) { return &ds414_serdes_cfg[0]; } u8 board_sat_r_get(u8 dev_num, u8 reg) { - return (0x1 << 1 | 1); + return 0xf; /* All PEX ports support PCIe Gen2 */ } int board_early_init_f(void) diff --git a/board/alliedtelesis/x530/x530.c b/board/alliedtelesis/x530/x530.c index d7d1942..6934fd8 100644 --- a/board/alliedtelesis/x530/x530.c +++ b/board/alliedtelesis/x530/x530.c @@ -7,6 +7,7 @@ #include <command.h> #include <dm.h> #include <i2c.h> +#include <wdt.h> #include <asm/gpio.h> #include <linux/mbus.h> #include <linux/io.h> @@ -24,6 +25,10 @@ DECLARE_GLOBAL_DATA_PTR; #define CONFIG_NVS_LOCATION 0xf4800000 #define CONFIG_NVS_SIZE (512 << 10) +#ifdef CONFIG_WATCHDOG +static struct udevice *watchdog_dev; +#endif + static struct serdes_map board_serdes_map[] = { {PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0}, {DEFAULT_SERDES, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0}, @@ -75,6 +80,10 @@ struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) int board_early_init_f(void) { +#ifdef CONFIG_WATCHDOG + watchdog_dev = NULL; +#endif + /* Configure MPP */ writel(0x00001111, MVEBU_MPP_BASE + 0x00); writel(0x00000000, MVEBU_MPP_BASE + 0x04); @@ -88,6 +97,17 @@ int board_early_init_f(void) return 0; } +void spl_board_init(void) +{ +#ifdef CONFIG_WATCHDOG + int ret; + + ret = uclass_get_device(UCLASS_WDT, 0, &watchdog_dev); + if (!ret) + wdt_start(watchdog_dev, 120000, 0); +#endif +} + int board_init(void) { /* address of boot parameters */ @@ -100,9 +120,37 @@ int board_init(void) /* DEV_READYn is not needed for NVS, ignore it when accessing CS1 */ writel(0x00004001, MVEBU_DEV_BUS_BASE + 0xc8); + spl_board_init(); + return 0; } +void arch_preboot_os(void) +{ +#ifdef CONFIG_WATCHDOG + wdt_stop(watchdog_dev); +#endif +} + +#ifdef CONFIG_WATCHDOG +void watchdog_reset(void) +{ + static ulong next_reset = 0; + ulong now; + + if (!watchdog_dev) + return; + + now = timer_get_us(); + + /* Do not reset the watchdog too often */ + if (now > next_reset) { + wdt_reset(watchdog_dev); + next_reset = now + 1000; + } +} +#endif + static int led_7seg_init(unsigned int segments) { int node; diff --git a/board/bosch/guardian/Kconfig b/board/bosch/guardian/Kconfig new file mode 100644 index 0000000..1417da6 --- /dev/null +++ b/board/bosch/guardian/Kconfig @@ -0,0 +1,15 @@ +if TARGET_AM335X_GUARDIAN + +config SYS_BOARD + default "guardian" + +config SYS_VENDOR + default "bosch" + +config SYS_SOC + default "am33xx" + +config SYS_CONFIG_NAME + default "am335x_guardian" + +endif diff --git a/board/bosch/guardian/MAINTAINERS b/board/bosch/guardian/MAINTAINERS new file mode 100644 index 0000000..8d16ec0 --- /dev/null +++ b/board/bosch/guardian/MAINTAINERS @@ -0,0 +1,6 @@ +Guardian BOARD +M: Sjoerd Simons <sjoerd.simons@collabora.co.uk> +S: Maintained +F: board/bosch/guardian/ +F: include/configs/am335x_guardian.h +F: configs/am335x_guardian_defconfig diff --git a/board/bosch/guardian/Makefile b/board/bosch/guardian/Makefile new file mode 100644 index 0000000..11625c9 --- /dev/null +++ b/board/bosch/guardian/Makefile @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Makefile +# +# Copyright (C) 2018 Robert Bosch Power Tools GmbH +# + +ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),) +obj-y := mux.o +endif + +obj-y += board.o diff --git a/board/bosch/guardian/board.c b/board/bosch/guardian/board.c new file mode 100644 index 0000000..86ab180 --- /dev/null +++ b/board/bosch/guardian/board.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * board.c + * + * Board functions for Bosch Guardian + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * Copyright (C) 2018 Robert Bosch Power Tools GmbH + */ + +#include <common.h> +#include <cpsw.h> +#include <dm.h> +#include <environment.h> +#include <environment.h> +#include <errno.h> +#include <i2c.h> +#include <miiphy.h> +#include <panel.h> +#include <power/tps65217.h> +#include <power/tps65910.h> +#include <spl.h> +#include <watchdog.h> +#include <asm/arch/clock.h> +#include <asm/arch/cpu.h> +#include <asm/arch/ddr_defs.h> +#include <asm/arch/gpio.h> +#include <asm/arch/hardware.h> +#include <asm/arch/mem.h> +#include <asm/arch/mmc_host_def.h> +#include <asm/arch/omap.h> +#include <asm/arch/sys_proto.h> +#include <asm/emif.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include "board.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + +static const struct ddr_data ddr3_data = { + .datardsratio0 = MT41K128M16JT125K_RD_DQS, + .datawdsratio0 = MT41K128M16JT125K_WR_DQS, + .datafwsratio0 = MT41K128M16JT125K_PHY_FIFO_WE, + .datawrsratio0 = MT41K128M16JT125K_PHY_WR_DATA, +}; + +static const struct cmd_control ddr3_cmd_ctrl_data = { + .cmd0csratio = MT41K128M16JT125K_RATIO, + .cmd0iclkout = MT41K128M16JT125K_INVERT_CLKOUT, + + .cmd1csratio = MT41K128M16JT125K_RATIO, + .cmd1iclkout = MT41K128M16JT125K_INVERT_CLKOUT, + + .cmd2csratio = MT41K128M16JT125K_RATIO, + .cmd2iclkout = MT41K128M16JT125K_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_emif_reg_data = { + .sdram_config = MT41K128M16JT125K_EMIF_SDCFG, + .ref_ctrl = MT41K128M16JT125K_EMIF_SDREF, + .sdram_tim1 = MT41K128M16JT125K_EMIF_TIM1, + .sdram_tim2 = MT41K128M16JT125K_EMIF_TIM2, + .sdram_tim3 = MT41K128M16JT125K_EMIF_TIM3, + .zq_config = MT41K128M16JT125K_ZQ_CFG, + .emif_ddr_phy_ctlr_1 = MT41K128M16JT125K_EMIF_READ_LATENCY, +}; + +#define OSC (V_OSCK / 1000000) +const struct dpll_params dpll_ddr = { + 400, OSC - 1, 1, -1, -1, -1, -1}; + +void am33xx_spl_board_init(void) +{ + int mpu_vdd; + int usb_cur_lim; + + /* Get the frequency */ + dpll_mpu_opp100.m = am335x_get_efuse_mpu_max_freq(cdev); + + if (i2c_probe(TPS65217_CHIP_PM)) + return; + + /* + * Increase USB current limit to 1300mA or 1800mA and set + * the MPU voltage controller as needed. + */ + if (dpll_mpu_opp100.m == MPUPLL_M_1000) { + usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1800MA; + mpu_vdd = TPS65217_DCDC_VOLT_SEL_1325MV; + } else { + usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA; + mpu_vdd = TPS65217_DCDC_VOLT_SEL_1275MV; + } + + if (tps65217_reg_write(TPS65217_PROT_LEVEL_NONE, + TPS65217_POWER_PATH, + usb_cur_lim, + TPS65217_USB_INPUT_CUR_LIMIT_MASK)) + puts("tps65217_reg_write failure\n"); + + /* Set DCDC3 (CORE) voltage to 1.125V */ + if (tps65217_voltage_update(TPS65217_DEFDCDC3, + TPS65217_DCDC_VOLT_SEL_1125MV)) { + puts("tps65217_voltage_update failure\n"); + return; + } + + /* Set CORE Frequencies to OPP100 */ + do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); + + /* Set DCDC2 (MPU) voltage */ + if (tps65217_voltage_update(TPS65217_DEFDCDC2, mpu_vdd)) { + puts("tps65217_voltage_update failure\n"); + return; + } + + /* + * Set LDO3 to 1.8V and LDO4 to 3.3V + */ + if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, + TPS65217_DEFLS1, + TPS65217_LDO_VOLTAGE_OUT_1_8, + TPS65217_LDO_MASK)) + puts("tps65217_reg_write failure\n"); + + if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, + TPS65217_DEFLS2, + TPS65217_LDO_VOLTAGE_OUT_3_3, + TPS65217_LDO_MASK)) + puts("tps65217_reg_write failure\n"); + + /* Set MPU Frequency to what we detected now that voltages are set */ + do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); +} + +const struct dpll_params *get_dpll_ddr_params(void) +{ + enable_i2c0_pin_mux(); + i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE); + + return &dpll_ddr; +} + +void set_uart_mux_conf(void) +{ + enable_uart0_pin_mux(); +} + +void set_mux_conf_regs(void) +{ + enable_board_pin_mux(); +} + +const struct ctrl_ioregs ioregs = { + .cm0ioctl = MT41K128M16JT125K_IOCTRL_VALUE, + .cm1ioctl = MT41K128M16JT125K_IOCTRL_VALUE, + .cm2ioctl = MT41K128M16JT125K_IOCTRL_VALUE, + .dt0ioctl = MT41K128M16JT125K_IOCTRL_VALUE, + .dt1ioctl = MT41K128M16JT125K_IOCTRL_VALUE, +}; + +void sdram_init(void) +{ + config_ddr(400, &ioregs, + &ddr3_data, + &ddr3_cmd_ctrl_data, + &ddr3_emif_reg_data, 0); +} +#endif + +int board_init(void) +{ +#if defined(CONFIG_HW_WATCHDOG) + hw_watchdog_init(); +#endif + + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + +#ifdef CONFIG_NAND + gpmc_init(); +#endif + return 0; +} diff --git a/board/bosch/guardian/board.h b/board/bosch/guardian/board.h new file mode 100644 index 0000000..b301caf --- /dev/null +++ b/board/bosch/guardian/board.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * board.h + * + * Board header for Bosch Guardian + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * Copyright (C) 2018 Robert Bosch Power Tools GmbH + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +void enable_uart0_pin_mux(void); +void enable_i2c0_pin_mux(void); +void enable_board_pin_mux(void); +#endif diff --git a/board/bosch/guardian/mux.c b/board/bosch/guardian/mux.c new file mode 100644 index 0000000..708c3e7 --- /dev/null +++ b/board/bosch/guardian/mux.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * mux.c + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * Copyright (C) 2018 Robert Bosch Power Tools GmbH + */ + +#include <common.h> +#include <i2c.h> +#include <asm/arch/hardware.h> +#include <asm/arch/mux.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include "board.h" + +static struct module_pin_mux uart0_pin_mux[] = { + {OFFSET(uart0_rxd), (MODE(0) | PULLUP_EN | RXACTIVE)}, + {OFFSET(uart0_txd), (MODE(0) | PULLUDEN)}, + {-1}, +}; + +static struct module_pin_mux i2c0_pin_mux[] = { + {OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)}, + {OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | PULLUDEN | SLEWCTRL)}, + {-1}, +}; + +static struct module_pin_mux adc_voltages_en[] = { + {OFFSET(mcasp0_ahclkx), (MODE(7) | PULLUP_EN)}, + {-1}, +}; + +static struct module_pin_mux asp_power_en[] = { + {OFFSET(mcasp0_aclkx), (MODE(7) | PULLUP_EN)}, + {-1}, +}; + +static struct module_pin_mux switch_off_3v6_pin_mux[] = { + {OFFSET(mii1_txd0), (MODE(7) | PULLUP_EN)}, + /* + * The uart1 lines are made floating inputs, based on the Guardian + * A2 Sample Power Supply Schematics + */ + {OFFSET(uart1_rxd), (MODE(7) | PULLUDDIS)}, + {OFFSET(uart1_txd), (MODE(7) | PULLUDDIS)}, + {-1}, +}; + +#ifdef CONFIG_NAND +static struct module_pin_mux nand_pin_mux[] = { + {OFFSET(gpmc_ad0), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad1), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad2), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad3), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad4), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad5), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad6), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad7), (MODE(0) | PULLUDDIS | RXACTIVE)}, +#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT + {OFFSET(gpmc_ad8), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad9), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad10), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad11), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad12), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad13), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad14), (MODE(0) | PULLUDDIS | RXACTIVE)}, + {OFFSET(gpmc_ad15), (MODE(0) | PULLUDDIS | RXACTIVE)}, +#endif + {OFFSET(gpmc_wait0), (MODE(0) | PULLUP_EN | RXACTIVE)}, + {OFFSET(gpmc_wpn), (MODE(7) | PULLUP_EN)}, + {OFFSET(gpmc_csn0), (MODE(0) | PULLUP_EN)}, + {OFFSET(gpmc_wen), (MODE(0) | PULLDOWN_EN)}, + {OFFSET(gpmc_oen_ren), (MODE(0) | PULLDOWN_EN)}, + {OFFSET(gpmc_advn_ale), (MODE(0) | PULLDOWN_EN)}, + {OFFSET(gpmc_be0n_cle), (MODE(0) | PULLDOWN_EN)}, + {-1}, +}; +#endif + +void enable_uart0_pin_mux(void) +{ + configure_module_pin_mux(uart0_pin_mux); +} + +void enable_i2c0_pin_mux(void) +{ + configure_module_pin_mux(i2c0_pin_mux); +} + +void enable_board_pin_mux(void) +{ +#ifdef CONFIG_NAND + configure_module_pin_mux(nand_pin_mux); +#endif + configure_module_pin_mux(adc_voltages_en); + configure_module_pin_mux(asp_power_en); + configure_module_pin_mux(switch_off_3v6_pin_mux); +} diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c index b0b29b3..e8ec553 100644 --- a/board/davinci/da8xxevm/da850evm.c +++ b/board/davinci/da8xxevm/da850evm.c @@ -49,33 +49,6 @@ DECLARE_GLOBAL_DATA_PTR; #define CFG_MAC_ADDR_OFFSET (flash->size - SZ_64K) -#ifdef CONFIG_SPL_BUILD -#include <ns16550.h> -#include <dm/platform_data/spi_davinci.h> - -static const struct ns16550_platdata da850evm_serial = { - .base = DAVINCI_UART2_BASE, - .reg_shift = 2, - .clock = 150000000, - .fcr = UART_FCR_DEFVAL, -}; - -U_BOOT_DEVICE(da850evm_uart) = { - .name = "ns16550_serial", - .platdata = &da850evm_serial, -}; - -static const struct davinci_spi_platdata davinci_spi_data = { - .regs = (struct davinci_spi_regs *)0x01f0e000, - .num_cs = 4, -}; - -U_BOOT_DEVICE(davinci_spi) = { - .name = "davinci_spi", - .platdata = &davinci_spi_data, -}; -#endif - #ifdef CONFIG_MAC_ADDR_IN_SPIFLASH static int get_mac_addr(u8 *addr) { diff --git a/board/davinci/da8xxevm/u-boot-spl-da850evm.lds b/board/davinci/da8xxevm/u-boot-spl-da850evm.lds index 7b5fab7..8f04911 100644 --- a/board/davinci/da8xxevm/u-boot-spl-da850evm.lds +++ b/board/davinci/da8xxevm/u-boot-spl-da850evm.lds @@ -10,6 +10,9 @@ MEMORY { .sram : ORIGIN = IMAGE_TEXT_BASE,\ LENGTH = CONFIG_SPL_MAX_FOOTPRINT } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) @@ -42,6 +45,15 @@ SECTIONS __rel_dyn_end = .; } >.sram + __image_copy_end = .; + + .end : + { + *(.__end) + } + + _image_binary_end = .; + .bss : { . = ALIGN(4); @@ -49,12 +61,5 @@ SECTIONS *(.bss*) . = ALIGN(4); __bss_end = .; - } >.sram - - __image_copy_end = .; - - .end : - { - *(.__end) - } + } >.sdram } diff --git a/board/logicpd/am3517evm/am3517evm.c b/board/logicpd/am3517evm/am3517evm.c index 6f72839..10031a4 100644 --- a/board/logicpd/am3517evm/am3517evm.c +++ b/board/logicpd/am3517evm/am3517evm.c @@ -37,6 +37,15 @@ DECLARE_GLOBAL_DATA_PTR; #define CPGMACSS_SW_RST (1 << 1) #define PHY_GPIO 30 +#if defined(CONFIG_SPL_BUILD) +#if defined(CONFIG_SPL_OS_BOOT) +int spl_start_uboot(void) +{ + /* break into full u-boot on 'c' */ + return serial_tstc() && serial_getc() == 'c'; +} +#endif +#endif /* * Routine: board_init diff --git a/board/maxbcm/maxbcm.c b/board/maxbcm/maxbcm.c index e8f8f7b..395904f 100644 --- a/board/maxbcm/maxbcm.c +++ b/board/maxbcm/maxbcm.c @@ -95,7 +95,7 @@ MV_DRAM_MODES *ddr3_get_static_ddr_mode(void) return &maxbcm_ddr_modes[0]; } -MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) +MV_BIN_SERDES_CFG *board_serdes_cfg_get(void) { return &maxbcm_serdes_cfg[0]; } diff --git a/board/mscc/jr2/jr2.c b/board/mscc/jr2/jr2.c index 58a4a04..6e5ef4c 100644 --- a/board/mscc/jr2/jr2.c +++ b/board/mscc/jr2/jr2.c @@ -6,6 +6,7 @@ #include <common.h> #include <asm/io.h> #include <led.h> +#include <miiphy.h> enum { BOARD_TYPE_PCB110 = 0xAABBCE00, @@ -64,6 +65,28 @@ static void vcoreiii_gpio_set_alternate(int gpio, int mode) } } +int board_phy_config(struct phy_device *phydev) +{ + if (gd->board_type == BOARD_TYPE_PCB110 || + gd->board_type == BOARD_TYPE_PCB112) { + phy_write(phydev, 0, 31, 0x10); + phy_write(phydev, 0, 18, 0x80F0); + while (phy_read(phydev, 0, 18) & 0x8000) + ; + phy_write(phydev, 0, 31, 0); + } + if (gd->board_type == BOARD_TYPE_PCB111) { + phy_write(phydev, 0, 31, 0x10); + phy_write(phydev, 0, 18, 0x80A0); + while (phy_read(phydev, 0, 18) & 0x8000) + ; + phy_write(phydev, 0, 14, 0x800); + phy_write(phydev, 0, 31, 0); + } + + return 0; +} + void board_debug_uart_init(void) { /* too early for the pinctrl driver, so configure the UART pins here */ diff --git a/board/qca/ap152/Kconfig b/board/qca/ap152/Kconfig new file mode 100644 index 0000000..f6ad498 --- /dev/null +++ b/board/qca/ap152/Kconfig @@ -0,0 +1,15 @@ +if TARGET_AP152 + +config SYS_VENDOR + default "qca" + +config SYS_BOARD + default "ap152" + +config SYS_CONFIG_NAME + default "ap152" + +config SYS_TEXT_BASE + default 0x9f000000 + +endif diff --git a/board/qca/ap152/MAINTAINERS b/board/qca/ap152/MAINTAINERS new file mode 100644 index 0000000..785ec27 --- /dev/null +++ b/board/qca/ap152/MAINTAINERS @@ -0,0 +1,6 @@ +AP152 BOARD +M: Rosy Song <rosysong@rosinson.com> +S: Maintained +F: board/qca/ap152/ +F: include/configs/ap152.h +F: configs/ap152_defconfig diff --git a/board/qca/ap152/Makefile b/board/qca/ap152/Makefile new file mode 100644 index 0000000..4270afa --- /dev/null +++ b/board/qca/ap152/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y = ap152.o diff --git a/board/qca/ap152/ap152.c b/board/qca/ap152/ap152.c new file mode 100644 index 0000000..30cd565 --- /dev/null +++ b/board/qca/ap152/ap152.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/addrspace.h> +#include <asm/types.h> +#include <mach/ar71xx_regs.h> +#include <mach/ddr.h> +#include <mach/ath79.h> +#include <debug_uart.h> + +#define RST_RESET_RTC_RESET_LSB 27 +#define RST_RESET_RTC_RESET_MASK 0x08000000 +#define RST_RESET_RTC_RESET_SET(x) \ + (((x) << RST_RESET_RTC_RESET_LSB) & RST_RESET_RTC_RESET_MASK) + +#ifdef CONFIG_DEBUG_UART_BOARD_INIT +void board_debug_uart_init(void) +{ + void __iomem *regs; + u32 val; + + regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, + MAP_NOCACHE); + + /* UART : RX18, TX22 done + * GPIO18 as input, GPIO22 as output + */ + val = readl(regs + AR71XX_GPIO_REG_OE); + val |= QCA956X_GPIO(18); + val &= ~QCA956X_GPIO(22); + writel(val, regs + AR71XX_GPIO_REG_OE); + + /* + * Enable GPIO22 as UART0_SOUT + */ + val = readl(regs + QCA956X_GPIO_REG_OUT_FUNC5); + val &= ~QCA956X_GPIO_MUX_MASK(16); + val |= QCA956X_GPIO_OUT_MUX_UART0_SOUT << 16; + writel(val, regs + QCA956X_GPIO_REG_OUT_FUNC5); + + /* + * Enable GPIO18 as UART0_SIN + */ + val = readl(regs + QCA956X_GPIO_REG_IN_ENABLE0); + val &= ~QCA956X_GPIO_MUX_MASK(8); + val |= QCA956X_GPIO_IN_MUX_UART0_SIN << 8; + writel(val, regs + QCA956X_GPIO_REG_IN_ENABLE0); + + /* + * Enable GPIO22 output + */ + val = readl(regs + AR71XX_GPIO_REG_OUT); + val |= QCA956X_GPIO(22); + writel(val, regs + AR71XX_GPIO_REG_OUT); +} +#endif + +int board_early_init_f(void) +{ + u32 reg; + void __iomem *rst_regs = map_physmem(AR71XX_RESET_BASE, + AR71XX_RESET_SIZE, MAP_NOCACHE); + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + /* CPU:775, DDR:650, AHB:258 */ + qca956x_pll_init(); + qca956x_ddr_init(); +#endif + + /* Take WMAC out of reset */ + reg = readl(rst_regs + QCA956X_RESET_REG_RESET_MODULE); + reg &= (~RST_RESET_RTC_RESET_SET(1)); + writel(reg, rst_regs + QCA956X_RESET_REG_RESET_MODULE); + + ath79_eth_reset(); + return 0; +} diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README index a7bc0d4..0b0e98d 100644 --- a/board/solidrun/clearfog/README +++ b/board/solidrun/clearfog/README @@ -17,6 +17,29 @@ $ sudo dd if=u-boot-spl.kwb of=/dev/sdX bs=512 seek=1 Please use the correct device node for your setup instead of "/dev/sdX" here! +Install U-Boot on eMMC: +----------------------- + +The ROM loads the bootloader from eMMC first boot partition at offset 0. This +is unlike load from SD card that is at offset 512. As a result, the offset of +the main U-Boot image on the eMMC boot partition changes. Set +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR to 0x140 for SPL to load U-Boot from +the correct location. + +To make SPL load the main U-Boot image from the eMMC boot partition enable +eMMC boot acknowledgement and boot partition with the following U-Boot +command: + + mmc partconf 0 1 1 0 + +Install U-Boot on eMMC boot partition from Linux running on Clearfog: + + echo 0 > /sys/block/mmcblk0boot0/force_ro + dd if=u-boot-spl.kwb of=/dev/mmcblk0boot0 + +Note that the SD card is not accessible when the Clearfog SOM has eMMC. +Consider initial boot from UART (see below). + Boot selection: --------------- diff --git a/board/st/stm32mp1/MAINTAINERS b/board/st/stm32mp1/MAINTAINERS index 48d8fd2..0a2eddb 100644 --- a/board/st/stm32mp1/MAINTAINERS +++ b/board/st/stm32mp1/MAINTAINERS @@ -2,7 +2,8 @@ STM32MP1 BOARD M: Patrick Delaunay <patrick.delaunay@st.com> L: uboot-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers) S: Maintained +F: arch/arm/dts/stm32mp157* F: board/st/stm32mp1 -F: include/configs/stm32mp1.h F: configs/stm32mp15_basic_defconfig -F: arch/arm/dts/stm32mp157* +F: configs/stm32mp15_trusted_defconfig +F: include/configs/stm32mp1.h diff --git a/board/st/stm32mp1/README b/board/st/stm32mp1/README index 174e6db..1cd3534 100644 --- a/board/st/stm32mp1/README +++ b/board/st/stm32mp1/README @@ -28,14 +28,15 @@ Everything is supported in Linux but U-Boot is limited to: And the necessary drivers 1. I2C -2. STPMU1 -2. STPMU1 (PMIC and regulator) +2. STPMIC1 (PMIC and regulator) 3. Clock, Reset, Sysreset 4. Fuse Currently the following boards are supported: + stm32mp157c-ev1 + stm32mp157c-ed1 ++ stm32mp157a-dk1 ++ stm32mp157c-dk2 3. Boot Sequences ================= @@ -45,15 +46,22 @@ BootRom => FSBL in SYSRAM => SSBL in DDR => OS (Linux Kernel) with FSBL = First Stage Bootloader SSBL = Second Stage Bootloader -One boot configuration is supported: +2 boot configurations are supported: - The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig) +1) The "Trusted" boot chain (defconfig_file : stm32mp15_trusted_defconfig) + BootRom => FSBL = Trusted Firmware-A (TF-A) => SSBL = U-Boot + TF-A performs a full initialization of Secure peripherals and installs a + secure monitor. + U-Boot is running in normal world and uses TF-A monitor + to access to secure resources + +2) The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig) BootRom => FSBL = U-Boot SPL => SSBL = U-Boot SPL has limited security initialisation U-Boot is running in secure mode and provide a secure monitor to the kernel with only PSCI support (Power State Coordination Interface defined by ARM) -All the STM32MP1 board supported by U-Boot use the same generic board +All the STM32MP1 boards supported by U-Boot use the same generic board stm32mp1 which support all the bootable devices. Each board is configurated only with the associated device tree. @@ -64,12 +72,18 @@ Each board is configurated only with the associated device tree. You need to select the appropriate device tree for your board, the supported device trees for stm32mp157 are: -+ ev1: eval board with pmic stpmu1 (ev1 = mother board + daughter ed1) ++ ev1: eval board with pmic stpmic1 (ev1 = mother board + daughter ed1) dts: stm32mp157c-ev1 -+ ed1: daughter board with pmic stpmu1 ++ ed1: daughter board with pmic stpmic1 dts: stm32mp157c-ed1 ++ dk1: Discovery board + dts: stm32mp157a-dk1 + ++ dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel + dts: stm32mp157c-dk2 + 5. Build Procedure ================== @@ -90,12 +104,14 @@ the supported device trees for stm32mp157 are: # export KBUILD_OUTPUT=/path/to/output for example: use one output directory for each configuration + # export KBUILD_OUTPUT=stm32mp15_trusted # export KBUILD_OUTPUT=stm32mp15_basic -4. Configure the U-Boot: +4. Configure U-Boot: # make <defconfig_file> + - For trusted boot mode : "stm32mp15_trusted_defconfig" - For basic boot mode: "stm32mp15_basic_defconfig" 5. Configure the device-tree and build the U-Boot image: @@ -104,16 +120,26 @@ the supported device trees for stm32mp157 are: example: - basic boot on ev1 + a) trusted boot on ev1 + # export KBUILD_OUTPUT=stm32mp15_trusted + # make stm32mp15_trusted_defconfig + # make DEVICE_TREE=stm32mp157c-ev1 all + + b) basic boot on ev1 # export KBUILD_OUTPUT=stm32mp15_basic # make stm32mp15_basic_defconfig # make DEVICE_TREE=stm32mp157c-ev1 all - basic boot on ed1 + c) basic boot on ed1 # export KBUILD_OUTPUT=stm32mp15_basic # make stm32mp15_basic_defconfig # make DEVICE_TREE=stm32mp157c-ed1 all + d) basic boot on dk2 + # export KBUILD_OUTPUT=stm32mp15_basic + # make stm32mp15_basic_defconfig + # make DEVICE_TREE=stm32mp157c-dk2 all + 6. Output files BootRom and TF-A expect binaries with STM32 image header @@ -122,6 +148,11 @@ the supported device trees for stm32mp157 are: So in the output directory (selected by KBUILD_OUTPUT), you can found the needed files: + a) For Trusted boot + + FSBL = tf-a.stm32 (provided by TF-A compilation) + + SSBL = u-boot.stm32 + + b) For Basic boot + FSBL = spl/u-boot-spl.stm32 + SSBL = u-boot.img @@ -135,13 +166,22 @@ You can select the boot mode, on the board ed1 with the switch SW1 ----------------------------------- Reserved 0 0 0 NOR 0 0 1 - SD-Card 1 1 1 SD-Card 1 0 1 eMMC 0 1 0 NAND 0 1 1 Recovery 1 1 0 Recovery 0 0 0 +- on board DK1/DK2 with the switch SW1 : BOOT0, BOOT2 + (BOOT1 forced to 0, NOR not supported) + + -------------------------- + Boot Mode BOOT2 BOOT0 + -------------------------- + Reserved 1 0 + SD-Card 1 1 + Recovery 0 0 + Recovery is a boot from serial link (UART/USB) and it is used with STM32CubeProgrammer tool to load executable in RAM and to update the flash devices available on the board (NOR/NAND/eMMC/SDCARD). @@ -158,14 +198,14 @@ The minimal requirements for STMP32MP1 boot up to U-Boot are: - one ssbl partition for U-Boot Then the minimal GPT partition is: - ----- ------- --------- ------------- - | Num | Name | Size | Content | - ----- ------- -------- -------------- + ----- ------- --------- -------------- + | Num | Name | Size | Content | + ----- ------- -------- --------------- | 1 | fsbl1 | 256 KiB | TF-A or SPL | | 2 | fsbl2 | 256 KiB | TF-A or SPL | - | 3 | ssbl | enought | U-Boot | - | * | - | - | Boot/Rootfs| - ----- ------- --------- ------------- + | 3 | ssbl | enought | U-Boot | + | * | - | - | Boot/Rootfs | + ----- ------- --------- -------------- (*) add bootable partition for extlinux.conf following Generic Distribution @@ -189,7 +229,7 @@ for example: with gpt table with 128 entries you can add other partitions for kernel one partition rootfs for example: - -n 3:5154: -c 4:rootfs + -n 4:5154: -c 4:rootfs \ c) copy the FSBL (2 times) and SSBL file on the correct partition. in this example in partition 1 to 3 @@ -199,6 +239,11 @@ for example: with gpt table with 128 entries # dd if=u-boot-spl.stm32 of=/dev/mmcblk0p2 # dd if=u-boot.img of=/dev/mmcblk0p3 + for trusted boot mode : + # dd if=tf-a.stm32 of=/dev/mmcblk0p1 + # dd if=tf-a.stm32 of=/dev/mmcblk0p2 + # dd if=u-boot.stm32 of=/dev/mmcblk0p3 + To boot from SDCard, select BootPinMode = 1 1 1 and reset. 8. Prepare eMMC @@ -208,7 +253,7 @@ You can use U-Boot to copy binary in eMMC. In the next example, you need to boot from SDCARD and the images (u-boot-spl.stm32, u-boot.img) are presents on SDCARD (mmc 0) in ext4 partition 4 (bootfs). -To boot from SDCard, select BootPinMode = 1 1 1 and reset. +To boot from SDCard, select BootPinMode = 1 0 1 and reset. Then you update the eMMC with the next U-Boot command : @@ -227,7 +272,7 @@ b) copy SPL on eMMC on firts boot partition # mmc write ${fileaddr} 0 200 # mmc partconf 1 1 1 0 -b) copy U-Boot in first GPT partition of eMMC +c) copy U-Boot in first GPT partition of eMMC # ext4load mmc 0:4 0xC0000000 u-boot.img # mmc dev 1 diff --git a/board/st/stm32mp1/board.c b/board/st/stm32mp1/board.c index 5f31ea9..5c1acca 100644 --- a/board/st/stm32mp1/board.c +++ b/board/st/stm32mp1/board.c @@ -8,7 +8,7 @@ #include <asm/io.h> #include <asm/arch/ddr.h> #include <power/pmic.h> -#include <power/stpmu1.h> +#include <power/stpmic1.h> #ifdef CONFIG_DEBUG_UART_BOARD_INIT void board_debug_uart_init(void) @@ -37,64 +37,65 @@ void board_debug_uart_init(void) } #endif -#ifdef CONFIG_PMIC_STPMU1 +#ifdef CONFIG_PMIC_STPMIC1 int board_ddr_power_init(void) { struct udevice *dev; int ret; ret = uclass_get_device_by_driver(UCLASS_PMIC, - DM_GET_DRIVER(pmic_stpmu1), &dev); + DM_GET_DRIVER(pmic_stpmic1), &dev); if (ret) /* No PMIC on board */ return 0; - /* Set LDO3 to sync mode */ - ret = pmic_reg_read(dev, STPMU1_LDOX_CTRL_REG(STPMU1_LDO3)); + /* VTT = Set LDO3 to sync mode */ + ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3)); if (ret < 0) return ret; - ret &= ~STPMU1_LDO3_MODE; - ret &= ~STPMU1_LDO12356_OUTPUT_MASK; - ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT; + ret &= ~STPMIC1_LDO3_MODE; + ret &= ~STPMIC1_LDO12356_VOUT_MASK; + ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL); - ret = pmic_reg_write(dev, STPMU1_LDOX_CTRL_REG(STPMU1_LDO3), + ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), ret); if (ret < 0) return ret; - /* Set BUCK2 to 1.35V */ + /* VDD_DDR = Set BUCK2 to 1.35V */ ret = pmic_clrsetbits(dev, - STPMU1_BUCKX_CTRL_REG(STPMU1_BUCK2), - STPMU1_BUCK_OUTPUT_MASK, - STPMU1_BUCK2_1350000V); + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), + STPMIC1_BUCK_VOUT_MASK, + STPMIC1_BUCK2_1350000V); if (ret < 0) return ret; - /* Enable BUCK2 and VREF */ + /* Enable VDD_DDR = BUCK2 */ ret = pmic_clrsetbits(dev, - STPMU1_BUCKX_CTRL_REG(STPMU1_BUCK2), - STPMU1_BUCK_EN, STPMU1_BUCK_EN); + STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2), + STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA); if (ret < 0) return ret; - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - ret = pmic_clrsetbits(dev, STPMU1_VREF_CTRL_REG, - STPMU1_VREF_EN, STPMU1_VREF_EN); + /* Enable VREF */ + ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR, + STPMIC1_VREF_ENA, STPMIC1_VREF_ENA); if (ret < 0) return ret; - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); /* Enable LDO3 */ ret = pmic_clrsetbits(dev, - STPMU1_LDOX_CTRL_REG(STPMU1_LDO3), - STPMU1_LDO_EN, STPMU1_LDO_EN); + STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3), + STPMIC1_LDO_ENA, STPMIC1_LDO_ENA); if (ret < 0) return ret; - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); return 0; } diff --git a/board/st/stm32mp1/spl.c b/board/st/stm32mp1/spl.c index f3db0d6..a7844f2 100644 --- a/board/st/stm32mp1/spl.c +++ b/board/st/stm32mp1/spl.c @@ -11,22 +11,22 @@ #include <asm/io.h> #include <post.h> #include <power/pmic.h> -#include <power/stpmu1.h> +#include <power/stpmic1.h> #include <asm/arch/ddr.h> void spl_board_init(void) { /* Keep vdd on during the reset cycle */ -#if defined(CONFIG_PMIC_STPMU1) && defined(CONFIG_SPL_POWER_SUPPORT) +#if defined(CONFIG_PMIC_STPMIC1) && defined(CONFIG_SPL_POWER_SUPPORT) struct udevice *dev; int ret; ret = uclass_get_device_by_driver(UCLASS_PMIC, - DM_GET_DRIVER(pmic_stpmu1), &dev); + DM_GET_DRIVER(pmic_stpmic1), &dev); if (!ret) pmic_clrsetbits(dev, - STPMU1_MASK_RESET_BUCK, - STPMU1_MASK_RESET_BUCK3, - STPMU1_MASK_RESET_BUCK3); + STPMIC1_BUCKS_MRST_CR, + STPMIC1_MRST_BUCK(STPMIC1_BUCK3), + STPMIC1_MRST_BUCK(STPMIC1_BUCK3)); #endif } diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c index 54feca0..24d299a 100644 --- a/board/st/stm32mp1/stm32mp1.c +++ b/board/st/stm32mp1/stm32mp1.c @@ -2,20 +2,57 @@ /* * Copyright (C) 2018, STMicroelectronics - All Rights Reserved */ -#include <config.h> #include <common.h> -#include <led.h> +#include <adc.h> +#include <config.h> #include <clk.h> #include <dm.h> #include <generic-phy.h> +#include <led.h> +#include <misc.h> #include <phy.h> #include <reset.h> +#include <syscon.h> #include <usb.h> -#include <asm/arch/stm32.h> #include <asm/io.h> +#include <asm/gpio.h> +#include <asm/arch/stm32.h> #include <power/regulator.h> #include <usb/dwc2_udc.h> +/* SYSCFG registers */ +#define SYSCFG_BOOTR 0x00 +#define SYSCFG_PMCSETR 0x04 +#define SYSCFG_IOCTRLSETR 0x18 +#define SYSCFG_ICNR 0x1C +#define SYSCFG_CMPCR 0x20 +#define SYSCFG_CMPENSETR 0x24 +#define SYSCFG_PMCCLRR 0x44 + +#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) +#define SYSCFG_BOOTR_BOOTPD_SHIFT 4 + +#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) +#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) +#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) +#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) +#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) + +#define SYSCFG_CMPCR_SW_CTRL BIT(1) +#define SYSCFG_CMPCR_READY BIT(8) + +#define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16) +#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17) + +#define SYSCFG_PMCSETR_ETH_SELMII BIT(20) + +#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21) +#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII (0 << 21) +#define SYSCFG_PMCSETR_ETH_SEL_RGMII (1 << 21) +#define SYSCFG_PMCSETR_ETH_SEL_RMII (4 << 21) + /* * Get a global data pointer */ @@ -26,6 +63,98 @@ DECLARE_GLOBAL_DATA_PTR; #define STM32MP_GGPIO 0x38 #define STM32MP_GGPIO_VBUS_SENSING BIT(21) +#define USB_WARNING_LOW_THRESHOLD_UV 660000 +#define USB_START_LOW_THRESHOLD_UV 1230000 +#define USB_START_HIGH_THRESHOLD_UV 2100000 + +int checkboard(void) +{ + int ret; + char *mode; + u32 otp; + struct udevice *dev; + const char *fdt_compat; + int fdt_compat_len; + + if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED)) + mode = "trusted"; + else + mode = "basic"; + + printf("Board: stm32mp1 in %s mode", mode); + fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible", + &fdt_compat_len); + if (fdt_compat && fdt_compat_len) + printf(" (%s)", fdt_compat); + puts("\n"); + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + + if (!ret) + ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD), + &otp, sizeof(otp)); + if (!ret && otp) { + printf("Board: MB%04x Var%d Rev.%c-%02d\n", + otp >> 16, + (otp >> 12) & 0xF, + ((otp >> 8) & 0xF) - 1 + 'A', + otp & 0xF); + } + + return 0; +} + +static void board_key_check(void) +{ +#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG) + ofnode node; + struct gpio_desc gpio; + enum forced_boot_mode boot_mode = BOOT_NORMAL; + + node = ofnode_path("/config"); + if (!ofnode_valid(node)) { + debug("%s: no /config node?\n", __func__); + return; + } +#ifdef CONFIG_FASTBOOT + if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0, + &gpio, GPIOD_IS_IN)) { + debug("%s: could not find a /config/st,fastboot-gpios\n", + __func__); + } else { + if (dm_gpio_get_value(&gpio)) { + puts("Fastboot key pressed, "); + boot_mode = BOOT_FASTBOOT; + } + + dm_gpio_free(NULL, &gpio); + } +#endif +#ifdef CONFIG_CMD_STM32PROG + if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0, + &gpio, GPIOD_IS_IN)) { + debug("%s: could not find a /config/st,stm32prog-gpios\n", + __func__); + } else { + if (dm_gpio_get_value(&gpio)) { + puts("STM32Programmer key pressed, "); + boot_mode = BOOT_STM32PROG; + } + dm_gpio_free(NULL, &gpio); + } +#endif + + if (boot_mode != BOOT_NORMAL) { + puts("entering download mode...\n"); + clrsetbits_le32(TAMP_BOOT_CONTEXT, + TAMP_BOOT_FORCED_MASK, + boot_mode); + } +#endif +} + static struct dwc2_plat_otg_data stm32mp_otg_data = { .usb_gusbcfg = STM32MP_GUSBCFG, }; @@ -170,6 +299,145 @@ clk_err: return ret; } +static int get_led(struct udevice **dev, char *led_string) +{ + char *led_name; + int ret; + + led_name = fdtdec_get_config_string(gd->fdt_blob, led_string); + if (!led_name) { + pr_debug("%s: could not find %s config string\n", + __func__, led_string); + return -ENOENT; + } + ret = led_get_by_label(led_name, dev); + if (ret) { + debug("%s: get=%d\n", __func__, ret); + return ret; + } + + return 0; +} + +static int setup_led(enum led_state_t cmd) +{ + struct udevice *dev; + int ret; + + ret = get_led(&dev, "u-boot,boot-led"); + if (ret) + return ret; + + ret = led_set_state(dev, cmd); + return ret; +} + +static int board_check_usb_power(void) +{ + struct ofnode_phandle_args adc_args; + struct udevice *adc; + struct udevice *led; + ofnode node; + unsigned int raw; + int max_uV = 0; + int ret, uV, adc_count; + u8 i, nb_blink; + + node = ofnode_path("/config"); + if (!ofnode_valid(node)) { + debug("%s: no /config node?\n", __func__); + return -ENOENT; + } + + /* + * Retrieve the ADC channels devices and get measurement + * for each of them + */ + adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd", + "#io-channel-cells"); + if (adc_count < 0) { + if (adc_count == -ENOENT) + return 0; + + pr_err("%s: can't find adc channel (%d)\n", __func__, + adc_count); + + return adc_count; + } + + for (i = 0; i < adc_count; i++) { + if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd", + "#io-channel-cells", 0, i, + &adc_args)) { + pr_debug("%s: can't find /config/st,adc_usb_pd\n", + __func__); + return 0; + } + + ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node, + &adc); + + if (ret) { + pr_err("%s: Can't get adc device(%d)\n", __func__, + ret); + return ret; + } + + ret = adc_channel_single_shot(adc->name, adc_args.args[0], + &raw); + if (ret) { + pr_err("%s: single shot failed for %s[%d]!\n", + __func__, adc->name, adc_args.args[0]); + return ret; + } + /* Convert to uV */ + if (!adc_raw_to_uV(adc, raw, &uV)) { + if (uV > max_uV) + max_uV = uV; + pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__, + adc->name, adc_args.args[0], raw, uV); + } else { + pr_err("%s: Can't get uV value for %s[%d]\n", + __func__, adc->name, adc_args.args[0]); + } + } + + /* + * If highest value is inside 1.23 Volts and 2.10 Volts, that means + * board is plugged on an USB-C 3A power supply and boot process can + * continue. + */ + if (max_uV > USB_START_LOW_THRESHOLD_UV && + max_uV < USB_START_HIGH_THRESHOLD_UV) + return 0; + + /* Display warning message and make u-boot,error-led blinking */ + pr_err("\n*******************************************\n"); + + if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) { + pr_err("* WARNING 500mA power supply detected *\n"); + nb_blink = 2; + } else { + pr_err("* WARNING 1.5A power supply detected *\n"); + nb_blink = 3; + } + + pr_err("* Current too low, use a 3A power supply! *\n"); + pr_err("*******************************************\n\n"); + + ret = get_led(&led, "u-boot,error-led"); + if (ret) + return ret; + + for (i = 0; i < nb_blink * 2; i++) { + led_set_state(led, LEDST_TOGGLE); + mdelay(125); + } + led_set_state(led, LEDST_ON); + + return 0; +} + int board_usb_cleanup(int index, enum usb_init_type init) { /* Reset usbotg */ @@ -180,19 +448,146 @@ int board_usb_cleanup(int index, enum usb_init_type init) return 0; } -int board_late_init(void) +static void sysconf_init(void) { - return 0; +#ifndef CONFIG_STM32MP1_TRUSTED + u8 *syscfg; +#ifdef CONFIG_DM_REGULATOR + struct udevice *pwr_dev; + struct udevice *pwr_reg; + struct udevice *dev; + int ret; + u32 otp = 0; +#endif + u32 bootr; + + syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); + + /* interconnect update : select master using the port 1 */ + /* LTDC = AXI_M9 */ + /* GPU = AXI_M8 */ + /* today information is hardcoded in U-Boot */ + writel(BIT(9), syscfg + SYSCFG_ICNR); + + /* disable Pull-Down for boot pin connected to VDD */ + bootr = readl(syscfg + SYSCFG_BOOTR); + bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT); + bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT; + writel(bootr, syscfg + SYSCFG_BOOTR); + +#ifdef CONFIG_DM_REGULATOR + /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI + * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. + * The customer will have to disable this for low frequencies + * or if AFMUX is selected but the function not used, typically for + * TRACE. Otherwise, impact on power consumption. + * + * WARNING: + * enabling High Speed mode while VDD>2.7V + * with the OTP product_below_2v5 (OTP 18, BIT 13) + * erroneously set to 1 can damage the IC! + * => U-Boot set the register only if VDD < 2.7V (in DT) + * but this value need to be consistent with board design + */ + ret = syscon_get_by_driver_data(STM32MP_SYSCON_PWR, &pwr_dev); + if (!ret) { + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(stm32mp_bsec), + &dev); + if (ret) { + pr_err("Can't find stm32mp_bsec driver\n"); + return; + } + + ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4); + if (!ret) + otp = otp & BIT(13); + + /* get VDD = pwr-supply */ + ret = device_get_supply_regulator(pwr_dev, "pwr-supply", + &pwr_reg); + + /* check if VDD is Low Voltage */ + if (!ret) { + if (regulator_get_value(pwr_reg) < 2700000) { + writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE | + SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | + SYSCFG_IOCTRLSETR_HSLVEN_ETH | + SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | + SYSCFG_IOCTRLSETR_HSLVEN_SPI, + syscfg + SYSCFG_IOCTRLSETR); + + if (!otp) + pr_err("product_below_2v5=0: HSLVEN protected by HW\n"); + } else { + if (otp) + pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n"); + } + } else { + debug("VDD unknown"); + } + } +#endif + + /* activate automatic I/O compensation + * warning: need to ensure CSI enabled and ready in clock driver + */ + writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR); + + while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY)) + ; + clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); +#endif } /* board dependent setup after realloc */ int board_init(void) { + struct udevice *dev; + /* address of boot parameters */ gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100; + /* probe all PINCTRL for hog */ + for (uclass_first_device(UCLASS_PINCTRL, &dev); + dev; + uclass_next_device(&dev)) { + pr_debug("probe pincontrol = %s\n", dev->name); + } + + board_key_check(); + + sysconf_init(); + if (IS_ENABLED(CONFIG_LED)) led_default_state(); return 0; } + +int board_late_init(void) +{ +#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG + const void *fdt_compat; + int fdt_compat_len; + + fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible", + &fdt_compat_len); + if (fdt_compat && fdt_compat_len) { + if (strncmp(fdt_compat, "st,", 3) != 0) + env_set("board_name", fdt_compat); + else + env_set("board_name", fdt_compat + 3); + } +#endif + + /* for DK1/DK2 boards */ + board_check_usb_power(); + + return 0; +} + +void board_quiesce_devices(void) +{ + setup_led(LEDST_OFF); +} diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS index 8dd0da4..338f374 100644 --- a/board/sunxi/MAINTAINERS +++ b/board/sunxi/MAINTAINERS @@ -341,6 +341,11 @@ M: FUKAUMI Naoki <naobsd@gmail.com> S: Maintained F: configs/Nintendo_NES_Classic_Edition_defconfig +OCEANIC 5205 5INMFD BOARD +M: Jagan Teki <jagan@amarulasolutions.com> +S: Maintained +F: configs/oceanic_5205_5inmfd_defconfig + OLIMEX A20-SOM204 BOARD M: Stefan Mavrodiev <stefan@olimex.com> S: Maintained diff --git a/board/theadorable/theadorable.c b/board/theadorable/theadorable.c index dd6def5..d423503 100644 --- a/board/theadorable/theadorable.c +++ b/board/theadorable/theadorable.c @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2015-2016 Stefan Roese <sr@denx.de> + * Copyright (C) 2015-2019 Stefan Roese <sr@denx.de> */ #include <common.h> +#include <console.h> #include <i2c.h> #include <pci.h> +#if !defined(CONFIG_SPL_BUILD) +#include <bootcount.h> +#endif #include <asm/gpio.h> #include <asm/io.h> #include <asm/arch/cpu.h> @@ -42,6 +46,7 @@ DECLARE_GLOBAL_DATA_PTR; #define STM_I2C_BUS 1 #define STM_I2C_ADDR 0x27 #define REBOOT_DELAY 1000 /* reboot-delay in ms */ +#define ABORT_TIMEOUT 3000 /* 3 seconds reboot abort timeout */ /* DDR3 static configuration */ static MV_DRAM_MC_INIT ddr3_theadorable[MV_MAX_DDR3_STATIC_SIZE] = { @@ -127,15 +132,15 @@ MV_DRAM_MODES *ddr3_get_static_ddr_mode(void) return &board_ddr_modes[0]; } -MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode) +MV_BIN_SERDES_CFG *board_serdes_cfg_get(void) { return &theadorable_serdes_cfg[0]; } u8 board_sat_r_get(u8 dev_num, u8 reg) { - /* Bit 0 enables PCI 2.0 link capabilities instead of PCI 1.x */ - return 0x01; + /* Bit x enables PCI 2.0 link capabilities instead of PCI 1.x */ + return 0xe; /* PEX port 0 is PCIe Gen1, PEX port 1..3 PCIe Gen2 */ } int board_early_init_f(void) @@ -218,7 +223,7 @@ int board_eth_init(bd_t *bis) } #endif -#ifdef CONFIG_BOARD_LATE_INIT +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_BOARD_LATE_INIT) int board_late_init(void) { pci_dev_t bdf; @@ -232,6 +237,7 @@ int board_late_init(void) */ bdf = pci_find_device(PCI_VENDOR_ID_PLX, 0x8619, 0); if (bdf == -1) { + unsigned long start_time = get_timer(0); u8 i2c_buf[8]; int ret; @@ -239,6 +245,28 @@ int board_late_init(void) bootcount = bootcount_load(); printf("Failed to find PLX PEX-switch (bootcount=%ld)\n", bootcount); + + /* + * The user can exit this boot-loop in the error case by + * hitting Ctrl-C. So wait some time for this key here. + */ + printf("Continue booting with Ctrl-C, otherwise rebooting\n"); + do { + /* Handle control-c and timeouts */ + if (ctrlc()) { + printf("PEX error boot-loop aborted!\n"); + return 0; + } + } while (get_timer(start_time) < ABORT_TIMEOUT); + + + /* + * At this stage the bootcounter has not been incremented + * yet. We need to do this manually here to get an actually + * working bootcounter in this error case. + */ + bootcount_inc(); + if (bootcount > PEX_SWITCH_NOT_FOUNT_LIMIT) { printf("Issuing power-switch via uC!\n"); diff --git a/board/ti/am335x/board.c b/board/ti/am335x/board.c index d67f94a..2c32b92 100644 --- a/board/ti/am335x/board.c +++ b/board/ti/am335x/board.c @@ -875,157 +875,55 @@ int board_late_init(void) } #endif -#ifndef CONFIG_DM_ETH - -#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ - (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) -static void cpsw_control(int enabled) -{ - /* VTP can be added here */ - - return; -} - -static struct cpsw_slave_data cpsw_slaves[] = { +/* CPSW platdata */ +#if !CONFIG_IS_ENABLED(OF_CONTROL) +struct cpsw_slave_data slave_data[] = { { - .slave_reg_ofs = 0x208, - .sliver_reg_ofs = 0xd80, - .phy_addr = 0, + .slave_reg_ofs = CPSW_SLAVE0_OFFSET, + .sliver_reg_ofs = CPSW_SLIVER0_OFFSET, + .phy_addr = 0, }, { - .slave_reg_ofs = 0x308, - .sliver_reg_ofs = 0xdc0, - .phy_addr = 1, + .slave_reg_ofs = CPSW_SLAVE1_OFFSET, + .sliver_reg_ofs = CPSW_SLIVER1_OFFSET, + .phy_addr = 1, }, }; -static struct cpsw_platform_data cpsw_data = { - .mdio_base = CPSW_MDIO_BASE, +struct cpsw_platform_data am335_eth_data = { .cpsw_base = CPSW_BASE, - .mdio_div = 0xff, + .version = CPSW_CTRL_VERSION_2, + .bd_ram_ofs = CPSW_BD_OFFSET, + .ale_reg_ofs = CPSW_ALE_OFFSET, + .cpdma_reg_ofs = CPSW_CPDMA_OFFSET, + .mdio_div = CPSW_MDIO_DIV, + .host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, .channels = 8, - .cpdma_reg_ofs = 0x800, - .slaves = 1, - .slave_data = cpsw_slaves, - .ale_reg_ofs = 0xd00, + .slaves = 2, + .slave_data = slave_data, .ale_entries = 1024, - .host_port_reg_ofs = 0x108, - .hw_stats_reg_ofs = 0x900, .bd_ram_ofs = 0x2000, - .mac_control = (1 << 5), - .control = cpsw_control, - .host_port_num = 0, - .version = CPSW_CTRL_VERSION_2, + .mac_control = 0x20, + .active_slave = 0, + .mdio_base = 0x4a101000, + .gmii_sel = 0x44e10650, + .phy_sel_compat = "ti,am3352-cpsw-phy-sel", + .syscon_addr = 0x44e10630, + .macid_sel_compat = "cpsw,am33xx", }; -#endif - -#if ((defined(CONFIG_SPL_ETH_SUPPORT) || defined(CONFIG_SPL_USB_ETHER)) &&\ - defined(CONFIG_SPL_BUILD)) || \ - ((defined(CONFIG_DRIVER_TI_CPSW) || \ - defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)) && \ - !defined(CONFIG_SPL_BUILD)) -/* - * This function will: - * Read the eFuse for MAC addresses, and set ethaddr/eth1addr/usbnet_devaddr - * in the environment - * Perform fixups to the PHY present on certain boards. We only need this - * function in: - * - SPL with either CPSW or USB ethernet support - * - Full U-Boot, with either CPSW or USB ethernet - * Build in only these cases to avoid warnings about unused variables - * when we build an SPL that has neither option but full U-Boot will. - */ -int board_eth_init(bd_t *bis) -{ - int rv, n = 0; -#if defined(CONFIG_USB_ETHER) && \ - (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USB_ETHER)) - uint8_t mac_addr[6]; - uint32_t mac_hi, mac_lo; - - /* - * use efuse mac address for USB ethernet as we know that - * both CPSW and USB ethernet will never be active at the same time - */ - mac_lo = readl(&cdev->macid0l); - mac_hi = readl(&cdev->macid0h); - mac_addr[0] = mac_hi & 0xFF; - mac_addr[1] = (mac_hi & 0xFF00) >> 8; - mac_addr[2] = (mac_hi & 0xFF0000) >> 16; - mac_addr[3] = (mac_hi & 0xFF000000) >> 24; - mac_addr[4] = mac_lo & 0xFF; - mac_addr[5] = (mac_lo & 0xFF00) >> 8; -#endif - - -#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ - (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) - -#ifdef CONFIG_DRIVER_TI_CPSW - if (board_is_bone() || board_is_bone_lt() || board_is_bben() || - board_is_idk()) { - writel(MII_MODE_ENABLE, &cdev->miisel); - cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if = - PHY_INTERFACE_MODE_MII; - } else if (board_is_icev2()) { - writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE, &cdev->miisel); - cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RMII; - cpsw_slaves[1].phy_if = PHY_INTERFACE_MODE_RMII; - cpsw_slaves[0].phy_addr = 1; - cpsw_slaves[1].phy_addr = 3; - } else { - writel((RGMII_MODE_ENABLE | RGMII_INT_DELAY), &cdev->miisel); - cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if = - PHY_INTERFACE_MODE_RGMII; - } - - rv = cpsw_register(&cpsw_data); - if (rv < 0) - printf("Error %d registering CPSW switch\n", rv); - else - n += rv; -#endif +struct eth_pdata cpsw_pdata = { + .iobase = 0x4a100000, + .phy_interface = 0, + .priv_pdata = &am335_eth_data, +}; - /* - * - * CPSW RGMII Internal Delay Mode is not supported in all PVT - * operating points. So we must set the TX clock delay feature - * in the AR8051 PHY. Since we only support a single ethernet - * device in U-Boot, we only do this for the first instance. - */ -#define AR8051_PHY_DEBUG_ADDR_REG 0x1d -#define AR8051_PHY_DEBUG_DATA_REG 0x1e -#define AR8051_DEBUG_RGMII_CLK_DLY_REG 0x5 -#define AR8051_RGMII_TX_CLK_DLY 0x100 - - if (board_is_evm_sk() || board_is_gp_evm() || board_is_bben()) { - const char *devname; - devname = miiphy_get_current_dev(); - - miiphy_write(devname, 0x0, AR8051_PHY_DEBUG_ADDR_REG, - AR8051_DEBUG_RGMII_CLK_DLY_REG); - miiphy_write(devname, 0x0, AR8051_PHY_DEBUG_DATA_REG, - AR8051_RGMII_TX_CLK_DLY); - } -#endif -#if defined(CONFIG_USB_ETHER) && \ - (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USB_ETHER)) - if (is_valid_ethaddr(mac_addr)) - eth_env_set_enetaddr("usbnet_devaddr", mac_addr); - - rv = usb_eth_initialize(bis); - if (rv < 0) - printf("Error %d registering USB_ETHER\n", rv); - else - n += rv; -#endif - return n; -} +U_BOOT_DEVICE(am335x_eth) = { + .name = "eth_cpsw", + .platdata = &cpsw_pdata, +}; #endif -#endif /* CONFIG_DM_ETH */ - #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c index 784b2b0..52f5d6b 100644 --- a/board/ti/am65x/evm.c +++ b/board/ti/am65x/evm.c @@ -10,6 +10,7 @@ #include <common.h> #include <asm/io.h> #include <spl.h> +#include <asm/arch/sys_proto.h> DECLARE_GLOBAL_DATA_PTR; @@ -66,3 +67,16 @@ int board_fit_config_name_match(const char *name) return -1; } #endif + +#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) +int ft_board_setup(void *blob, bd_t *bd) +{ + int ret; + + ret = fdt_fixup_msmc_ram(blob, "/interconnect@100000", "sram@70000000"); + if (ret) + printf("%s: fixing up msmc ram failed %d\n", __func__, ret); + + return ret; +} +#endif diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c index 060c471..179adc2 100644 --- a/board/ti/dra7xx/evm.c +++ b/board/ti/dra7xx/evm.c @@ -27,6 +27,7 @@ #include <environment.h> #include <dwc3-uboot.h> #include <dwc3-omap-uboot.h> +#include <i2c.h> #include <ti-usb-phy-uboot.h> #include <miiphy.h> @@ -55,6 +56,10 @@ DECLARE_GLOBAL_DATA_PTR; #define SYSINFO_BOARD_NAME_MAX_LEN 37 +/* I2C I/O Expander */ +#define NAND_PCF8575_ADDR 0x21 +#define NAND_PCF8575_I2C_BUS_NUM 0 + const struct omap_sysinfo sysinfo = { "Board: UNKNOWN(DRA7 EVM) REV UNKNOWN\n" }; @@ -777,6 +782,44 @@ void set_muxconf_regs(void) early_padconf, ARRAY_SIZE(early_padconf)); } +#if defined(CONFIG_NAND) +static int nand_sw_detect(void) +{ + int rc; + uchar data[2]; + struct udevice *dev; + + rc = i2c_get_chip_for_busnum(NAND_PCF8575_I2C_BUS_NUM, + NAND_PCF8575_ADDR, 0, &dev); + if (rc) + return -1; + + rc = dm_i2c_read(dev, 0, (uint8_t *)&data, sizeof(data)); + if (rc) + return -1; + + /* We are only interested in P10 and P11 on PCF8575 which is equal to + * bits 8 and 9. + */ + data[1] = data[1] & 0x3; + + /* Ensure only P11 is set and P10 is cleared. This ensures only + * NAND (P10) is configured and not NOR (P11) which are both low + * true signals. NAND and NOR settings should not be enabled at + * the same time. + */ + if (data[1] == 0x2) + return 0; + + return -1; +} +#else +int nand_sw_detect(void) +{ + return -1; +} +#endif + #ifdef CONFIG_IODELAY_RECALIBRATION void recalibrate_iodelay(void) { @@ -796,6 +839,19 @@ void recalibrate_iodelay(void) npads = ARRAY_SIZE(dra71x_core_padconf_array); iodelay = dra71_iodelay_cfg_array; niodelays = ARRAY_SIZE(dra71_iodelay_cfg_array); + /* If SW8 on the EVM is set to enable NAND then + * overwrite the pins used by VOUT3 with NAND. + */ + if (!nand_sw_detect()) { + delta_pads = dra71x_nand_padconf_array; + delta_npads = + ARRAY_SIZE(dra71x_nand_padconf_array); + } else { + delta_pads = dra71x_vout3_padconf_array; + delta_npads = + ARRAY_SIZE(dra71x_vout3_padconf_array); + } + } else if (board_is_dra72x_revc_or_later()) { delta_pads = dra72x_rgmii_padconf_array_revc; delta_npads = diff --git a/board/ti/dra7xx/mux_data.h b/board/ti/dra7xx/mux_data.h index f1f6bd5..75da5cb 100644 --- a/board/ti/dra7xx/mux_data.h +++ b/board/ti/dra7xx/mux_data.h @@ -220,22 +220,6 @@ const struct pad_conf_entry dra72x_rgmii_padconf_array_revc[] = { }; const struct pad_conf_entry dra71x_core_padconf_array[] = { - {GPMC_AD0, (M3 | PIN_INPUT)}, /* gpmc_ad0.vout3_d0 */ - {GPMC_AD1, (M3 | PIN_INPUT)}, /* gpmc_ad1.vout3_d1 */ - {GPMC_AD2, (M3 | PIN_INPUT)}, /* gpmc_ad2.vout3_d2 */ - {GPMC_AD3, (M3 | PIN_INPUT)}, /* gpmc_ad3.vout3_d3 */ - {GPMC_AD4, (M3 | PIN_INPUT)}, /* gpmc_ad4.vout3_d4 */ - {GPMC_AD5, (M3 | PIN_INPUT)}, /* gpmc_ad5.vout3_d5 */ - {GPMC_AD6, (M3 | PIN_INPUT)}, /* gpmc_ad6.vout3_d6 */ - {GPMC_AD7, (M3 | PIN_INPUT)}, /* gpmc_ad7.vout3_d7 */ - {GPMC_AD8, (M3 | PIN_INPUT)}, /* gpmc_ad8.vout3_d8 */ - {GPMC_AD9, (M3 | PIN_INPUT)}, /* gpmc_ad9.vout3_d9 */ - {GPMC_AD10, (M3 | PIN_INPUT)}, /* gpmc_ad10.vout3_d10 */ - {GPMC_AD11, (M3 | PIN_INPUT)}, /* gpmc_ad11.vout3_d11 */ - {GPMC_AD12, (M3 | PIN_INPUT)}, /* gpmc_ad12.vout3_d12 */ - {GPMC_AD13, (M3 | PIN_INPUT)}, /* gpmc_ad13.vout3_d13 */ - {GPMC_AD14, (M3 | PIN_INPUT)}, /* gpmc_ad14.vout3_d14 */ - {GPMC_AD15, (M3 | PIN_INPUT)}, /* gpmc_ad15.vout3_d15 */ {GPMC_A0, (M3 | PIN_INPUT_PULLDOWN)}, /* gpmc_a0.vout3_d16 */ {GPMC_A1, (M3 | PIN_INPUT_PULLDOWN)}, /* gpmc_a1.vout3_d17 */ {GPMC_A2, (M3 | PIN_INPUT_PULLDOWN)}, /* gpmc_a2.vout3_d18 */ @@ -370,6 +354,50 @@ const struct pad_conf_entry dra71x_core_padconf_array[] = { {WAKEUP3, (M1 | PULL_ENA | PULL_UP)}, /* Wakeup3.sys_nirq1 */ }; +const struct pad_conf_entry dra71x_vout3_padconf_array[] = { + {GPMC_AD0, (M3 | PIN_INPUT)}, /* gpmc_ad0.vout3_d0 */ + {GPMC_AD1, (M3 | PIN_INPUT)}, /* gpmc_ad1.vout3_d1 */ + {GPMC_AD2, (M3 | PIN_INPUT)}, /* gpmc_ad2.vout3_d2 */ + {GPMC_AD3, (M3 | PIN_INPUT)}, /* gpmc_ad3.vout3_d3 */ + {GPMC_AD4, (M3 | PIN_INPUT)}, /* gpmc_ad4.vout3_d4 */ + {GPMC_AD5, (M3 | PIN_INPUT)}, /* gpmc_ad5.vout3_d5 */ + {GPMC_AD6, (M3 | PIN_INPUT)}, /* gpmc_ad6.vout3_d6 */ + {GPMC_AD7, (M3 | PIN_INPUT)}, /* gpmc_ad7.vout3_d7 */ + {GPMC_AD8, (M3 | PIN_INPUT)}, /* gpmc_ad8.vout3_d8 */ + {GPMC_AD9, (M3 | PIN_INPUT)}, /* gpmc_ad9.vout3_d9 */ + {GPMC_AD10, (M3 | PIN_INPUT)}, /* gpmc_ad10.vout3_d10 */ + {GPMC_AD11, (M3 | PIN_INPUT)}, /* gpmc_ad11.vout3_d11 */ + {GPMC_AD12, (M3 | PIN_INPUT)}, /* gpmc_ad12.vout3_d12 */ + {GPMC_AD13, (M3 | PIN_INPUT)}, /* gpmc_ad13.vout3_d13 */ + {GPMC_AD14, (M3 | PIN_INPUT)}, /* gpmc_ad14.vout3_d14 */ + {GPMC_AD15, (M3 | PIN_INPUT)}, /* gpmc_ad15.vout3_d15 */ +}; + +const struct pad_conf_entry dra71x_nand_padconf_array[] = { + {GPMC_AD0, (M0 | PIN_INPUT)}, /* gpmc_ad0.gpmc_ad0 */ + {GPMC_AD1, (M0 | PIN_INPUT)}, /* gpmc_ad1.gpmc_ad1 */ + {GPMC_AD2, (M0 | PIN_INPUT)}, /* gpmc_ad2.gpmc_ad2 */ + {GPMC_AD3, (M0 | PIN_INPUT)}, /* gpmc_ad3.gpmc_ad3 */ + {GPMC_AD4, (M0 | PIN_INPUT)}, /* gpmc_ad4.gpmc_ad4 */ + {GPMC_AD5, (M0 | PIN_INPUT)}, /* gpmc_ad5.gpmc_ad5 */ + {GPMC_AD6, (M0 | PIN_INPUT)}, /* gpmc_ad6.gpmc_ad6 */ + {GPMC_AD7, (M0 | PIN_INPUT)}, /* gpmc_ad7.gpmc_ad7 */ + {GPMC_AD8, (M0 | PIN_INPUT)}, /* gpmc_ad8.gpmc_ad8 */ + {GPMC_AD9, (M0 | PIN_INPUT)}, /* gpmc_ad9.gpmc_ad9 */ + {GPMC_AD10, (M0 | PIN_INPUT)}, /* gpmc_ad10.gpmc_ad10 */ + {GPMC_AD11, (M0 | PIN_INPUT)}, /* gpmc_ad11.gpmc_ad11 */ + {GPMC_AD12, (M0 | PIN_INPUT)}, /* gpmc_ad12.gpmc_ad12 */ + {GPMC_AD13, (M0 | PIN_INPUT)}, /* gpmc_ad13.gpmc_ad13 */ + {GPMC_AD14, (M0 | PIN_INPUT)}, /* gpmc_ad14.gpmc_ad14 */ + {GPMC_AD15, (M0 | PIN_INPUT)}, /* gpmc_ad15.gpmc_ad15 */ + {GPMC_CS0, (M0 | PIN_INPUT_PULLUP)}, /* gpmc_cs0.gpmc_cs0 */ + {GPMC_ADVN_ALE, (M0 | PIN_INPUT_PULLDOWN)}, /* gpmc_advn_ale.gpmc_advn_ale */ + {GPMC_OEN_REN, (M0 | PIN_INPUT_PULLUP)}, /* gpmc_oen_ren.gpmc_oen_ren */ + {GPMC_WEN, (M0 | PIN_INPUT_PULLUP)}, /* gpmc_wen.gpmc_wen */ + {GPMC_BEN0, (M0 | PIN_INPUT_PULLDOWN)}, /* gpmc_ben0.gpmc_ben0 */ + {GPMC_WAIT0, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* gpmc_wait0.gpmc_wait0 */ +}; + const struct pad_conf_entry early_padconf[] = { {UART1_RXD, (PIN_INPUT_SLEW | M0)}, /* UART1_RXD */ {UART1_TXD, (PIN_INPUT_SLEW | M0)}, /* UART1_TXD */ diff --git a/board/ti/ks2_evm/board_k2g.c b/board/ti/ks2_evm/board_k2g.c index 39a782e..6d0fc21 100644 --- a/board/ti/ks2_evm/board_k2g.c +++ b/board/ti/ks2_evm/board_k2g.c @@ -315,6 +315,21 @@ int embedded_dtb_select(void) BIT(9)); setbits_le32(K2G_GPIO1_BANK2_BASE + K2G_GPIO_SETDATA_OFFSET, BIT(9)); + } else if (board_is_k2g_ice()) { + /* GBE Phy workaround. For Phy to latch the input + * configuration, a GPIO reset is asserted at the + * Phy reset pin to latch configuration correctly after SoC + * reset. GPIO0 Pin 10 (Ball AA20) is used for this on ICE + * board. Just do a low to high transition. + */ + clrbits_le32(K2G_GPIO0_BANK0_BASE + K2G_GPIO_DIR_OFFSET, + BIT(10)); + setbits_le32(K2G_GPIO0_BANK0_BASE + K2G_GPIO_CLRDATA_OFFSET, + BIT(10)); + /* Delay just to get a transition to high */ + udelay(100); + setbits_le32(K2G_GPIO0_BANK0_BASE + K2G_GPIO_SETDATA_OFFSET, + BIT(10)); } return 0; diff --git a/board/ti/ks2_evm/mux-k2g.h b/board/ti/ks2_evm/mux-k2g.h index 706fb7e..89c49f9 100644 --- a/board/ti/ks2_evm/mux-k2g.h +++ b/board/ti/ks2_evm/mux-k2g.h @@ -125,21 +125,23 @@ struct pin_cfg k2g_evm_pin_cfg[] = { { 70, MODE(0) }, /* SOC_MMC1_SDWP */ { 71, MODE(0) }, /* MMC1POW TP124 */ - /* RGMII */ - { 72, MODE(1) | PIN_IEN }, /* SOC_RGMII_RXCLK */ - { 77, MODE(1) | PIN_IEN }, /* SOC_RGMII_RXD3 */ - { 78, MODE(1) | PIN_IEN }, /* SOC_RGMII_RXD2 */ - { 79, MODE(1) | PIN_IEN }, /* SOC_RGMII_RXD1 */ - { 80, MODE(1) | PIN_IEN }, /* SOC_RGMII_RXD0 */ - { 81, MODE(1) | PIN_IEN }, /* SOC_RGMII_RXCTL */ - { 85, MODE(1) }, /* SOC_RGMII_TXCLK */ - { 91, MODE(1) }, /* SOC_RGMII_TXD3 */ - { 92, MODE(1) }, /* SOC_RGMII_TXD2 */ - { 93, MODE(1) }, /* SOC_RGMII_TXD1 */ - { 94, MODE(1) }, /* SOC_RGMII_TXD0 */ - { 95, MODE(1) }, /* SOC_RGMII_TXCTL */ - { 98, MODE(0) }, /* SOC_MDIO_DATA */ - { 99, MODE(0) }, /* SOC_MDIO_CLK */ + /* EMAC */ + { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */ + { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */ + { 77, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD3 */ + { 80, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD0 */ + { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */ + { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */ + { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */ + { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */ + { 85, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXC */ + { 95, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXCTL */ + { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */ + { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */ + + /* MDIO */ + { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */ + { 98, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_DATA */ /* PWM */ { 73, MODE(4) }, /* SOC_EHRPWM3A */ @@ -346,6 +348,25 @@ struct pin_cfg k2g_ice_evm_pin_cfg[] = { { 133, MODE(0) }, /* SOC_QSPI_D2 */ { 134, MODE(0) }, /* SOC_QSPI_D3 */ { 135, MODE(0) }, /* SOC_QSPI_CSN0 */ + + /* EMAC */ + { 79, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD1 */ + { 78, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD2 */ + { 77, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD3 */ + { 80, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXD0 */ + { 94, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD0 */ + { 93, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD1 */ + { 92, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD2 */ + { 91, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXD3 */ + { 85, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXC */ + { 95, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_TXCTL */ + { 72, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXC */ + { 81, BUFFER_CLASS_D | PIN_PDIS | MODE(1) }, /* RGMII_RXCTL */ + + /* MDIO */ + { 99, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_CLK */ + { 98, BUFFER_CLASS_B | PIN_PDIS | MODE(0) }, /* MDIO_DATA */ + { MAX_PIN_N, } }; diff --git a/cmd/Kconfig b/cmd/Kconfig index 0b07b3b..2bdbfcb 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1101,6 +1101,12 @@ config CMD_VIRTIO help VirtIO block device support +config CMD_WDT + bool "wdt" + depends on WDT + help + This provides commands to control the watchdog timer devices. + config CMD_AXI bool "axi" depends on AXI diff --git a/cmd/Makefile b/cmd/Makefile index acb85f4..6b1c6b0 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -142,6 +142,7 @@ obj-$(CONFIG_CMD_UBIFS) += ubifs.o obj-$(CONFIG_CMD_UNIVERSE) += universe.o obj-$(CONFIG_CMD_UNZIP) += unzip.o obj-$(CONFIG_CMD_VIRTIO) += virtio.o +obj-$(CONFIG_CMD_WDT) += wdt.o obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o obj-$(CONFIG_CMD_USB) += usb.o disk.o diff --git a/cmd/wdt.c b/cmd/wdt.c new file mode 100644 index 0000000..647d989 --- /dev/null +++ b/cmd/wdt.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Watchdog commands + * + * Copyright (c) 2019 Michael Walle <michael@walle.cc> + */ + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <wdt.h> + +static struct udevice *currdev; + +static int do_wdt_list(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_WDT, &uc); + if (ret) + return CMD_RET_FAILURE; + + uclass_foreach_dev(dev, uc) + printf("%s (%s)\n", dev->name, dev->driver->name); + + return CMD_RET_SUCCESS; +} + +static int do_wdt_dev(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + if (argc > 1) { + ret = uclass_get_device_by_name(UCLASS_WDT, argv[1], &currdev); + if (ret) { + printf("Can't get the watchdog timer: %s\n", argv[1]); + return CMD_RET_FAILURE; + } + } else { + if (!currdev) { + printf("No watchdog timer device set!\n"); + return CMD_RET_FAILURE; + } + printf("dev: %s\n", currdev->name); + } + + return CMD_RET_SUCCESS; +} + +static int check_currdev(void) +{ + if (!currdev) { + printf("No device set, use 'wdt dev' first\n"); + return CMD_RET_FAILURE; + } + return 0; +} + +static int do_wdt_start(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + u64 timeout; + ulong flags = 0; + + if (argc < 2) + return CMD_RET_USAGE; + + ret = check_currdev(); + if (ret) + return ret; + + timeout = simple_strtoull(argv[1], NULL, 0); + if (argc > 2) + flags = simple_strtoul(argv[2], NULL, 0); + + ret = wdt_start(currdev, timeout, flags); + if (ret == -ENOSYS) { + printf("Starting watchdog timer not supported.\n"); + return CMD_RET_FAILURE; + } else if (ret) { + printf("Starting watchdog timer failed (%d)\n", ret); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_wdt_stop(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = check_currdev(); + if (ret) + return ret; + + ret = wdt_stop(currdev); + if (ret == -ENOSYS) { + printf("Stopping watchdog timer not supported.\n"); + return CMD_RET_FAILURE; + } else if (ret) { + printf("Stopping watchdog timer failed (%d)\n", ret); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_wdt_reset(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = check_currdev(); + if (ret) + return ret; + + ret = wdt_reset(currdev); + if (ret == -ENOSYS) { + printf("Resetting watchdog timer not supported.\n"); + return CMD_RET_FAILURE; + } else if (ret) { + printf("Resetting watchdog timer failed (%d)\n", ret); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static int do_wdt_expire(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + ulong flags = 0; + + ret = check_currdev(); + if (ret) + return ret; + + if (argc > 1) + flags = simple_strtoul(argv[1], NULL, 0); + + ret = wdt_expire_now(currdev, flags); + if (ret == -ENOSYS) { + printf("Expiring watchdog timer not supported.\n"); + return CMD_RET_FAILURE; + } else if (ret) { + printf("Expiring watchdog timer failed (%d)\n", ret); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +static char wdt_help_text[] = + "list - list watchdog devices\n" + "wdt dev [<name>] - get/set current watchdog device\n" + "wdt start <timeout ms> [flags] - start watchdog timer\n" + "wdt stop - stop watchdog timer\n" + "wdt reset - reset watchdog timer\n" + "wdt expire [flags] - expire watchdog timer immediately\n"; + +U_BOOT_CMD_WITH_SUBCMDS(wdt, "Watchdog sub-system", wdt_help_text, + U_BOOT_SUBCMD_MKENT(list, 1, 1, do_wdt_list), + U_BOOT_SUBCMD_MKENT(dev, 2, 1, do_wdt_dev), + U_BOOT_SUBCMD_MKENT(start, 3, 1, do_wdt_start), + U_BOOT_SUBCMD_MKENT(stop, 1, 1, do_wdt_stop), + U_BOOT_SUBCMD_MKENT(reset, 1, 1, do_wdt_reset), + U_BOOT_SUBCMD_MKENT(expire, 2, 1, do_wdt_expire)); diff --git a/common/fdt_support.c b/common/fdt_support.c index 42583e3..ab08a01 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -456,12 +456,6 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) if (!banks) return 0; - for (i = 0; i < banks; i++) - if (start[i] == 0 && size[i] == 0) - break; - - banks = i; - len = fdt_pack_reg(blob, tmp, start, size, banks); err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig index a6a237f..a396a39 100644 --- a/configs/am335x_evm_defconfig +++ b/configs/am335x_evm_defconfig @@ -7,14 +7,16 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_SPL_LOAD_FIT=y CONFIG_OF_BOARD_SETUP=y CONFIG_BOOTCOMMAND="if test ${boot_fit} -eq 1; then run update_to_fit; fi; run findfdt; run init_console; run envboot; run distro_bootcmd" +CONFIG_LOGLEVEL=3 CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_VERSION_VARIABLE=y CONFIG_ARCH_MISC_INIT=y +CONFIG_SPL_ETH_SUPPORT=y # CONFIG_SPL_FS_EXT4 is not set CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_MUSB_NEW_SUPPORT=y CONFIG_SPL_NET_SUPPORT=y -CONFIG_SPL_NET_VCI_STRING="AM33xx U-Boot SPL" +CONFIG_SPL_NET_VCI_STRING="AM335x U-Boot SPL" CONFIG_SPL_OS_BOOT=y CONFIG_SPL_USB_GADGET=y CONFIG_SPL_USB_ETHER=y @@ -31,6 +33,7 @@ CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="am335x-evm" CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2" CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_SPL_ENV_IS_NOWHERE=y CONFIG_BOOTCOUNT_LIMIT=y CONFIG_DFU_MMC=y CONFIG_DFU_NAND=y @@ -39,6 +42,7 @@ CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_DM_I2C=y CONFIG_MISC=y CONFIG_DM_MMC=y +# CONFIG_MMC_HW_PARTITIONING is not set CONFIG_MMC_OMAP_HS=y CONFIG_NAND=y CONFIG_DM_SPI_FLASH=y @@ -46,7 +50,6 @@ CONFIG_SPI_FLASH=y CONFIG_SF_DEFAULT_SPEED=24000000 CONFIG_SPI_FLASH_WINBOND=y CONFIG_DM_ETH=y -CONFIG_PHY_GIGE=y CONFIG_MII=y CONFIG_DRIVER_TI_CPSW=y CONFIG_SPI=y @@ -70,3 +73,4 @@ CONFIG_USB_ETHER=y CONFIG_DYNAMIC_CRC_TABLE=y CONFIG_RSA=y CONFIG_LZO=y +# CONFIG_OF_LIBFDT_OVERLAY is not set diff --git a/configs/am335x_guardian_defconfig b/configs/am335x_guardian_defconfig new file mode 100644 index 0000000..c25a1a9 --- /dev/null +++ b/configs/am335x_guardian_defconfig @@ -0,0 +1,90 @@ +CONFIG_ARM=y +CONFIG_ARCH_OMAP2PLUS=y +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_AM33XX=y +CONFIG_TARGET_AM335X_GUARDIAN=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_SPL=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTSTAGE_STASH_ADDR=0x0 +CONFIG_CONSOLE_MUX=y +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_VERSION_VARIABLE=y +CONFIG_ARCH_MISC_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_ETH_SUPPORT=y +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_MUSB_NEW_SUPPORT=y +CONFIG_SPL_NET_SUPPORT=y +CONFIG_SPL_NET_VCI_STRING="Guardian U-Boot SPL" +CONFIG_SPL_POWER_SUPPORT=y +CONFIG_SPL_USB_GADGET=y +CONFIG_SPL_USB_ETHER=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SPL_YMODEM_SUPPORT=y +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n" +CONFIG_AUTOBOOT_DELAY_STR="d" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_CMD_SPL=y +CONFIG_CMD_SPL_NAND_OFS=0x0 +CONFIG_CMD_ASKENV=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_MTD=y +CONFIG_CMD_NAND=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_MTDPARTS=y +CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(SPL),256k(SPL.backup1),256k(SPL.backup2),256k(SPL.backup3),1m(u-boot),1m(u-boot.backup1),256k(u-boot-env),256k(u-boot-env.backup1),-(UBI)" +CONFIG_CMD_UBI=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_DEFAULT_DEVICE_TREE="am335x-guardian" +CONFIG_ENV_IS_IN_NAND=y +CONFIG_SPL_ENV_IS_NOWHERE=y +CONFIG_SPL_DM=y +CONFIG_BOOTCOUNT_LIMIT=y +CONFIG_BOOTCOUNT_ENV=y +CONFIG_MISC=y +CONFIG_DM_MMC=y +CONFIG_MMC_OMAP_HS=y +CONFIG_MTD=y +CONFIG_NAND=y +CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y +CONFIG_SYS_NAND_U_BOOT_OFFS=0x100000 +CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND=0x200000 +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_PHYLIB=y +CONFIG_DM_ETH=y +CONFIG_PHY=y +CONFIG_NOP_PHY=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_USB=y +CONFIG_DM_USB_GADGET=y +CONFIG_SPL_DM_USB_GADGET=y +CONFIG_USB_MUSB_HOST=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_MUSB_TI=y +CONFIG_USB_MUSB_DSPS=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments" +CONFIG_USB_GADGET_VENDOR_NUM=0x0451 +CONFIG_USB_GADGET_PRODUCT_NUM=0xd022 +CONFIG_USB_ETHER=y +CONFIG_FAT_WRITE=y diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 3d71020..e5de833 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -40,9 +40,13 @@ CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_DM=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_REGMAP=y +CONFIG_SPL_SYSCON=y +CONFIG_SPL_OF_TRANSLATE=y CONFIG_DWC_AHCI=y CONFIG_DFU_MMC=y CONFIG_DFU_RAM=y +CONFIG_DFU_SF=y CONFIG_USB_FUNCTION_FASTBOOT=y CONFIG_FASTBOOT_BUF_ADDR=0x82000000 CONFIG_FASTBOOT_BUF_SIZE=0x2F000000 diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 8f6fd25..724b4bc 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -15,6 +15,7 @@ CONFIG_DISTRO_DEFAULTS=y CONFIG_NR_DRAM_BANKS=2 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_LOAD_FIT=y +CONFIG_OF_BOARD_SETUP=y CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y @@ -48,10 +49,11 @@ CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_CLK_TI_SCI=y +CONFIG_DMA_CHANNELS=y +CONFIG_TI_K3_NAVSS_UDMA=y CONFIG_TI_SCI_PROTOCOL=y CONFIG_DM_MAILBOX=y CONFIG_K3_SEC_PROXY=y -CONFIG_MISC=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_K3_ARASAN=y @@ -67,5 +69,6 @@ CONFIG_REMOTEPROC_K3=y CONFIG_DM_RESET=y CONFIG_RESET_TI_SCI=y CONFIG_DM_SERIAL=y +CONFIG_SOC_TI=y CONFIG_SYSRESET=y CONFIG_SYSRESET_TI_SCI=y diff --git a/configs/ap152_defconfig b/configs/ap152_defconfig new file mode 100644 index 0000000..21cb6eb --- /dev/null +++ b/configs/ap152_defconfig @@ -0,0 +1,49 @@ +CONFIG_MIPS=y +CONFIG_SYS_TEXT_BASE=0x9F000000 +CONFIG_SYS_MALLOC_F_LEN=0x800 +CONFIG_SYS_CACHE_SIZE_AUTO=y +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_DEBUG_UART_BASE=0xb8020000 +CONFIG_DEBUG_UART_CLOCK=25000000 +CONFIG_ARCH_ATH79=y +CONFIG_TARGET_AP152=y +CONFIG_DEBUG_UART=y +CONFIG_BOOTDELAY=3 +CONFIG_USE_BOOTARGS=y +CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs" +CONFIG_DISPLAY_CPUINFO=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SYS_PROMPT="ap152 # " +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_CRC32 is not set +CONFIG_CMD_MEMTEST=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_MTDPARTS=y +CONFIG_MTDIDS_DEFAULT="nor0=spi-flash.0" +CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-flash.0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1472k(uImage),64k(ART)" +# CONFIG_ISO_PARTITION is not set +CONFIG_DEFAULT_DEVICE_TREE="ap152" +CONFIG_ENV_IS_IN_SPI_FLASH=y +# CONFIG_NET is not set +CONFIG_DM_SPI_FLASH=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_SPI_FLASH_DATAFLASH=y +CONFIG_SPI_FLASH_MTD=y +CONFIG_PINCTRL=y +CONFIG_DM_SERIAL=y +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_DM_SPI=y +CONFIG_ATH79_SPI=y +CONFIG_LZMA=y diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig index 597618f..4e47346 100644 --- a/configs/bananapi_m2_plus_h3_defconfig +++ b/configs/bananapi_m2_plus_h3_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MACPWR="PD6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig index e7c10db..29dd892 100644 --- a/configs/bananapi_m2_plus_h5_defconfig +++ b/configs/bananapi_m2_plus_h5_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MACPWR="PD6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/bananapi_m2_zero_defconfig b/configs/bananapi_m2_zero_defconfig index 91302eb..8546674 100644 --- a/configs/bananapi_m2_zero_defconfig +++ b/configs/bananapi_m2_zero_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=408 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MMC0_CD_PIN="" # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/bcm963158_ram_defconfig b/configs/bcm963158_ram_defconfig index fc55e98..5659249 100644 --- a/configs/bcm963158_ram_defconfig +++ b/configs/bcm963158_ram_defconfig @@ -20,6 +20,7 @@ CONFIG_CMD_BOOTEFI_SELFTEST=y # CONFIG_CMD_LZMADEC is not set # CONFIG_CMD_UNZIP is not set # CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y CONFIG_CMD_CACHE=y CONFIG_DOS_PARTITION=y CONFIG_ISO_PARTITION=y @@ -28,6 +29,8 @@ CONFIG_DEFAULT_DEVICE_TREE="bcm963158" # CONFIG_NET is not set CONFIG_BLK=y CONFIG_CLK=y +CONFIG_DM_GPIO=y +CONFIG_BCM6345_GPIO=y # CONFIG_MMC is not set CONFIG_SPECIFY_CONSOLE_INDEX=y # CONFIG_SPL_SERIAL_PRESENT is not set diff --git a/configs/bcm968380gerg_ram_defconfig b/configs/bcm968380gerg_ram_defconfig index 61661bd..fa9dc85 100644 --- a/configs/bcm968380gerg_ram_defconfig +++ b/configs/bcm968380gerg_ram_defconfig @@ -24,6 +24,7 @@ CONFIG_CMD_LICENSE=y # CONFIG_CMD_CRC32 is not set CONFIG_CMD_MEMINFO=y # CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y # CONFIG_CMD_LOADS is not set # CONFIG_CMD_MISC is not set CONFIG_DEFAULT_DEVICE_TREE="brcm,bcm968380gerg" @@ -31,6 +32,7 @@ CONFIG_DEFAULT_DEVICE_TREE="brcm,bcm968380gerg" # CONFIG_DM_DEVICE_REMOVE is not set CONFIG_HAVE_BLOCK_DEVICE=y CONFIG_DM_GPIO=y +CONFIG_BCM6345_GPIO=y CONFIG_LED=y CONFIG_LED_BCM6328=y CONFIG_LED_BLINK=y diff --git a/configs/bcm968580xref_ram_defconfig b/configs/bcm968580xref_ram_defconfig index e8cb3a0..456ece7 100644 --- a/configs/bcm968580xref_ram_defconfig +++ b/configs/bcm968580xref_ram_defconfig @@ -15,6 +15,7 @@ CONFIG_SUPPORT_RAW_INITRD=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_HUSH_PARSER=y CONFIG_CMD_BOOTEFI_SELFTEST=y +CONFIG_CMD_GPIO=y CONFIG_DOS_PARTITION=y CONFIG_ISO_PARTITION=y CONFIG_EFI_PARTITION=y @@ -22,6 +23,8 @@ CONFIG_DEFAULT_DEVICE_TREE="bcm968580xref" # CONFIG_NET is not set CONFIG_BLK=y CONFIG_CLK=y +CONFIG_DM_GPIO=y +CONFIG_BCM6345_GPIO=y # CONFIG_MMC is not set CONFIG_SPECIFY_CONSOLE_INDEX=y # CONFIG_SPL_SERIAL_PRESENT is not set diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig index 41dae05..4b09ba1 100644 --- a/configs/da850evm_defconfig +++ b/configs/da850evm_defconfig @@ -1,4 +1,5 @@ CONFIG_ARM=y +CONFIG_SYS_THUMB_BUILD=y CONFIG_ARCH_DAVINCI=y CONFIG_SYS_TEXT_BASE=0xc1080000 CONFIG_TARGET_DA850EVM=y @@ -13,6 +14,7 @@ CONFIG_SPL_SPI_SUPPORT=y CONFIG_NR_DRAM_BANKS=1 CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH" CONFIG_BOOTDELAY=3 +CONFIG_DEFAULT_FDT_FILE="da850-evm.dtb" CONFIG_MISC_INIT_R=y CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_CPUINFO is not set @@ -20,6 +22,7 @@ CONFIG_VERSION_VARIABLE=y CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_SPI_LOAD=y CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="U-Boot > " @@ -39,10 +42,11 @@ CONFIG_CMD_DIAG=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="da850-evm" -CONFIG_SPL_OF_PLATDATA=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_DM=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_OF_TRANSLATE=y CONFIG_DM_GPIO=y CONFIG_DA8XX_GPIO=y CONFIG_DM_I2C=y diff --git a/configs/da850evm_nand_defconfig b/configs/da850evm_nand_defconfig index 48b7c2a..af5ba81 100644 --- a/configs/da850evm_nand_defconfig +++ b/configs/da850evm_nand_defconfig @@ -1,4 +1,5 @@ CONFIG_ARM=y +CONFIG_SYS_THUMB_BUILD=y CONFIG_ARCH_DAVINCI=y CONFIG_SYS_TEXT_BASE=0xc1080000 CONFIG_TARGET_DA850EVM=y @@ -12,12 +13,14 @@ CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH" CONFIG_BOOTDELAY=3 +CONFIG_DEFAULT_FDT_FILE="da850-evm.dtb" CONFIG_VERSION_VARIABLE=y # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_BOARDINFO is not set CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_NAND_SUPPORT=y CONFIG_SPL_SPI_LOAD=y CONFIG_HUSH_PARSER=y @@ -37,13 +40,15 @@ CONFIG_CMD_DIAG=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="da850-evm" -CONFIG_SPL_OF_PLATDATA=y CONFIG_ENV_IS_IN_NAND=y CONFIG_DM=y CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_SPL_OF_TRANSLATE=y CONFIG_DM_GPIO=y CONFIG_DA8XX_GPIO=y CONFIG_DM_I2C=y +CONFIG_DM_MMC=y CONFIG_NAND=y CONFIG_NAND_DAVINCI=y CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y diff --git a/configs/db-88f6820-amc_defconfig b/configs/db-88f6820-amc_defconfig index dcf2a25..e8ba518 100644 --- a/configs/db-88f6820-amc_defconfig +++ b/configs/db-88f6820-amc_defconfig @@ -41,7 +41,7 @@ CONFIG_CMD_FS_GENERIC=y CONFIG_EFI_PARTITION=y # CONFIG_PARTITION_UUIDS is not set # CONFIG_SPL_PARTITION_UUIDS is not set -CONFIG_DEFAULT_DEVICE_TREE="armada-385-amc" +CONFIG_DEFAULT_DEVICE_TREE="armada-385-db-88f6820-amc" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig index 98e47ee..078bd23 100644 --- a/configs/db-mv784mp-gp_defconfig +++ b/configs/db-mv784mp-gp_defconfig @@ -46,6 +46,7 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_SPL_OF_TRANSLATE=y CONFIG_SATA_MV=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_NAND=y CONFIG_NAND_PXA3XX=y diff --git a/configs/db-xc3-24g4xg_defconfig b/configs/db-xc3-24g4xg_defconfig new file mode 100644 index 0000000..0285ccaa --- /dev/null +++ b/configs/db-xc3-24g4xg_defconfig @@ -0,0 +1,55 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_TEXT_BASE=0x00800000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_DB_XC3_24G4XG=y +CONFIG_BUILD_TARGET="u-boot.kwb" +CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_CMD_MEMTEST=y +CONFIG_SYS_ALT_MEMTEST=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_I2C=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_UBI=y +CONFIG_DEFAULT_DEVICE_TREE="armada-xp-db-xc3-24g4xg" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_SPL_OF_TRANSLATE=y +CONFIG_BLK=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +# CONFIG_MMC is not set +CONFIG_MTD=y +CONFIG_MTD_DEVICE=y +CONFIG_NAND=y +CONFIG_NAND_PXA3XX=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_SFDP_SUPPORT=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set +CONFIG_PCI=y +CONFIG_PCI_MVEBU=y +CONFIG_SYS_NS16550=y +CONFIG_KIRKWOOD_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y diff --git a/configs/dns325_defconfig b/configs/dns325_defconfig index 5a76698..ba8b053 100644 --- a/configs/dns325_defconfig +++ b/configs/dns325_defconfig @@ -30,6 +30,7 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-dns325" CONFIG_ENV_IS_IN_NAND=y CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_MVGBE=y CONFIG_MII=y @@ -37,5 +38,6 @@ CONFIG_DM_RTC=y CONFIG_RTC_MV=y CONFIG_SYS_NS16550=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index 598a2a3..072582c 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -23,12 +23,15 @@ CONFIG_BOARD_EARLY_INIT_F=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_SEPARATE_BSS=y CONFIG_SPL_DMA_SUPPORT=y -# CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_OS_BOOT=y CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_SPL=y # CONFIG_CMD_FLASH is not set +CONFIG_CMD_NAND=y # CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_MTDPARTS=y +CONFIG_MTDIDS_DEFAULT="nand0=nand.0" +CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(NAND.SPL),256k(NAND.SPL.backup1),256k(NAND.SPL.backup2),256k(NAND.SPL.backup3),256k(NAND.u-boot-spl-os),2m(NAND.u-boot),128k(NAND.u-boot-env),128k(NAND.u-boot-env.backup1),8m(NAND.kernel),-(NAND.file-system)" CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="dra7-evm" @@ -66,6 +69,8 @@ CONFIG_MMC_UHS_SUPPORT=y CONFIG_MMC_HS200_SUPPORT=y CONFIG_SPL_MMC_HS200_SUPPORT=y CONFIG_MMC_OMAP_HS=y +CONFIG_NAND=y +CONFIG_SYS_NAND_BUSWIDTH_16BIT=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0 diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index d854154..60329c7 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -32,7 +32,10 @@ CONFIG_SPL_DMA_SUPPORT=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_SPI_LOAD=y # CONFIG_CMD_FLASH is not set -# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_NAND=y +CONFIG_CMD_MTDPARTS=y +CONFIG_MTDIDS_DEFAULT="nand0=nand.0" +CONFIG_MTDPARTS_DEFAULT="mtdparts=nand.0:256k(NAND.SPL),256k(NAND.SPL.backup1),256k(NAND.SPL.backup2),256k(NAND.SPL.backup3),256k(NAND.u-boot-spl-os),2m(NAND.u-boot),128k(NAND.u-boot-env),128k(NAND.u-boot-env.backup1),8m(NAND.kernel),-(NAND.file-system)" CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="dra7-evm" @@ -70,6 +73,8 @@ CONFIG_MMC_UHS_SUPPORT=y CONFIG_MMC_HS200_SUPPORT=y CONFIG_SPL_MMC_HS200_SUPPORT=y CONFIG_MMC_OMAP_HS=y +CONFIG_NAND=y +CONFIG_SYS_NAND_BUSWIDTH_16BIT=y CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y CONFIG_SF_DEFAULT_MODE=0 diff --git a/configs/dreamplug_defconfig b/configs/dreamplug_defconfig index 8202848..eae36f9 100644 --- a/configs/dreamplug_defconfig +++ b/configs/dreamplug_defconfig @@ -27,6 +27,7 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y @@ -40,5 +41,6 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_KIRKWOOD_SPI=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y diff --git a/configs/ds109_defconfig b/configs/ds109_defconfig index 29d5f98..22996e8 100644 --- a/configs/ds109_defconfig +++ b/configs/ds109_defconfig @@ -22,6 +22,7 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_BLK=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MVTWSI=y # CONFIG_MMC is not set @@ -37,5 +38,6 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_KIRKWOOD_SPI=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_FS_EXT4=y diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 62cad53..9e93649 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -43,6 +43,7 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_OF_TRANSLATE=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_MTD_DEVICE=y CONFIG_SPI_FLASH=y diff --git a/configs/emlid_neutis_n5_devboard_defconfig b/configs/emlid_neutis_n5_devboard_defconfig index 3df0ca1..19e8d79 100644 --- a/configs/emlid_neutis_n5_devboard_defconfig +++ b/configs/emlid_neutis_n5_devboard_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=408 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/goflexhome_defconfig b/configs/goflexhome_defconfig index c04bf0e..568b74f 100644 --- a/configs/goflexhome_defconfig +++ b/configs/goflexhome_defconfig @@ -31,6 +31,7 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-goflexnet" CONFIG_ENV_IS_IN_NAND=y CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_MVGBE=y CONFIG_MII=y @@ -38,5 +39,6 @@ CONFIG_DM_RTC=y CONFIG_RTC_MV=y CONFIG_SYS_NS16550=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y diff --git a/configs/guruplug_defconfig b/configs/guruplug_defconfig index 9998e48..8ae7e20 100644 --- a/configs/guruplug_defconfig +++ b/configs/guruplug_defconfig @@ -31,6 +31,7 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-guruplug-server-plus" CONFIG_ENV_IS_IN_NAND=y CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_MVGBE=y CONFIG_MII=y @@ -38,6 +39,7 @@ CONFIG_DM_RTC=y CONFIG_RTC_MV=y CONFIG_SYS_NS16550=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_LZMA=y diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig index 6123dad..fb006dc 100644 --- a/configs/k2e_evm_defconfig +++ b/configs/k2e_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC100000 CONFIG_SYS_TEXT_BASE=0xC000000 CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_LIBCOMMON_SUPPORT=y diff --git a/configs/k2e_hs_evm_defconfig b/configs/k2e_hs_evm_defconfig index 11c9fda..449e664 100644 --- a/configs/k2e_hs_evm_defconfig +++ b/configs/k2e_hs_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC100000 CONFIG_TI_SECURE_DEVICE=y CONFIG_SYS_TEXT_BASE=0xC000060 CONFIG_TI_COMMON_CMD_OPTIONS=y diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig index 4ff9c13..38db43e 100644 --- a/configs/k2g_evm_defconfig +++ b/configs/k2g_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC0A0000 CONFIG_SYS_TEXT_BASE=0xC000000 CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_LIBCOMMON_SUPPORT=y @@ -72,3 +73,4 @@ CONFIG_USB_DWC3_GENERIC=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_FUNCTION_SDP=y +CONFIG_PHY_TI=y diff --git a/configs/k2g_hs_evm_defconfig b/configs/k2g_hs_evm_defconfig index 990c7f6..9c7e3ca 100644 --- a/configs/k2g_hs_evm_defconfig +++ b/configs/k2g_hs_evm_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y CONFIG_TI_SECURE_DEVICE=y +CONFIG_ISW_ENTRY_ADDR=0xC0A0000 CONFIG_SYS_TEXT_BASE=0xC000060 CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_TARGET_K2G_EVM=y diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig index 6835874..39aa933 100644 --- a/configs/k2hk_evm_defconfig +++ b/configs/k2hk_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC200000 CONFIG_SYS_TEXT_BASE=0xC000000 CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_LIBCOMMON_SUPPORT=y diff --git a/configs/k2hk_hs_evm_defconfig b/configs/k2hk_hs_evm_defconfig index e14f901..94bc70a 100644 --- a/configs/k2hk_hs_evm_defconfig +++ b/configs/k2hk_hs_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC200000 CONFIG_TI_SECURE_DEVICE=y CONFIG_SYS_TEXT_BASE=0xC000060 CONFIG_TI_COMMON_CMD_OPTIONS=y diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig index 0e2f73a..c37a0ce 100644 --- a/configs/k2l_evm_defconfig +++ b/configs/k2l_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC100000 CONFIG_SYS_TEXT_BASE=0xC000000 CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_SPL_LIBCOMMON_SUPPORT=y diff --git a/configs/k2l_hs_evm_defconfig b/configs/k2l_hs_evm_defconfig index 1f7a93e..443758c 100644 --- a/configs/k2l_hs_evm_defconfig +++ b/configs/k2l_hs_evm_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ISW_ENTRY_ADDR=0xC100000 CONFIG_TI_SECURE_DEVICE=y CONFIG_SYS_TEXT_BASE=0xC000060 CONFIG_TI_COMMON_CMD_OPTIONS=y diff --git a/configs/libretech_all_h3_cc_h2_plus_defconfig b/configs/libretech_all_h3_cc_h2_plus_defconfig index 8f31448..3bccd60 100644 --- a/configs/libretech_all_h3_cc_h2_plus_defconfig +++ b/configs/libretech_all_h3_cc_h2_plus_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/libretech_all_h3_cc_h3_defconfig b/configs/libretech_all_h3_cc_h3_defconfig index e5e0f59..c00ab01 100644 --- a/configs/libretech_all_h3_cc_h3_defconfig +++ b/configs/libretech_all_h3_cc_h3_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/libretech_all_h3_cc_h5_defconfig b/configs/libretech_all_h3_cc_h5_defconfig index e4a93bd..5843f34 100644 --- a/configs/libretech_all_h3_cc_h5_defconfig +++ b/configs/libretech_all_h3_cc_h5_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/linkit-smart-7688-ram_defconfig b/configs/linkit-smart-7688-ram_defconfig index 2d3ab7e..649db0f 100644 --- a/configs/linkit-smart-7688-ram_defconfig +++ b/configs/linkit-smart-7688-ram_defconfig @@ -20,17 +20,22 @@ CONFIG_CMD_MEMINFO=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y # CONFIG_CMD_LOADS is not set +CONFIG_CMD_MTD=y +CONFIG_CMD_PART=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y +CONFIG_CMD_FS_GENERIC=y +# CONFIG_DOS_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y # CONFIG_DM_DEVICE_REMOVE is not set -CONFIG_HAVE_BLOCK_DEVICE=y +CONFIG_BLK=y CONFIG_CLK=y CONFIG_LED=y CONFIG_LED_BLINK=y @@ -46,6 +51,7 @@ CONFIG_PHYLIB=y CONFIG_PHY_FIXED=y CONFIG_MT7628_ETH=y CONFIG_PHY=y +CONFIG_MT76X8_USB_PHY=y CONFIG_POWER_DOMAIN=y CONFIG_RAM=y CONFIG_DM_RESET=y @@ -54,5 +60,12 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_MT7621_SPI=y CONFIG_SYSRESET_SYSCON=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_STORAGE=y +CONFIG_FS_EXT4=y +CONFIG_FS_FAT=y CONFIG_LZMA=y CONFIG_LZO=y diff --git a/configs/linkit-smart-7688_defconfig b/configs/linkit-smart-7688_defconfig index ad34aaf..41aa900 100644 --- a/configs/linkit-smart-7688_defconfig +++ b/configs/linkit-smart-7688_defconfig @@ -24,17 +24,22 @@ CONFIG_CMD_MEMINFO=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y # CONFIG_CMD_LOADS is not set +CONFIG_CMD_MTD=y +CONFIG_CMD_PART=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y CONFIG_CMD_DHCP=y CONFIG_CMD_MII=y CONFIG_CMD_PING=y CONFIG_CMD_TIME=y +CONFIG_CMD_FS_GENERIC=y +# CONFIG_DOS_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y # CONFIG_DM_DEVICE_REMOVE is not set -CONFIG_HAVE_BLOCK_DEVICE=y +CONFIG_BLK=y CONFIG_CLK=y CONFIG_LED=y CONFIG_LED_BLINK=y @@ -50,6 +55,7 @@ CONFIG_PHYLIB=y CONFIG_PHY_FIXED=y CONFIG_MT7628_ETH=y CONFIG_PHY=y +CONFIG_MT76X8_USB_PHY=y CONFIG_POWER_DOMAIN=y CONFIG_RAM=y CONFIG_DM_RESET=y @@ -58,5 +64,12 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_MT7621_SPI=y CONFIG_SYSRESET_SYSCON=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_STORAGE=y +CONFIG_FS_EXT4=y +CONFIG_FS_FAT=y CONFIG_LZMA=y CONFIG_LZO=y diff --git a/configs/lschlv2_defconfig b/configs/lschlv2_defconfig index 16d9c92..c550798 100644 --- a/configs/lschlv2_defconfig +++ b/configs/lschlv2_defconfig @@ -16,7 +16,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_MISC_INIT_R=y # CONFIG_DISPLAY_BOARDINFO is not set # CONFIG_CMD_FLASH is not set -CONFIG_CMD_IDE=y +CONFIG_CMD_SATA=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y @@ -26,7 +26,8 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-lschlv2" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y -CONFIG_MVSATA_IDE=y +CONFIG_SATA_MV=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y @@ -39,4 +40,5 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_KIRKWOOD_SPI=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/lsxhl_defconfig b/configs/lsxhl_defconfig index b6eba4a..efcce45 100644 --- a/configs/lsxhl_defconfig +++ b/configs/lsxhl_defconfig @@ -16,7 +16,7 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_MISC_INIT_R=y # CONFIG_DISPLAY_BOARDINFO is not set # CONFIG_CMD_FLASH is not set -CONFIG_CMD_IDE=y +CONFIG_CMD_SATA=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y @@ -26,7 +26,8 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-lsxhl" CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y -CONFIG_MVSATA_IDE=y +CONFIG_SATA_MV=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y @@ -39,4 +40,5 @@ CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_KIRKWOOD_SPI=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y diff --git a/configs/mscc_jr2_defconfig b/configs/mscc_jr2_defconfig index 9276df2..d6e4bd4 100644 --- a/configs/mscc_jr2_defconfig +++ b/configs/mscc_jr2_defconfig @@ -28,7 +28,10 @@ CONFIG_CMD_MEMTEST=y CONFIG_CMD_GPIO=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y -# CONFIG_CMD_NET is not set +CONFIG_CMD_DHCP=y +# CONFIG_NET_TFTP_VARS is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PING=y CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)" @@ -62,3 +65,4 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_LZMA=y +CONFIG_MSCC_JR2_SWITCH=y diff --git a/configs/mscc_servalt_defconfig b/configs/mscc_servalt_defconfig index a450f48..924cf6a 100644 --- a/configs/mscc_servalt_defconfig +++ b/configs/mscc_servalt_defconfig @@ -24,7 +24,6 @@ CONFIG_CMD_MEMTEST=y CONFIG_CMD_GPIO=y CONFIG_CMD_SF=y CONFIG_CMD_SPI=y -# CONFIG_CMD_NET is not set CONFIG_CMD_MTDPARTS=y CONFIG_MTDIDS_DEFAULT="nor0=spi_flash" CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)" @@ -55,3 +54,8 @@ CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_DM_SPI=y CONFIG_LZMA=y +CONFIG_CMD_DHCP=y +# CONFIG_NET_TFTP_VARS is not set +# CONFIG_CMD_NFS is not set +CONFIG_CMD_PING=y +CONFIG_MSCC_SERVALT_SWITCH=y diff --git a/configs/nanopi_m1_defconfig b/configs/nanopi_m1_defconfig index b3a7870..af7fa0b 100644 --- a/configs/nanopi_m1_defconfig +++ b/configs/nanopi_m1_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=408 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig index b83cdf2..84e1525 100644 --- a/configs/nanopi_m1_plus_defconfig +++ b/configs/nanopi_m1_plus_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=408 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MMC0_CD_PIN="PH13" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/nanopi_neo2_defconfig b/configs/nanopi_neo2_defconfig index 9de893a..2d44135 100644 --- a/configs/nanopi_neo2_defconfig +++ b/configs/nanopi_neo2_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=672 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/nanopi_neo_air_defconfig b/configs/nanopi_neo_air_defconfig index 33f9c07..bd099c8 100644 --- a/configs/nanopi_neo_air_defconfig +++ b/configs/nanopi_neo_air_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=408 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y # CONFIG_VIDEO_DE2 is not set CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/nanopi_neo_defconfig b/configs/nanopi_neo_defconfig index 40f5bd1..074b172 100644 --- a/configs/nanopi_neo_defconfig +++ b/configs/nanopi_neo_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=408 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y # CONFIG_VIDEO_DE2 is not set CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig index 88c76a5..11cb8f6 100644 --- a/configs/nanopi_neo_plus2_defconfig +++ b/configs/nanopi_neo_plus2_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=408 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_MACPWR="PD6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/nas220_defconfig b/configs/nas220_defconfig index 6bd308b..a244b8d 100644 --- a/configs/nas220_defconfig +++ b/configs/nas220_defconfig @@ -31,6 +31,7 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-blackarmor-nas220" CONFIG_ENV_IS_IN_NAND=y CONFIG_DM=y CONFIG_MVSATA_IDE=y +CONFIG_BLK=y # CONFIG_MMC is not set CONFIG_MVGBE=y CONFIG_MII=y @@ -38,5 +39,6 @@ CONFIG_DM_RTC=y CONFIG_RTC_MV=y CONFIG_SYS_NS16550=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig new file mode 100644 index 0000000..34fe6f5 --- /dev/null +++ b/configs/oceanic_5205_5inmfd_defconfig @@ -0,0 +1,20 @@ +CONFIG_ARM=y +CONFIG_ARCH_SUNXI=y +CONFIG_SPL=y +CONFIG_MACH_SUN50I=y +CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y +CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y +CONFIG_DRAM_CLK=552 +CONFIG_DRAM_ZQ=3881949 +CONFIG_MMC0_CD_PIN="" +CONFIG_SPL_SPI_SUNXI=y +CONFIG_NR_DRAM_BANKS=1 +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-oceanic-5205-5inmfd" +CONFIG_SUN8I_EMAC=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y diff --git a/configs/orangepi_2_defconfig b/configs/orangepi_2_defconfig index ab6566e..ce3cc83 100644 --- a/configs/orangepi_2_defconfig +++ b/configs/orangepi_2_defconfig @@ -4,8 +4,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_USB1_VBUS_PIN="PG13" CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/orangepi_lite_defconfig b/configs/orangepi_lite_defconfig index 1092a85..490f5a3 100644 --- a/configs/orangepi_lite_defconfig +++ b/configs/orangepi_lite_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/orangepi_one_defconfig b/configs/orangepi_one_defconfig index 404fdd9..949fc5d 100644 --- a/configs/orangepi_one_defconfig +++ b/configs/orangepi_one_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig index ad83738..a5bac5b 100644 --- a/configs/orangepi_pc2_defconfig +++ b/configs/orangepi_pc2_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=672 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_MACPWR="PD6" CONFIG_SPL_SPI_SUNXI=y CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig index de11df7..79d6237 100644 --- a/configs/orangepi_pc_defconfig +++ b/configs/orangepi_pc_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=624 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_SPL_I2C_SUPPORT=y diff --git a/configs/orangepi_pc_plus_defconfig b/configs/orangepi_pc_plus_defconfig index ce26cfa..31e9bcf 100644 --- a/configs/orangepi_pc_plus_defconfig +++ b/configs/orangepi_pc_plus_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=624 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig index b0813e4..f31fd28 100644 --- a/configs/orangepi_plus2e_defconfig +++ b/configs/orangepi_plus2e_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MACPWR="PD6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig index 0502373..8a9ea27 100644 --- a/configs/orangepi_plus_defconfig +++ b/configs/orangepi_plus_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=672 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y CONFIG_MACPWR="PD6" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_USB1_VBUS_PIN="PG13" diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig index 20ae6df..0d64eeb 100644 --- a/configs/orangepi_prime_defconfig +++ b/configs/orangepi_prime_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=672 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig index 05c3b08..6492d85 100644 --- a/configs/orangepi_r1_defconfig +++ b/configs/orangepi_r1_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=624 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y # CONFIG_VIDEO_DE2 is not set CONFIG_SPL_SPI_SUNXI=y CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig index 44fc18b..b881a84 100644 --- a/configs/orangepi_zero_defconfig +++ b/configs/orangepi_zero_defconfig @@ -3,8 +3,6 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN8I_H3=y CONFIG_DRAM_CLK=624 -CONFIG_DRAM_ZQ=3881979 -CONFIG_DRAM_ODT_EN=y # CONFIG_VIDEO_DE2 is not set CONFIG_SPL_SPI_SUNXI=y CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig index e62b3cb..ab0d12e 100644 --- a/configs/orangepi_zero_plus2_defconfig +++ b/configs/orangepi_zero_plus2_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=672 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_MMC0_CD_PIN="PH13" CONFIG_MMC_SUNXI_SLOT_EXTRA=2 CONFIG_NR_DRAM_BANKS=1 diff --git a/configs/orangepi_zero_plus_defconfig b/configs/orangepi_zero_plus_defconfig index cc8b8c7..37ca6df 100644 --- a/configs/orangepi_zero_plus_defconfig +++ b/configs/orangepi_zero_plus_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL=y CONFIG_MACH_SUN50I_H5=y CONFIG_DRAM_CLK=624 CONFIG_DRAM_ZQ=3881977 +# CONFIG_DRAM_ODT_EN is not set CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig index fd3cdee..a833137 100644 --- a/configs/pine64-lts_defconfig +++ b/configs/pine64-lts_defconfig @@ -16,4 +16,5 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-lts" CONFIG_SUN8I_EMAC=y CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index da4bdce..c04ecd9 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -194,6 +194,7 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 193e418..bb508a8 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -215,6 +215,7 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y diff --git a/configs/sheevaplug_defconfig b/configs/sheevaplug_defconfig index 04b00cd..ec527fc 100644 --- a/configs/sheevaplug_defconfig +++ b/configs/sheevaplug_defconfig @@ -39,6 +39,7 @@ CONFIG_DM_RTC=y CONFIG_RTC_MV=y CONFIG_SYS_NS16550=y CONFIG_USB=y +CONFIG_DM_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_LZMA=y diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index d20b2ab..6781adb 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -1,11 +1,12 @@ CONFIG_ARM=y CONFIG_ARCH_STM32MP=y -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x3000 CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL=y CONFIG_TARGET_STM32MP1=y CONFIG_DISTRO_DEFAULTS=y -CONFIG_NR_DRAM_BANKS=1 +CONFIG_FIT=y +CONFIG_BOOTCOMMAND="run bootcmd_stm32mp" CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=3 CONFIG_SPL_I2C_SUPPORT=y @@ -18,8 +19,10 @@ CONFIG_SYS_PROMPT="STM32MP> " # CONFIG_CMD_EXPORTENV is not set # CONFIG_CMD_IMPORTENV is not set CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MEMTEST=y CONFIG_CMD_ADC=y CONFIG_CMD_CLK=y +CONFIG_CMD_DFU=y CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y @@ -27,12 +30,21 @@ CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_TIMER=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y CONFIG_CMD_EXT4_WRITE=y # CONFIG_SPL_DOS_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1" CONFIG_STM32_ADC=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 +CONFIG_FASTBOOT_BUF_SIZE=0x02000000 +CONFIG_FASTBOOT_USB_DEV=1 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=1 CONFIG_DM_HWSPINLOCK=y CONFIG_HWSPINLOCK_STM32=y CONFIG_DM_I2C=y @@ -43,15 +55,16 @@ CONFIG_DM_MMC=y CONFIG_STM32_SDMMC2=y CONFIG_PHY=y CONFIG_PHY_STM32_USBPHYC=y -# CONFIG_PINCTRL_FULL is not set +CONFIG_PINCONF=y # CONFIG_SPL_PINCTRL_FULL is not set +CONFIG_PINCTRL_STMFX=y CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set -CONFIG_PMIC_STPMU1=y +CONFIG_PMIC_STPMIC1=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_DM_REGULATOR_STM32_VREFBUF=y -CONFIG_DM_REGULATOR_STPMU1=y +CONFIG_DM_REGULATOR_STPMIC1=y CONFIG_SERIAL_RX_BUFFER=y CONFIG_STM32_SERIAL=y CONFIG_USB=y @@ -64,4 +77,3 @@ CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" CONFIG_USB_GADGET_VENDOR_NUM=0x0483 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720 CONFIG_USB_GADGET_DWC2_OTG=y -CONFIG_USB_GADGET_DOWNLOAD=y diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig new file mode 100644 index 0000000..a050cee --- /dev/null +++ b/configs/stm32mp15_trusted_defconfig @@ -0,0 +1,70 @@ +CONFIG_ARM=y +CONFIG_ARCH_STM32MP=y +CONFIG_SYS_MALLOC_F_LEN=0x3000 +CONFIG_TARGET_STM32MP1=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_BOOTCOMMAND="run bootcmd_stm32mp" +CONFIG_SYS_PROMPT="STM32MP> " +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_ADC=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DFU=y +CONFIG_CMD_FUSE=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1" +CONFIG_STM32_ADC=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0xC0000000 +CONFIG_FASTBOOT_BUF_SIZE=0x02000000 +CONFIG_FASTBOOT_USB_DEV=1 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=1 +CONFIG_DM_HWSPINLOCK=y +CONFIG_HWSPINLOCK_STM32=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_STM32F7=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_DM_MMC=y +CONFIG_STM32_SDMMC2=y +CONFIG_PHY=y +CONFIG_PHY_STM32_USBPHYC=y +CONFIG_PINCONF=y +CONFIG_PINCTRL_STMFX=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_STPMIC1=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_REGULATOR_STM32_VREFBUF=y +CONFIG_DM_REGULATOR_STPMIC1=y +CONFIG_SERIAL_RX_BUFFER=y +CONFIG_STM32_SERIAL=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_DWC2=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics" +CONFIG_USB_GADGET_VENDOR_NUM=0x0483 +CONFIG_USB_GADGET_PRODUCT_NUM=0x5720 +CONFIG_USB_GADGET_DWC2_OTG=y diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig index fb9307a..3736aec 100644 --- a/configs/theadorable_debug_defconfig +++ b/configs/theadorable_debug_defconfig @@ -51,6 +51,7 @@ CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_SATA_MV=y +CONFIG_BLK=y CONFIG_BOOTCOUNT_LIMIT=y CONFIG_BOOTCOUNT_RAM=y CONFIG_FPGA_ALTERA=y diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig index c406b25..85f2141 100644 --- a/configs/turris_omnia_defconfig +++ b/configs/turris_omnia_defconfig @@ -43,6 +43,7 @@ CONFIG_ATSHA204A=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_MV=y CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_SPANSION=y CONFIG_PHY_MARVELL=y CONFIG_PHY_GIGE=y CONFIG_MVNETA=y diff --git a/configs/x530_defconfig b/configs/x530_defconfig index cd18e9e..c893c44 100644 --- a/configs/x530_defconfig +++ b/configs/x530_defconfig @@ -19,6 +19,8 @@ CONFIG_SILENT_CONSOLE=y CONFIG_SILENT_U_BOOT_ONLY=y CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC=y CONFIG_MISC_INIT_R=y +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y CONFIG_CMD_MEMINFO=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_GPIO=y @@ -72,3 +74,6 @@ CONFIG_USB_STORAGE=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y CONFIG_USB_ETHER_ASIX88179=y +CONFIG_WATCHDOG=y +CONFIG_WDT=y +CONFIG_WDT_ORION=y diff --git a/doc/README.chromium b/doc/README.chromium index 45eaece..096bc4f 100644 --- a/doc/README.chromium +++ b/doc/README.chromium @@ -1,239 +1,177 @@ -Running U-Boot from coreboot on Chromebooks -=========================================== +Chromium OS Support in U-Boot +============================= -U-Boot can be used as a secondary boot loader in a few situations such as from -UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on -ARM platforms to start up the machine. +Introduction +------------ -This document aims to provide a guide to booting U-Boot on a Chromebook. It -is only a starting point, and there are many guides on the interwebs. But -placing this information in the U-Boot tree should make it easier to find for -those who use U-Boot habitually. +This describes how to use U-Boot with Chromium OS. Several options are +available: -Most of these platforms are supported by U-Boot natively, but it is risky to -replace the ROM unless you have a servo board and cable to restore it with. + - Running U-Boot from the 'altfw' feature, which is available on selected + Chromebooks from 2019 onwards (initially Grunt). Press '1' from the + developer-mode screen to get into U-Boot. See here for details: + https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1 + - Running U-Boot from the disk partition. This involves signing U-Boot and + placing it on the disk, for booting as a 'kernel'. See + README.chromium-chainload for information on this. This is the only + option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat + more involved. -For all of these the standard U-Boot build instructions apply. For example on -ARM: + - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be + used instead of either or both of depthcharge (a bootloader which forked + from U-Boot in 2013) and coreboot. See below for more information on + this. - sudo apt install gcc-arm-linux-gnueabi - mkdir b - make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all -You can obtain the vbutil_kernel utility here: +U-Boot with Chromium OS verified boot +------------------------------------- - https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U +To obtain: + git clone https://github.com/sglass68/u-boot.git + cd u-boot + git checkout cros-master -Snow (Samsung ARM Chromebook) ------------------------------ +To build for sandbox: -See here: + UB=/tmp/b/chromeos_sandbox # U-Boot build directory + CROS=/home/sglass/cosarm # Chromium OS directory + make O=$UB/chromeos_sandbox_defconfig + make O=$UB -j20 -s VBOOT_SOURCE=$CROS/src/platform/vboot_reference \ + MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1 -https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook +Replace sandbox with another supported target. +This produces $UB/image.bin which contains the firmware binaries in a SPI +flash image. -Nyan-big --------- - -Compiled based on information here: -https://lists.denx.de/pipermail/u-boot/2015-March/209530.html -https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big -https://lists.denx.de/pipermail/u-boot/2017-May/289491.html -https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card - -1. Build U-Boot - - mkdir b - make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all - - -2. Select a .its file - -Select something from doc/chromium which matches your board, or create your -own. - -Note that the device tree node is required, even though it is not actually -used by U-Boot. This is because the Chromebook expects to pass it to the -kernel, and crashes if it is not present. - - -3. Build and sign an image - - ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit - echo test >dummy.txt - vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \ - --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \ - --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ - --bootloader dummy.txt --pack u-boot.kpart - - -4. Prepare an SD card - - DISK=/dev/sdc # Replace with your actual SD card device - sudo cgpt create $DISK - sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK - sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK - sudo gdisk $DISK # Enter command 'w' to write a protective MBR to the disk - - -5. Write U-Boot to the SD card +To run on sandbox: - sudo dd if=u-boot.kpart of=/dev/sdc1; sync + $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \ + -L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \ + -l -w -s state.dtb -r +To run on other boards: + Install image.bin in the SPI flash of your device + Boot your system -6. Start it up -Reboot the device in dev mode. Make sure that you have USB booting enabled. To -do this, login as root (via Ctrl-Alt-forward_arrow) and type -'enable_dev_usb_boot'. You only need to do this once. +Sandbox +------- -Reboot the device with the SD card inserted. Press Clrl-U at the developer -mode screen. It should show something like the following on the display: +Most Chromium OS development with U-Boot is undertaken using sandbox. There is +a sandbox target available (chromeos_sandbox) which allows running U-Boot on +a Linux machine completion with emulations of the display, TPM, disk, etc. - U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600) +Running sandbox starts TPL, which contains the first phase of vboot, providing +a device tree and binding a Chromium OS disk image for use to find kernels +(any Chromium OS image will do). It also saves driver state between U-Boot +phases into state.dtb and will automatically ensure that memory is shared +between all phases. TPL will jump to SPL and then on to U-Boot proper. - Model: Acer Chromebook 13 CB5-311 - Board: Google/NVIDIA Nyan-big, ID: 1 +It is possible to run with debugging on, e.g. - Net: No ethernet found. - Hit any key to stop autoboot: 0 - Tegra124 (Nyan-big) # + gdb --args $UB/tpl/u-boot-tpl -d .... +Breakpoints can be set in any U-Boot phase. Overall this is a good debugging +environment for new verified-boot features. -7. Known problems -On the serial console the word MMC is chopped at the start of the line: +Samus +----- -C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0 +Basic support is available for samus, using the chromeos_samus target. If you +have an em100, use: -This is likely due to some problem with change-over of the serial driver -during relocation (or perhaps updating the clock setup in board_init()). + sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r +to write the image and then boot samus (Power-Refresh). -9. Notes -To check that you copied the u-boot.its file correctly, use these commands. -You should see that the data at 0x100 in u-boot-chromium.fit is the first few -bytes of U-Boot: +Boot flow +--------- - hd u-boot-chromium.fit |head -20 - ... - 00000100 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| +Verified boot starts in TPL, which selects the A or B SPL, which in turn selects +the A or B U-Boot. Then this jumps to the selected kernel. If anything goes +wrong, the device reboots and the recovery SPL and U-Boot are used instead. - hd b/nyan-big/u-boot.bin |head - 00000000 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| +More details are available here: + https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery -The 'data' property of the FIT is set up to start at offset 0x100 bytes into -the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes -from the load address. If this changes, you either need to modify U-Boot to be -fully relocatable, or expect it to hang. +New uclasses +------------ -chromebook_jerry ----------------- +Several uclasses are provided in cros/: -The instruction are similar to those for Nyan with changes as noted below: + UCLASS_CROS_AUX_FW Chrome OS auxiliary firmware + UCLASS_CROS_FWSTORE Chrome OS firmware storage + UCLASS_CROS_NVDATA Chrome OS non-volatile data device + UCLASS_CROS_VBOOT_EC Chrome OS vboot EC operations + UCLASS_CROS_VBOOT_FLAG Chrome OS verified boot flag -1. Patch U-Boot +The existing UCLASS_CROS_EC is also used. -Open include/configs/rk3288_common.h -Change: - -#define CONFIG_SYS_TEXT_BASE 0x00100000 - -to: - -#define CONFIG_SYS_TEXT_BASE 0x02000100 - - - -2. Build U-Boot - - mkdir b - make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \ - chromebook_jerry_defconfig all - - -3. See above - -4. Build and sign an image - - ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \ - u-boot-chromium.fit - echo test >dummy.txt - vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \ - --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \ - --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ - --bootloader dummy.txt --pack u-boot.kpart - - -5. See above +Commands +-------- -6. See above +A new 'vboot' command is provided to run particular vboot stages. The most +useful command is 'vboot go auto', which continues where the last stage left +off. -7. Start it up +Note that TPL and SPL do not supports commands as yet, so the vboot code is +called directly from the SPL boot devices (BOOT_DEVICE_CROS_VBOOT). See +cros_load_image_tpl() and cros_load_image_spl() which both call +vboot_run_auto(). -Reboot the device in dev mode. Make sure that you have USB booting enabled. To -do this, login as root (via Ctrl-Alt-forward_arrow) and type -'enable_dev_usb_boot'. You only need to do this once. -Reboot the device with the SD card inserted. Press Clrl-U at the developer -mode screen. It should show something like the following on the display: +Config options +-------------- - U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600) +The main option is CONFIG_CHROMEOS, which enables a wide array of other options +so that the required features are present. - Model: Google Jerry - Net: Net Initialization Skipped - No ethernet found. - Hit any key to stop autoboot: 0 +Device-tree config +------------------ -8. Known problems +Various options are available which control the operation of verified boot. +See cros/dts/bindings/config.txt for details. Most config is handled at run- +time, although build-time config (with Kconfig) could also be added fairly +easily. -None as yet. +Porting to other hardware +------------------------- -9. Notes +A basic port to samus (Chromebook Pixel 2015) is in a basic working state, +using the chromeos_samus target. Patches will likely be forthcoming in early +2019. Ports to an ARM board and coreboot (for x86 Chromebooks) are in the +dreaming state. -None as yet. +Tests +----- -Other notes -=========== +Chromium OS firmware has a very limited set of tests. The tests that originally +existed in U-Boot were not brought over to coreboot or depthcharge. -flashrom --------- +The U-Boot tests ('make check') do operate, but at present there are no +Chromium OS tests available. These will hopefully come together over time. Of +course the above sandbox feature provides a sort of functional test and can +detecte problems that affect the flow or particular vboot features. - Used to make a backup of your firmware, or to replace it. - See: https://www.chromium.org/chromium-os/packages/cros-flashrom +TO DO +----- +- Support for booting from coreboot (patches expected March 2019) +- Support for booting from an ARM board, e.g. bob -coreboot --------- -Coreboot itself is not designed to actually boot an OS. Instead, a program -called Depthcharge is used. This originally came out of U-Boot and was then -heavily hacked and modified such that is is almost unrecognisable. It does -include a very small part of the U-Boot command-line interface but is not -usable as a general-purpose boot loader. - -In addition, it has a very unusual design in that it does not do device init -itself, but instead relies on coreboot. This is similar to (in U-Boot) having -a SPI driver with an empty probe() method, relying on whatever was set up -beforehand. It can be quite hard to figure out between these two code bases -what settings are actually used. When chain-loading into U-Boot we must be -careful to reinit anything that U-Boot expects. If not, some peripherals (or -the whole machine) may not work. This makes the process of chainloading more -complicated than it could be on some platforms. - -Finally, it supports only a subset of the U-Boot's FIT format. In particular -it uses a fixed address to load the FIT and does not support load/exec -addresses. This means that U-Boot must be able to boot from whatever -address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting -in Depthcharge). In practice this means that the data in the kernel@1 FIT node -(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE. +Simon Glass +sjg@chromium.org +7 October 2018 diff --git a/doc/README.chromium-chainload b/doc/README.chromium-chainload new file mode 100644 index 0000000..45eaece --- /dev/null +++ b/doc/README.chromium-chainload @@ -0,0 +1,239 @@ +Running U-Boot from coreboot on Chromebooks +=========================================== + +U-Boot can be used as a secondary boot loader in a few situations such as from +UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on +ARM platforms to start up the machine. + +This document aims to provide a guide to booting U-Boot on a Chromebook. It +is only a starting point, and there are many guides on the interwebs. But +placing this information in the U-Boot tree should make it easier to find for +those who use U-Boot habitually. + +Most of these platforms are supported by U-Boot natively, but it is risky to +replace the ROM unless you have a servo board and cable to restore it with. + + +For all of these the standard U-Boot build instructions apply. For example on +ARM: + + sudo apt install gcc-arm-linux-gnueabi + mkdir b + make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all + +You can obtain the vbutil_kernel utility here: + + https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U + + +Snow (Samsung ARM Chromebook) +----------------------------- + +See here: + +https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook + + +Nyan-big +-------- + +Compiled based on information here: +https://lists.denx.de/pipermail/u-boot/2015-March/209530.html +https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big +https://lists.denx.de/pipermail/u-boot/2017-May/289491.html +https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card + +1. Build U-Boot + + mkdir b + make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all + + +2. Select a .its file + +Select something from doc/chromium which matches your board, or create your +own. + +Note that the device tree node is required, even though it is not actually +used by U-Boot. This is because the Chromebook expects to pass it to the +kernel, and crashes if it is not present. + + +3. Build and sign an image + + ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit + echo test >dummy.txt + vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \ + --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \ + --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ + --bootloader dummy.txt --pack u-boot.kpart + + +4. Prepare an SD card + + DISK=/dev/sdc # Replace with your actual SD card device + sudo cgpt create $DISK + sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK + sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK + sudo gdisk $DISK # Enter command 'w' to write a protective MBR to the disk + + +5. Write U-Boot to the SD card + + sudo dd if=u-boot.kpart of=/dev/sdc1; sync + + +6. Start it up + +Reboot the device in dev mode. Make sure that you have USB booting enabled. To +do this, login as root (via Ctrl-Alt-forward_arrow) and type +'enable_dev_usb_boot'. You only need to do this once. + +Reboot the device with the SD card inserted. Press Clrl-U at the developer +mode screen. It should show something like the following on the display: + + U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600) + + Model: Acer Chromebook 13 CB5-311 + Board: Google/NVIDIA Nyan-big, ID: 1 + + Net: No ethernet found. + Hit any key to stop autoboot: 0 + Tegra124 (Nyan-big) # + + +7. Known problems + +On the serial console the word MMC is chopped at the start of the line: + +C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0 + +This is likely due to some problem with change-over of the serial driver +during relocation (or perhaps updating the clock setup in board_init()). + + +9. Notes + +To check that you copied the u-boot.its file correctly, use these commands. +You should see that the data at 0x100 in u-boot-chromium.fit is the first few +bytes of U-Boot: + + hd u-boot-chromium.fit |head -20 + ... + 00000100 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| + + hd b/nyan-big/u-boot.bin |head + 00000000 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| + + +The 'data' property of the FIT is set up to start at offset 0x100 bytes into +the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes +from the load address. If this changes, you either need to modify U-Boot to be +fully relocatable, or expect it to hang. + + +chromebook_jerry +---------------- + +The instruction are similar to those for Nyan with changes as noted below: + +1. Patch U-Boot + +Open include/configs/rk3288_common.h + +Change: + +#define CONFIG_SYS_TEXT_BASE 0x00100000 + +to: + +#define CONFIG_SYS_TEXT_BASE 0x02000100 + + + +2. Build U-Boot + + mkdir b + make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \ + chromebook_jerry_defconfig all + + +3. See above + +4. Build and sign an image + + ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \ + u-boot-chromium.fit + echo test >dummy.txt + vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \ + --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \ + --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ + --bootloader dummy.txt --pack u-boot.kpart + + +5. See above + +6. See above + +7. Start it up + +Reboot the device in dev mode. Make sure that you have USB booting enabled. To +do this, login as root (via Ctrl-Alt-forward_arrow) and type +'enable_dev_usb_boot'. You only need to do this once. + +Reboot the device with the SD card inserted. Press Clrl-U at the developer +mode screen. It should show something like the following on the display: + + U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600) + + Model: Google Jerry + Net: Net Initialization Skipped + No ethernet found. + Hit any key to stop autoboot: 0 + + +8. Known problems + +None as yet. + + +9. Notes + +None as yet. + + +Other notes +=========== + +flashrom +-------- + + Used to make a backup of your firmware, or to replace it. + + See: https://www.chromium.org/chromium-os/packages/cros-flashrom + + +coreboot +-------- + +Coreboot itself is not designed to actually boot an OS. Instead, a program +called Depthcharge is used. This originally came out of U-Boot and was then +heavily hacked and modified such that is is almost unrecognisable. It does +include a very small part of the U-Boot command-line interface but is not +usable as a general-purpose boot loader. + +In addition, it has a very unusual design in that it does not do device init +itself, but instead relies on coreboot. This is similar to (in U-Boot) having +a SPI driver with an empty probe() method, relying on whatever was set up +beforehand. It can be quite hard to figure out between these two code bases +what settings are actually used. When chain-loading into U-Boot we must be +careful to reinit anything that U-Boot expects. If not, some peripherals (or +the whole machine) may not work. This makes the process of chainloading more +complicated than it could be on some platforms. + +Finally, it supports only a subset of the U-Boot's FIT format. In particular +it uses a fixed address to load the FIT and does not support load/exec +addresses. This means that U-Boot must be able to boot from whatever +address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting +in Depthcharge). In practice this means that the data in the kernel@1 FIT node +(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE. diff --git a/doc/device-tree-bindings/i2c/i2c.txt b/doc/device-tree-bindings/i2c/i2c.txt index de818d4..9698e48 100644 --- a/doc/device-tree-bindings/i2c/i2c.txt +++ b/doc/device-tree-bindings/i2c/i2c.txt @@ -12,6 +12,10 @@ property which allows the chip offset length to be selected. Optional properties: - u-boot,i2c-offset-len - length of chip offset in bytes. If omitted the default value of 1 is used. +- u-boot,i2c-transaction-bytes - the length of single I2C transaction on + the bus. Some devices require more than single byte transmission + (e.g. mc34708 mfd). This information is necessary to correctly + initialize (put into idle state) I2C bus after soft reset. - gpios = <sda ...>, <scl ...>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&i2c_xfer>; @@ -28,6 +32,7 @@ i2c4: i2c@12ca0000 { compatible = "google,cros-ec"; i2c-max-frequency = <100000>; u-boot,i2c-offset-len = <0>; + u-boot,i2c-transaction-bytes = <3>; ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>; }; }; diff --git a/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt new file mode 100644 index 0000000..70e76be --- /dev/null +++ b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt @@ -0,0 +1,59 @@ +STMicroelectronics Flexible Memory Controller 2 (FMC2) +NAND Interface + +Required properties: +- compatible: Should be one of: + * st,stm32mp15-fmc2 +- reg: NAND flash controller memory areas. + First region contains the register location. + Regions 2 to 4 respectively contain the data, command, + and address space for CS0. + Regions 5 to 7 contain the same areas for CS1. +- interrupts: The interrupt number +- pinctrl-0: Standard Pinctrl phandle (see: pinctrl/pinctrl-bindings.txt) +- clocks: The clock needed by the NAND flash controller + +Optional properties: +- resets: Reference to a reset controller asserting the FMC controller +- dmas: DMA specifiers (see: dma/stm32-mdma.txt) +- dma-names: Must be "tx", "rx" and "ecc" + +Optional children nodes: +Children nodes represent the available NAND chips. + +Optional properties: +- nand-on-flash-bbt: see nand.txt +- nand-ecc-strength: see nand.txt +- nand-ecc-step-size: see nand.txt + +The following ECC strength and step size are currently supported: + - nand-ecc-strength = <1>, nand-ecc-step-size = <512> (Hamming) + - nand-ecc-strength = <4>, nand-ecc-step-size = <512> (BCH4) + - nand-ecc-strength = <8>, nand-ecc-step-size = <512> (BCH8) (default) + +Example: + + fmc: nand-controller@58002000 { + compatible = "st,stm32mp15-fmc2"; + reg = <0x58002000 0x1000>, + <0x80000000 0x1000>, + <0x88010000 0x1000>, + <0x88020000 0x1000>, + <0x81000000 0x1000>, + <0x89010000 0x1000>, + <0x89020000 0x1000>; + interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + pinctrl-names = "default"; + pinctrl-0 = <&fmc_pins_a>; + #address-cells = <1>; + #size-cells = <0>; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; + }; diff --git a/doc/git-mailrc b/doc/git-mailrc index 9cf1807..f989792 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -26,7 +26,6 @@ alias iwamatsu Nobuhiro Iwamatsu <iwamatsu@nigauri.org> alias jaehoon Jaehoon Chung <jh80.chung@samsung.com> alias jagan Jagan Teki <jagan@amarulasolutions.com> alias jhersh Joe Hershberger <joe.hershberger@ni.com> -alias luka Luka Perkov <luka.perkov@sartura.hr> alias lukma Lukasz Majewski <lukma@denx.de> alias macpaul Macpaul Lin <macpaul@andestech.com> alias marex Marek Vasut <marex@denx.de> @@ -35,7 +34,6 @@ alias masahiro Masahiro Yamada <yamada.masahiro@socionext.com> alias mateusz Mateusz Kulikowski <mateusz.kulikowski@gmail.com> alias maxime Maxime Ripard <maxime.ripard@free-electrons.com> alias monstr Michal Simek <monstr@monstr.eu> -alias prafulla Prafulla Wadaskar <prafulla@marvell.com> alias prom Minkyu Kang <mk7.kang@samsung.com> alias ptomsich Philipp Tomsich <philipp.tomsich@theobroma-systems.com> alias sbabic Stefano Babic <sbabic@denx.de> @@ -56,7 +54,7 @@ alias arm uboot, aaribaud, trini alias at91 uboot, abiessmann alias davinci ti alias imx uboot, sbabic -alias kirkwood uboot, prafulla, luka, stroese +alias kirkwood uboot, stroese alias omap ti alias pxa uboot, marex alias rmobile uboot, iwamatsu diff --git a/drivers/Kconfig b/drivers/Kconfig index f24351a..e6702ec 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -98,6 +98,8 @@ source "drivers/smem/Kconfig" source "drivers/sound/Kconfig" +source "drivers/soc/Kconfig" + source "drivers/spi/Kconfig" source "drivers/spmi/Kconfig" diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 49a056e..7ebee75 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -81,7 +81,9 @@ config MVSATA_IDE config SATA_MV bool "Enable Marvell SATA controller driver support" + select AHCI select LIBATA + depends on BLK help Enable this driver to support the SATA controller found in some Marvell SoCs. diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c index 6e3f17e..48a9d00 100644 --- a/drivers/ata/ahci_mvebu.c +++ b/drivers/ata/ahci_mvebu.c @@ -44,6 +44,7 @@ static int mvebu_ahci_probe(struct udevice *dev) } static const struct udevice_id mvebu_ahci_ids[] = { + { .compatible = "marvell,armada-380-ahci" }, { .compatible = "marvell,armada-3700-ahci" }, { .compatible = "marvell,armada-8k-ahci" }, { } diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index a168196..2a630d4 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -3,7 +3,7 @@ * Copyright (C) Excito Elektronik i SkÃ¥ne AB, 2010. * Author: Tor Krill <tor@excito.com> * - * Copyright (C) 2015 Stefan Roese <sr@denx.de> + * Copyright (C) 2015, 2019 Stefan Roese <sr@denx.de> */ /* @@ -32,6 +32,10 @@ */ #include <common.h> +#include <ahci.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> #include <fis.h> #include <libata.h> #include <malloc.h> @@ -40,11 +44,10 @@ #include <asm/io.h> #include <linux/mbus.h> +#include <asm/arch/soc.h> #if defined(CONFIG_KIRKWOOD) -#include <asm/arch/kirkwood.h> #define SATAHC_BASE KW_SATA_BASE #else -#include <asm/arch/soc.h> #define SATAHC_BASE MVEBU_AXP_SATA_BASE #endif @@ -214,8 +217,8 @@ struct crqb { #define CRQB_SECTCOUNT_COUNT_EXP_MASK (0xff << 8) #define CRQB_SECTCOUNT_COUNT_EXP_SHIFT 8 -#define MVSATA_WIN_CONTROL(w) (MVEBU_AXP_SATA_BASE + 0x30 + ((w) << 4)) -#define MVSATA_WIN_BASE(w) (MVEBU_AXP_SATA_BASE + 0x34 + ((w) << 4)) +#define MVSATA_WIN_CONTROL(w) (SATAHC_BASE + 0x30 + ((w) << 4)) +#define MVSATA_WIN_BASE(w) (SATAHC_BASE + 0x34 + ((w) << 4)) struct eprd { u32 phyaddr_low; @@ -256,6 +259,7 @@ struct mv_priv { u16 pio; u16 mwdma; u16 udma; + int dev_nr; void *crqb_alloc; struct crqb *request; @@ -278,9 +282,9 @@ static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec) } /* Cut from sata_mv in linux kernel */ -static int mv_stop_edma_engine(int port) +static int mv_stop_edma_engine(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); int i; /* Disable eDMA. The disable bit auto clears. */ @@ -299,9 +303,9 @@ static int mv_stop_edma_engine(int port) return -1; } -static int mv_start_edma_engine(int port) +static int mv_start_edma_engine(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; /* Check preconditions */ @@ -351,12 +355,12 @@ static int mv_start_edma_engine(int port) return 0; } -static int mv_reset_channel(int port) +static int mv_reset_channel(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); /* Make sure edma is stopped */ - mv_stop_edma_engine(port); + mv_stop_edma_engine(dev, port); out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST); udelay(25); /* allow reset propagation */ @@ -366,11 +370,11 @@ static int mv_reset_channel(int port) return 0; } -static void mv_reset_port(int port) +static void mv_reset_port(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); - mv_reset_channel(port); + mv_reset_channel(dev, port); out_le32(priv->regbase + EDMA_CMD, 0x0); out_le32(priv->regbase + EDMA_CFG, 0x101f); @@ -392,9 +396,9 @@ static void mv_reset_one_hc(void) out_le32(SATAHC_BASE + SATAHC_ICR, 0x00); } -static int probe_port(int port) +static int probe_port(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); int tries, tries2, set15 = 0; u32 tmp; @@ -446,7 +450,7 @@ static int probe_port(int port) tmp &= ~SIR_CFG_GEN2EN; out_le32(priv->regbase + SIR_ICFG, tmp); - mv_reset_channel(port); + mv_reset_channel(dev, port); } } @@ -455,9 +459,9 @@ static int probe_port(int port) } /* Get request queue in pointer */ -static int get_reqip(int port) +static int get_reqip(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK; @@ -466,9 +470,9 @@ static int get_reqip(int port) return tmp; } -static void set_reqip(int port, int reqin) +static void set_reqip(struct udevice *dev, int port, int reqin) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK; @@ -477,17 +481,17 @@ static void set_reqip(int port, int reqin) } /* Get next available slot, ignoring possible overwrite */ -static int get_next_reqip(int port) +static int get_next_reqip(struct udevice *dev, int port) { - int slot = get_reqip(port); + int slot = get_reqip(dev, port); slot = (slot + 1) % REQUEST_QUEUE_SIZE; return slot; } /* Get response queue in pointer */ -static int get_rspip(int port) +static int get_rspip(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK; @@ -497,9 +501,9 @@ static int get_rspip(int port) } /* Get response queue out pointer */ -static int get_rspop(int port) +static int get_rspop(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK; @@ -508,15 +512,15 @@ static int get_rspop(int port) } /* Get next response queue pointer */ -static int get_next_rspop(int port) +static int get_next_rspop(struct udevice *dev, int port) { - return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE; + return (get_rspop(dev, port) + 1) % RESPONSE_QUEUE_SIZE; } /* Set response queue pointer */ -static void set_rspop(int port, int reqin) +static void set_rspop(struct udevice *dev, int port, int reqin) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); u32 tmp; tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK; @@ -525,7 +529,8 @@ static void set_rspop(int port, int reqin) out_le32(priv->regbase + EDMA_RSOPR, tmp); } -static int wait_dma_completion(int port, int index, u32 timeout_msec) +static int wait_dma_completion(struct udevice *dev, int port, int index, + u32 timeout_msec) { u32 tmp, res; @@ -538,13 +543,13 @@ static int wait_dma_completion(int port, int index, u32 timeout_msec) return res; } -static void process_responses(int port) +static void process_responses(struct udevice *dev, int port) { #ifdef DEBUG - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); #endif u32 tmp; - u32 outind = get_rspop(port); + u32 outind = get_rspop(dev, port); /* Ack interrupts */ tmp = in_le32(SATAHC_BASE + SATAHC_ICR); @@ -555,20 +560,21 @@ static void process_responses(int port) tmp &= ~(BIT(4)); out_le32(SATAHC_BASE + SATAHC_ICR, tmp); - while (get_rspip(port) != outind) { + while (get_rspip(dev, port) != outind) { #ifdef DEBUG debug("Response index %d flags %08x on port %d\n", outind, priv->response[outind].flags, port); #endif - outind = get_next_rspop(port); - set_rspop(port, outind); + outind = get_next_rspop(dev, port); + set_rspop(dev, port, outind); } } -static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, +static int mv_ata_exec_ata_cmd(struct udevice *dev, int port, + struct sata_fis_h2d *cfis, u8 *buffer, u32 len, u32 iswrite) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); struct crqb *req; int slot; u32 start; @@ -579,7 +585,7 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, } /* Initialize request */ - slot = get_reqip(port); + slot = get_reqip(dev, port); memset(&priv->request[slot], 0, sizeof(struct crqb)); req = &priv->request[slot]; @@ -633,16 +639,16 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN)); /* Trigger operation */ - slot = get_next_reqip(port); - set_reqip(port, slot); + slot = get_next_reqip(dev, port); + set_reqip(dev, port, slot); /* Wait for completion */ - if (wait_dma_completion(port, slot, 10000)) { + if (wait_dma_completion(dev, port, slot, 10000)) { printf("ATA operation timed out\n"); return -1; } - process_responses(port); + process_responses(dev, port); /* Invalidate data on read */ if (buffer && len) { @@ -654,7 +660,8 @@ static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis, return len; } -static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, +static u32 mv_sata_rw_cmd_ext(struct udevice *dev, int port, lbaint_t start, + u32 blkcnt, u8 *buffer, int is_write) { struct sata_fis_h2d cfis; @@ -678,14 +685,14 @@ static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt, cfis.sector_count_exp = (blkcnt >> 8) & 0xff; cfis.sector_count = blkcnt & 0xff; - res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt, - is_write); + res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer, + ATA_SECT_SIZE * blkcnt, is_write); return res >= 0 ? blkcnt : res; } -static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer, - int is_write) +static u32 mv_sata_rw_cmd(struct udevice *dev, int port, lbaint_t start, + u32 blkcnt, u8 *buffer, int is_write) { struct sata_fis_h2d cfis; lbaint_t block; @@ -705,20 +712,21 @@ static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer, cfis.lba_low = block & 0xff; cfis.sector_count = (u8)(blkcnt & 0xff); - res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt, - is_write); + res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer, + ATA_SECT_SIZE * blkcnt, is_write); return res >= 0 ? blkcnt : res; } -static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer, int is_write) +static u32 ata_low_level_rw(struct udevice *dev, int port, lbaint_t blknr, + lbaint_t blkcnt, void *buffer, int is_write) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); lbaint_t start, blks; u8 *addr; int max_blks; - debug("%s: %ld %ld\n", __func__, blknr, blkcnt); + debug("%s: " LBAFU " " LBAFU "\n", __func__, blknr, blkcnt); start = blknr; blks = blkcnt; @@ -727,22 +735,22 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, max_blks = MV_ATA_MAX_SECTORS; do { if (blks > max_blks) { - if (sata_dev_desc[dev].lba48) { - mv_sata_rw_cmd_ext(dev, start, max_blks, addr, - is_write); + if (desc->lba48) { + mv_sata_rw_cmd_ext(dev, port, start, max_blks, + addr, is_write); } else { - mv_sata_rw_cmd(dev, start, max_blks, addr, - is_write); + mv_sata_rw_cmd(dev, port, start, max_blks, + addr, is_write); } start += max_blks; blks -= max_blks; addr += ATA_SECT_SIZE * max_blks; } else { - if (sata_dev_desc[dev].lba48) { - mv_sata_rw_cmd_ext(dev, start, blks, addr, + if (desc->lba48) { + mv_sata_rw_cmd_ext(dev, port, start, blks, addr, is_write); } else { - mv_sata_rw_cmd(dev, start, blks, addr, + mv_sata_rw_cmd(dev, port, start, blks, addr, is_write); } start += blks; @@ -754,11 +762,11 @@ static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt, return blkcnt; } -static int mv_ata_exec_ata_cmd_nondma(int port, +static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port, struct sata_fis_h2d *cfis, u8 *buffer, u32 len, u32 iswrite) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); int i; u16 *tp; @@ -791,7 +799,7 @@ static int mv_ata_exec_ata_cmd_nondma(int port, return len; } -static int mv_sata_identify(int port, u16 *id) +static int mv_sata_identify(struct udevice *dev, int port, u16 *id) { struct sata_fis_h2d h2d; @@ -803,13 +811,13 @@ static int mv_sata_identify(int port, u16 *id) /* Give device time to get operational */ mdelay(10); - return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id, + return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id, ATA_ID_WORDS * 2, READ_CMD); } -static void mv_sata_xfer_mode(int port, u16 *id) +static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); priv->pio = id[ATA_ID_PIO_MODES]; priv->mwdma = id[ATA_ID_MWDMA_MODES]; @@ -818,9 +826,9 @@ static void mv_sata_xfer_mode(int port, u16 *id) priv->udma); } -static void mv_sata_set_features(int port) +static void mv_sata_set_features(struct udevice *dev, int port) { - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; + struct mv_priv *priv = dev_get_platdata(dev); struct sata_fis_h2d cfis; u8 udma_cap; @@ -842,53 +850,7 @@ static void mv_sata_set_features(int port) if (udma_cap == ATA_UDMA3) cfis.sector_count = XFER_UDMA_3; - mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD); -} - -int mv_sata_spin_down(int dev) -{ - struct sata_fis_h2d cfis; - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv; - - if (priv->link == 0) { - debug("No device on port: %d\n", dev); - return 1; - } - - memset(&cfis, 0, sizeof(struct sata_fis_h2d)); - - cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; - cfis.command = ATA_CMD_STANDBY; - - return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD); -} - -int mv_sata_spin_up(int dev) -{ - struct sata_fis_h2d cfis; - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv; - - if (priv->link == 0) { - debug("No device on port: %d\n", dev); - return 1; - } - - memset(&cfis, 0, sizeof(struct sata_fis_h2d)); - - cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D; - cfis.command = ATA_CMD_IDLE; - - return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD); -} - -ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) -{ - return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD); -} - -ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) -{ - return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD); + mv_ata_exec_ata_cmd_nondma(dev, port, &cfis, NULL, 0, READ_CMD); } /* @@ -916,25 +878,17 @@ static void mvsata_ide_conf_mbus_windows(void) } } -int init_sata(int dev) +static int sata_mv_init_sata(struct udevice *dev, int port) { - struct mv_priv *priv; + struct mv_priv *priv = dev_get_platdata(dev); - debug("Initialize sata dev: %d\n", dev); + debug("Initialize sata dev: %d\n", port); - if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) { - printf("Invalid sata device %d\n", dev); + if (port < 0 || port >= CONFIG_SYS_SATA_MAX_DEVICE) { + printf("Invalid sata device %d\n", port); return -1; } - priv = (struct mv_priv *)malloc(sizeof(struct mv_priv)); - if (!priv) { - printf("Failed to allocate memory for private sata data\n"); - return -ENOMEM; - } - - memset((void *)priv, 0, sizeof(struct mv_priv)); - /* Allocate and align request buffer */ priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE + CRQB_ALIGN); @@ -959,11 +913,9 @@ int init_sata(int dev) priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) & ~(CRPB_ALIGN - 1)); - sata_dev_desc[dev].priv = (void *)priv; - - sprintf(priv->name, "SATA%d", dev); + sprintf(priv->name, "SATA%d", port); - priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE; + priv->regbase = port == 0 ? SATA0_BASE : SATA1_BASE; if (!hw_init) { debug("Initialize sata hw\n"); @@ -972,9 +924,9 @@ int init_sata(int dev) mvsata_ide_conf_mbus_windows(); } - mv_reset_port(dev); + mv_reset_port(dev, port); - if (probe_port(dev)) { + if (probe_port(dev, port)) { priv->link = 0; return -ENODEV; } @@ -983,19 +935,15 @@ int init_sata(int dev) return 0; } -int reset_sata(int dev) -{ - return 0; -} - -int scan_sata(int port) +static int sata_mv_scan_sata(struct udevice *dev, int port) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + struct mv_priv *priv = dev_get_platdata(dev); unsigned char serial[ATA_ID_SERNO_LEN + 1]; unsigned char firmware[ATA_ID_FW_REV_LEN + 1]; unsigned char product[ATA_ID_PROD_LEN + 1]; u64 n_sectors; u16 *id; - struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv; if (!priv->link) return -ENODEV; @@ -1006,7 +954,7 @@ int scan_sata(int port) return -ENOMEM; } - mv_sata_identify(port, id); + mv_sata_identify(dev, port, id); ata_swap_buf_le16(id, ATA_ID_WORDS); #ifdef DEBUG ata_dump_id(id); @@ -1014,23 +962,23 @@ int scan_sata(int port) /* Serial number */ ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); - memcpy(sata_dev_desc[port].product, serial, sizeof(serial)); + memcpy(desc->product, serial, sizeof(serial)); /* Firmware version */ ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware)); - memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware)); + memcpy(desc->revision, firmware, sizeof(firmware)); /* Product model */ ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product)); - memcpy(sata_dev_desc[port].vendor, product, sizeof(product)); + memcpy(desc->vendor, product, sizeof(product)); /* Total sectors */ n_sectors = ata_id_n_sectors(id); - sata_dev_desc[port].lba = n_sectors; + desc->lba = n_sectors; /* Check if support LBA48 */ if (ata_id_has_lba48(id)) { - sata_dev_desc[port].lba48 = 1; + desc->lba48 = 1; debug("Device support LBA48\n"); } @@ -1038,13 +986,111 @@ int scan_sata(int port) priv->queue_depth = ata_id_queue_depth(id); /* Get the xfer mode from device */ - mv_sata_xfer_mode(port, id); + mv_sata_xfer_mode(dev, port, id); /* Set the xfer mode to highest speed */ - mv_sata_set_features(port); + mv_sata_set_features(dev, port); /* Start up */ - mv_start_edma_engine(port); + mv_start_edma_engine(dev, port); + + return 0; +} + +static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + struct mv_priv *priv = dev_get_platdata(blk); + + return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt, + buffer, READ_CMD); +} + +static ulong sata_mv_write(struct udevice *blk, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + struct mv_priv *priv = dev_get_platdata(blk); + + return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt, + (void *)buffer, WRITE_CMD); +} + +static const struct blk_ops sata_mv_blk_ops = { + .read = sata_mv_read, + .write = sata_mv_write, +}; + +U_BOOT_DRIVER(sata_mv_driver) = { + .name = "sata_mv_blk", + .id = UCLASS_BLK, + .ops = &sata_mv_blk_ops, + .platdata_auto_alloc_size = sizeof(struct mv_priv), +}; + +static int sata_mv_probe(struct udevice *dev) +{ + const void *blob = gd->fdt_blob; + int node = dev_of_offset(dev); + struct mv_priv *priv; + struct udevice *blk; + int nr_ports; + int ret; + int i; + + /* Get number of ports of this SATA controller */ + nr_ports = min(fdtdec_get_int(blob, node, "nr-ports", -1), + CONFIG_SYS_SATA_MAX_DEVICE); + + for (i = 0; i < nr_ports; i++) { + ret = blk_create_devicef(dev, "sata_mv_blk", "blk", + IF_TYPE_SATA, -1, 512, 0, &blk); + if (ret) { + debug("Can't create device\n"); + return ret; + } + + priv = dev_get_platdata(blk); + priv->dev_nr = i; + + /* Init SATA port */ + ret = sata_mv_init_sata(blk, i); + if (ret) { + debug("%s: Failed to init bus\n", __func__); + return ret; + } + + /* Scan SATA port */ + ret = sata_mv_scan_sata(blk, i); + if (ret) { + debug("%s: Failed to scan bus\n", __func__); + return ret; + } + } + + return 0; +} + +static int sata_mv_scan(struct udevice *dev) +{ + /* Nothing to do here */ return 0; } + +static const struct udevice_id sata_mv_ids[] = { + { .compatible = "marvell,armada-370-sata" }, + { .compatible = "marvell,orion-sata" }, + { } +}; + +struct ahci_ops sata_mv_ahci_ops = { + .scan = sata_mv_scan, +}; + +U_BOOT_DRIVER(sata_mv_ahci) = { + .name = "sata_mv_ahci", + .id = UCLASS_AHCI, + .of_match = sata_mv_ids, + .ops = &sata_mv_ahci_ops, + .probe = sata_mv_probe, +}; diff --git a/drivers/clk/altera/clk-arria10.c b/drivers/clk/altera/clk-arria10.c index 612a171..179869d 100644 --- a/drivers/clk/altera/clk-arria10.c +++ b/drivers/clk/altera/clk-arria10.c @@ -254,7 +254,8 @@ static int socfpga_a10_clk_bind(struct udevice *dev) fdt_node_check_compatible(fdt, offset, "fixed-clock")) continue; - if (pre_reloc_only && !dm_fdt_pre_reloc(fdt, offset)) + if (pre_reloc_only && + !dm_ofnode_pre_reloc(offset_to_ofnode(offset))) continue; ret = device_bind_driver_to_node(dev, "clk-a10", name, diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 7cfbabc..6b55ec5 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -61,7 +61,7 @@ int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name) offset > 0; offset = fdt_next_subnode(fdt, offset)) { if (pre_reloc_only && - !dm_fdt_pre_reloc(fdt, offset)) + !dm_ofnode_pre_reloc(offset_to_ofnode(offset))) continue; /* * If this node has "compatible" property, this is not diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index aebc6f0..24859fd 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -15,10 +15,12 @@ #include <dt-bindings/clock/stm32mp1-clks.h> #include <dt-bindings/clock/stm32mp1-clksrc.h> +#ifndef CONFIG_STM32MP1_TRUSTED #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) /* activate clock tree initialization in the driver */ #define STM32MP1_CLOCK_TREE_INIT #endif +#endif #define MAX_HSI_HZ 64000000 diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 0e584c1..785f5c3 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -254,14 +254,13 @@ int ofnode_read_size(ofnode node, const char *propname) fdt_addr_t ofnode_get_addr_index(ofnode node, int index) { int na, ns; - fdt_size_t size; if (ofnode_is_np(node)) { const __be32 *prop_val; uint flags; prop_val = of_get_address(ofnode_to_np(node), index, - (u64 *)&size, &flags); + NULL, &flags); if (!prop_val) return FDT_ADDR_T_NONE; @@ -278,7 +277,7 @@ fdt_addr_t ofnode_get_addr_index(ofnode node, int index) ns = ofnode_read_simple_size_cells(ofnode_get_parent(node)); return fdtdec_get_addr_size_fixed(gd->fdt_blob, ofnode_to_offset(node), "reg", - index, na, ns, &size, true); + index, na, ns, NULL, true); } return FDT_ADDR_T_NONE; @@ -700,18 +699,18 @@ int ofnode_read_simple_size_cells(ofnode node) bool ofnode_pre_reloc(ofnode node) { +#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD) + /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass + * had property dm-pre-reloc or u-boot,dm-spl/tpl. + * They are removed in final dtb (fdtgrep 2nd pass) + */ + return true; +#else if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) return true; if (ofnode_read_bool(node, "u-boot,dm-pre-proper")) return true; -#ifdef CONFIG_TPL_BUILD - if (ofnode_read_bool(node, "u-boot,dm-tpl")) - return true; -#elif defined(CONFIG_SPL_BUILD) - if (ofnode_read_bool(node, "u-boot,dm-spl")) - return true; -#else /* * In regular builds individual spl and tpl handling both * count as handled pre-relocation for later second init. @@ -719,9 +718,9 @@ bool ofnode_pre_reloc(ofnode node) if (ofnode_read_bool(node, "u-boot,dm-spl") || ofnode_read_bool(node, "u-boot,dm-tpl")) return true; -#endif return false; +#endif } int ofnode_read_resource(ofnode node, uint index, struct resource *res) diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c index afac6d6..5bb38e3 100644 --- a/drivers/core/syscon-uclass.c +++ b/drivers/core/syscon-uclass.c @@ -57,18 +57,64 @@ static int syscon_pre_probe(struct udevice *dev) #endif } +static int syscon_probe_by_ofnode(ofnode node, struct udevice **devp) +{ + struct udevice *dev, *parent; + int ret; + + /* found node with "syscon" compatible, not bounded to SYSCON UCLASS */ + if (!ofnode_device_is_compatible(node, "syscon")) { + dev_dbg(dev, "invalid compatible for syscon device\n"); + return -EINVAL; + } + + /* bound to driver with same ofnode or to root if not found */ + if (device_find_global_by_ofnode(node, &parent)) + parent = dm_root(); + + /* force bound to syscon class */ + ret = device_bind_driver_to_node(parent, "syscon", + ofnode_get_name(node), + node, &dev); + if (ret) { + dev_dbg(dev, "unable to bound syscon device\n"); + return ret; + } + ret = device_probe(dev); + if (ret) { + dev_dbg(dev, "unable to probe syscon device\n"); + return ret; + } + + *devp = dev; + return 0; +} + struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev, const char *name) { struct udevice *syscon; struct regmap *r; + u32 phandle; + ofnode node; int err; err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, name, &syscon); if (err) { - dev_dbg(dev, "unable to find syscon device\n"); - return ERR_PTR(err); + /* found node with "syscon" compatible, not bounded to SYSCON */ + err = ofnode_read_u32(dev_ofnode(dev), name, &phandle); + if (err) + return ERR_PTR(err); + + node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(node)) { + dev_dbg(dev, "unable to find syscon device\n"); + return ERR_PTR(-EINVAL); + } + err = syscon_probe_by_ofnode(node, &syscon); + if (err) + return ERR_PTR(-ENODEV); } r = syscon_get_regmap(syscon); @@ -152,29 +198,18 @@ U_BOOT_DRIVER(generic_syscon) = { */ struct regmap *syscon_node_to_regmap(ofnode node) { - struct udevice *dev, *parent; - int ret; - - if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev)) - return syscon_get_regmap(dev); - - if (!ofnode_device_is_compatible(node, "syscon")) - return ERR_PTR(-EINVAL); + struct udevice *dev; + struct regmap *r; - /* bound to driver with same ofnode or to root if not found */ - if (device_find_global_by_ofnode(node, &parent)) - parent = dm_root(); + if (uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev)) + if (syscon_probe_by_ofnode(node, &dev)) + return ERR_PTR(-ENODEV); - /* force bound to syscon class */ - ret = device_bind_driver_to_node(parent, "syscon", - ofnode_get_name(node), - node, &dev); - if (ret) - return ERR_PTR(ret); - - ret = device_probe(dev); - if (ret) - return ERR_PTR(ret); + r = syscon_get_regmap(dev); + if (!r) { + dev_dbg(dev, "unable to find regmap\n"); + return ERR_PTR(-ENODEV); + } - return syscon_get_regmap(dev); + return r; } diff --git a/drivers/core/util.c b/drivers/core/util.c index 27a6848..96e47dc 100644 --- a/drivers/core/util.c +++ b/drivers/core/util.c @@ -31,42 +31,18 @@ int list_count_items(struct list_head *head) return count; } -bool dm_fdt_pre_reloc(const void *blob, int offset) -{ - if (fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL)) - return true; - -#ifdef CONFIG_TPL_BUILD - if (fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL)) - return true; -#elif defined(CONFIG_SPL_BUILD) - if (fdt_getprop(blob, offset, "u-boot,dm-spl", NULL)) - return true; -#else - /* - * In regular builds individual spl and tpl handling both - * count as handled pre-relocation for later second init. - */ - if (fdt_getprop(blob, offset, "u-boot,dm-spl", NULL) || - fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL)) - return true; -#endif - - return false; -} - bool dm_ofnode_pre_reloc(ofnode node) { +#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD) + /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass + * had property dm-pre-reloc or u-boot,dm-spl/tpl. + * They are removed in final dtb (fdtgrep 2nd pass) + */ + return true; +#else if (ofnode_read_bool(node, "u-boot,dm-pre-reloc")) return true; -#ifdef CONFIG_TPL_BUILD - if (ofnode_read_bool(node, "u-boot,dm-tpl")) - return true; -#elif defined(CONFIG_SPL_BUILD) - if (ofnode_read_bool(node, "u-boot,dm-spl")) - return true; -#else /* * In regular builds individual spl and tpl handling both * count as handled pre-relocation for later second init. @@ -74,7 +50,7 @@ bool dm_ofnode_pre_reloc(ofnode node) if (ofnode_read_bool(node, "u-boot,dm-spl") || ofnode_read_bool(node, "u-boot,dm-tpl")) return true; -#endif return false; +#endif } diff --git a/drivers/ddr/marvell/axp/xor_regs.h b/drivers/ddr/marvell/axp/xor_regs.h index db5c419..d779e56 100644 --- a/drivers/ddr/marvell/axp/xor_regs.h +++ b/drivers/ddr/marvell/axp/xor_regs.h @@ -13,7 +13,11 @@ #define XOR_UNIT(chan) ((chan) >> 1) #define XOR_CHAN(chan) ((chan) & 1) +#ifdef CONFIG_ARMADA_MSYS +#define MV_XOR_REGS_OFFSET(unit) (0xF0800) +#else #define MV_XOR_REGS_OFFSET(unit) (0x60900) +#endif #define MV_XOR_REGS_BASE(unit) (MV_XOR_REGS_OFFSET(unit)) /* XOR Engine Control Register Map */ diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 1820676..4f37ba7 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -57,4 +57,6 @@ config APBH_DMA_BURST8 endif +source "drivers/dma/ti/Kconfig" + endmenu # menu "DMA Support" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index b5f9147..afab324 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -13,3 +13,5 @@ obj-$(CONFIG_SANDBOX_DMA) += sandbox-dma-test.o obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o obj-$(CONFIG_TI_EDMA3) += ti-edma3.o obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o + +obj-y += ti/ diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c index 1d3c192..e7bd1b2 100644 --- a/drivers/dma/bcm6348-iudma.c +++ b/drivers/dma/bcm6348-iudma.c @@ -324,6 +324,9 @@ static int bcm6348_iudma_receive(struct dma *dma, void **dst, void *metadata) struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring; int ret; + if (!ch_priv->running) + return -EINVAL; + /* get dma ring descriptor address */ dma_desc += ch_priv->desc_id; @@ -369,6 +372,9 @@ static int bcm6348_iudma_send(struct dma *dma, void *src, size_t len, struct bcm6348_dma_desc *dma_desc; uint16_t status; + if (!ch_priv->running) + return -EINVAL; + /* flush cache */ bcm6348_iudma_fdc(src, len); diff --git a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig new file mode 100644 index 0000000..3d54983 --- /dev/null +++ b/drivers/dma/ti/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0+ + +if ARCH_K3 + +config TI_K3_NAVSS_UDMA + bool "Texas Instruments UDMA" + depends on ARCH_K3 + select DMA + select TI_K3_NAVSS_RINGACC + select TI_K3_NAVSS_PSILCFG + default n + help + Support for UDMA used in K3 devices. +endif diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile new file mode 100644 index 0000000..de2f9ac --- /dev/null +++ b/drivers/dma/ti/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_TI_K3_NAVSS_UDMA) += k3-udma.o diff --git a/drivers/dma/ti/k3-udma-hwdef.h b/drivers/dma/ti/k3-udma-hwdef.h new file mode 100644 index 0000000..c88399a --- /dev/null +++ b/drivers/dma/ti/k3-udma-hwdef.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef K3_NAVSS_UDMA_HWDEF_H_ +#define K3_NAVSS_UDMA_HWDEF_H_ + +#define UDMA_PSIL_DST_THREAD_ID_OFFSET 0x8000 + +/* Global registers */ +#define UDMA_REV_REG 0x0 +#define UDMA_PERF_CTL_REG 0x4 +#define UDMA_EMU_CTL_REG 0x8 +#define UDMA_PSIL_TO_REG 0x10 +#define UDMA_UTC_CTL_REG 0x1c +#define UDMA_CAP_REG(i) (0x20 + (i * 4)) +#define UDMA_RX_FLOW_ID_FW_OES_REG 0x80 +#define UDMA_RX_FLOW_ID_FW_STATUS_REG 0x88 + +/* RX Flow regs */ +#define UDMA_RFLOW_RFA_REG 0x0 +#define UDMA_RFLOW_RFB_REG 0x4 +#define UDMA_RFLOW_RFC_REG 0x8 +#define UDMA_RFLOW_RFD_REG 0xc +#define UDMA_RFLOW_RFE_REG 0x10 +#define UDMA_RFLOW_RFF_REG 0x14 +#define UDMA_RFLOW_RFG_REG 0x18 +#define UDMA_RFLOW_RFH_REG 0x1c + +#define UDMA_RFLOW_REG(x) (UDMA_RFLOW_RF##x##_REG) + +/* TX chan regs */ +#define UDMA_TCHAN_TCFG_REG 0x0 +#define UDMA_TCHAN_TCREDIT_REG 0x4 +#define UDMA_TCHAN_TCQ_REG 0x14 +#define UDMA_TCHAN_TOES_REG(i) (0x20 + (i) * 4) +#define UDMA_TCHAN_TEOES_REG 0x60 +#define UDMA_TCHAN_TPRI_CTRL_REG 0x64 +#define UDMA_TCHAN_THREAD_ID_REG 0x68 +#define UDMA_TCHAN_TFIFO_DEPTH_REG 0x70 +#define UDMA_TCHAN_TST_SCHED_REG 0x80 + +/* RX chan regs */ +#define UDMA_RCHAN_RCFG_REG 0x0 +#define UDMA_RCHAN_RCQ_REG 0x14 +#define UDMA_RCHAN_ROES_REG(i) (0x20 + (i) * 4) +#define UDMA_RCHAN_REOES_REG 0x60 +#define UDMA_RCHAN_RPRI_CTRL_REG 0x64 +#define UDMA_RCHAN_THREAD_ID_REG 0x68 +#define UDMA_RCHAN_RST_SCHED_REG 0x80 +#define UDMA_RCHAN_RFLOW_RNG_REG 0xf0 + +/* TX chan RT regs */ +#define UDMA_TCHAN_RT_CTL_REG 0x0 +#define UDMA_TCHAN_RT_SWTRIG_REG 0x8 +#define UDMA_TCHAN_RT_STDATA_REG 0x80 + +#define UDMA_TCHAN_RT_PEERn_REG(i) (0x200 + (i * 0x4)) +#define UDMA_TCHAN_RT_PEER_STATIC_TR_XY_REG \ + UDMA_TCHAN_RT_PEERn_REG(0) /* PSI-L: 0x400 */ +#define UDMA_TCHAN_RT_PEER_STATIC_TR_Z_REG \ + UDMA_TCHAN_RT_PEERn_REG(1) /* PSI-L: 0x401 */ +#define UDMA_TCHAN_RT_PEER_BCNT_REG \ + UDMA_TCHAN_RT_PEERn_REG(4) /* PSI-L: 0x404 */ +#define UDMA_TCHAN_RT_PEER_RT_EN_REG \ + UDMA_TCHAN_RT_PEERn_REG(8) /* PSI-L: 0x408 */ + +#define UDMA_TCHAN_RT_PCNT_REG 0x400 +#define UDMA_TCHAN_RT_BCNT_REG 0x408 +#define UDMA_TCHAN_RT_SBCNT_REG 0x410 + +/* RX chan RT regs */ +#define UDMA_RCHAN_RT_CTL_REG 0x0 +#define UDMA_RCHAN_RT_SWTRIG_REG 0x8 +#define UDMA_RCHAN_RT_STDATA_REG 0x80 + +#define UDMA_RCHAN_RT_PEERn_REG(i) (0x200 + (i * 0x4)) +#define UDMA_RCHAN_RT_PEER_STATIC_TR_XY_REG \ + UDMA_RCHAN_RT_PEERn_REG(0) /* PSI-L: 0x400 */ +#define UDMA_RCHAN_RT_PEER_STATIC_TR_Z_REG \ + UDMA_RCHAN_RT_PEERn_REG(1) /* PSI-L: 0x401 */ +#define UDMA_RCHAN_RT_PEER_BCNT_REG \ + UDMA_RCHAN_RT_PEERn_REG(4) /* PSI-L: 0x404 */ +#define UDMA_RCHAN_RT_PEER_RT_EN_REG \ + UDMA_RCHAN_RT_PEERn_REG(8) /* PSI-L: 0x408 */ + +#define UDMA_RCHAN_RT_PCNT_REG 0x400 +#define UDMA_RCHAN_RT_BCNT_REG 0x408 +#define UDMA_RCHAN_RT_SBCNT_REG 0x410 + +/* UDMA_TCHAN_TCFG_REG/UDMA_RCHAN_RCFG_REG */ +#define UDMA_CHAN_CFG_PAUSE_ON_ERR BIT(31) +#define UDMA_TCHAN_CFG_FILT_EINFO BIT(30) +#define UDMA_TCHAN_CFG_FILT_PSWORDS BIT(29) +#define UDMA_CHAN_CFG_ATYPE_MASK GENMASK(25, 24) +#define UDMA_CHAN_CFG_ATYPE_SHIFT 24 +#define UDMA_CHAN_CFG_CHAN_TYPE_MASK GENMASK(19, 16) +#define UDMA_CHAN_CFG_CHAN_TYPE_SHIFT 16 +/* + * PBVR - using pass by value rings + * PBRR - using pass by reference rings + * 3RDP - Third Party DMA + * BC - Block Copy + * SB - single buffer packet mode enabled + */ +#define UDMA_CHAN_CFG_CHAN_TYPE_PACKET_PBRR \ + (2 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT) +#define UDMA_CHAN_CFG_CHAN_TYPE_PACKET_SB_PBRR \ + (3 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT) +#define UDMA_CHAN_CFG_CHAN_TYPE_3RDP_PBRR \ + (10 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT) +#define UDMA_CHAN_CFG_CHAN_TYPE_3RDP_PBVR \ + (11 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT) +#define UDMA_CHAN_CFG_CHAN_TYPE_3RDP_BC_PBRR \ + (12 << UDMA_CHAN_CFG_CHAN_TYPE_SHIFT) +#define UDMA_RCHAN_CFG_IGNORE_SHORT BIT(15) +#define UDMA_RCHAN_CFG_IGNORE_LONG BIT(14) +#define UDMA_TCHAN_CFG_SUPR_TDPKT BIT(8) +#define UDMA_CHAN_CFG_FETCH_SIZE_MASK GENMASK(6, 0) +#define UDMA_CHAN_CFG_FETCH_SIZE_SHIFT 0 + +/* UDMA_TCHAN_RT_CTL_REG/UDMA_RCHAN_RT_CTL_REG */ +#define UDMA_CHAN_RT_CTL_EN BIT(31) +#define UDMA_CHAN_RT_CTL_TDOWN BIT(30) +#define UDMA_CHAN_RT_CTL_PAUSE BIT(29) +#define UDMA_CHAN_RT_CTL_FTDOWN BIT(28) +#define UDMA_CHAN_RT_CTL_ERROR BIT(0) + +/* UDMA_TCHAN_RT_PEER_RT_EN_REG/UDMA_RCHAN_RT_PEER_RT_EN_REG (PSI-L: 0x408) */ +#define UDMA_PEER_RT_EN_ENABLE BIT(31) +#define UDMA_PEER_RT_EN_TEARDOWN BIT(30) +#define UDMA_PEER_RT_EN_PAUSE BIT(29) +#define UDMA_PEER_RT_EN_FLUSH BIT(28) +#define UDMA_PEER_RT_EN_IDLE BIT(1) + +/* RX Flow reg RFA */ +#define UDMA_RFLOW_RFA_EINFO BIT(30) +#define UDMA_RFLOW_RFA_PSINFO BIT(29) +#define UDMA_RFLOW_RFA_ERR_HANDLING BIT(28) +#define UDMA_RFLOW_RFA_DESC_TYPE_MASK GENMASK(27, 26) +#define UDMA_RFLOW_RFA_DESC_TYPE_SHIFT 26 +#define UDMA_RFLOW_RFA_PS_LOC BIT(25) +#define UDMA_RFLOW_RFA_SOP_OFF_MASK GENMASK(24, 16) +#define UDMA_RFLOW_RFA_SOP_OFF_SHIFT 16 +#define UDMA_RFLOW_RFA_DEST_QNUM_MASK GENMASK(15, 0) +#define UDMA_RFLOW_RFA_DEST_QNUM_SHIFT 0 + +/* RX Flow reg RFC */ +#define UDMA_RFLOW_RFC_SRC_TAG_HI_SEL_SHIFT 28 +#define UDMA_RFLOW_RFC_SRC_TAG_LO_SEL_SHIFT 24 +#define UDMA_RFLOW_RFC_DST_TAG_HI_SEL_SHIFT 20 +#define UDMA_RFLOW_RFC_DST_TAG_LO_SE_SHIFT 16 + +/* + * UDMA_TCHAN_RT_PEER_STATIC_TR_XY_REG / + * UDMA_RCHAN_RT_PEER_STATIC_TR_XY_REG + */ +#define PDMA_STATIC_TR_X_MASK GENMASK(26, 24) +#define PDMA_STATIC_TR_X_SHIFT (24) +#define PDMA_STATIC_TR_Y_MASK GENMASK(11, 0) +#define PDMA_STATIC_TR_Y_SHIFT (0) + +#define PDMA_STATIC_TR_Y(x) \ + (((x) << PDMA_STATIC_TR_Y_SHIFT) & PDMA_STATIC_TR_Y_MASK) +#define PDMA_STATIC_TR_X(x) \ + (((x) << PDMA_STATIC_TR_X_SHIFT) & PDMA_STATIC_TR_X_MASK) + +/* + * UDMA_TCHAN_RT_PEER_STATIC_TR_Z_REG / + * UDMA_RCHAN_RT_PEER_STATIC_TR_Z_REG + */ +#define PDMA_STATIC_TR_Z_MASK GENMASK(11, 0) +#define PDMA_STATIC_TR_Z_SHIFT (0) +#define PDMA_STATIC_TR_Z(x) \ + (((x) << PDMA_STATIC_TR_Z_SHIFT) & PDMA_STATIC_TR_Z_MASK) + +#endif /* K3_NAVSS_UDMA_HWDEF_H_ */ diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c new file mode 100644 index 0000000..f78a01a --- /dev/null +++ b/drivers/dma/ti/k3-udma.c @@ -0,0 +1,1730 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ +#define pr_fmt(fmt) "udma: " fmt + +#include <common.h> +#include <asm/io.h> +#include <asm/bitops.h> +#include <malloc.h> +#include <asm/dma-mapping.h> +#include <dm.h> +#include <dm/read.h> +#include <dm/of_access.h> +#include <dma.h> +#include <dma-uclass.h> +#include <linux/delay.h> +#include <dt-bindings/dma/k3-udma.h> +#include <linux/soc/ti/k3-navss-ringacc.h> +#include <linux/soc/ti/cppi5.h> +#include <linux/soc/ti/ti-udma.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +#include "k3-udma-hwdef.h" + +#if BITS_PER_LONG == 64 +#define RINGACC_RING_USE_PROXY (0) +#else +#define RINGACC_RING_USE_PROXY (1) +#endif + +struct udma_chan; + +enum udma_mmr { + MMR_GCFG = 0, + MMR_RCHANRT, + MMR_TCHANRT, + MMR_LAST, +}; + +static const char * const mmr_names[] = { + "gcfg", "rchanrt", "tchanrt" +}; + +struct udma_tchan { + void __iomem *reg_rt; + + int id; + struct k3_nav_ring *t_ring; /* Transmit ring */ + struct k3_nav_ring *tc_ring; /* Transmit Completion ring */ +}; + +struct udma_rchan { + void __iomem *reg_rt; + + int id; + struct k3_nav_ring *fd_ring; /* Free Descriptor ring */ + struct k3_nav_ring *r_ring; /* Receive ring*/ +}; + +struct udma_rflow { + int id; +}; + +struct udma_dev { + struct device *dev; + void __iomem *mmrs[MMR_LAST]; + + struct k3_nav_ringacc *ringacc; + + u32 features; + + int tchan_cnt; + int echan_cnt; + int rchan_cnt; + int rflow_cnt; + unsigned long *tchan_map; + unsigned long *rchan_map; + unsigned long *rflow_map; + + struct udma_tchan *tchans; + struct udma_rchan *rchans; + struct udma_rflow *rflows; + + struct udma_chan *channels; + u32 psil_base; + + u32 ch_count; + const struct ti_sci_handle *tisci; + const struct ti_sci_rm_udmap_ops *tisci_udmap_ops; + const struct ti_sci_rm_psil_ops *tisci_psil_ops; + u32 tisci_dev_id; + u32 tisci_navss_dev_id; + bool is_coherent; +}; + +struct udma_chan { + struct udma_dev *ud; + char name[20]; + + struct udma_tchan *tchan; + struct udma_rchan *rchan; + struct udma_rflow *rflow; + + u32 bcnt; /* number of bytes completed since the start of the channel */ + + bool pkt_mode; /* TR or packet */ + bool needs_epib; /* EPIB is needed for the communication or not */ + u32 psd_size; /* size of Protocol Specific Data */ + u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */ + int slave_thread_id; + u32 src_thread; + u32 dst_thread; + u32 static_tr_type; + + u32 id; + enum dma_direction dir; + + struct cppi5_host_desc_t *desc_tx; + u32 hdesc_size; + bool in_use; + void *desc_rx; + u32 num_rx_bufs; + u32 desc_rx_cur; + +}; + +#define UDMA_CH_1000(ch) (ch * 0x1000) +#define UDMA_CH_100(ch) (ch * 0x100) +#define UDMA_CH_40(ch) (ch * 0x40) + +#ifdef PKTBUFSRX +#define UDMA_RX_DESC_NUM PKTBUFSRX +#else +#define UDMA_RX_DESC_NUM 4 +#endif + +/* Generic register access functions */ +static inline u32 udma_read(void __iomem *base, int reg) +{ + u32 v; + + v = __raw_readl(base + reg); + pr_debug("READL(32): v(%08X)<--reg(%p)\n", v, base + reg); + return v; +} + +static inline void udma_write(void __iomem *base, int reg, u32 val) +{ + pr_debug("WRITEL(32): v(%08X)-->reg(%p)\n", val, base + reg); + __raw_writel(val, base + reg); +} + +static inline void udma_update_bits(void __iomem *base, int reg, + u32 mask, u32 val) +{ + u32 tmp, orig; + + orig = udma_read(base, reg); + tmp = orig & ~mask; + tmp |= (val & mask); + + if (tmp != orig) + udma_write(base, reg, tmp); +} + +/* TCHANRT */ +static inline u32 udma_tchanrt_read(struct udma_tchan *tchan, int reg) +{ + if (!tchan) + return 0; + return udma_read(tchan->reg_rt, reg); +} + +static inline void udma_tchanrt_write(struct udma_tchan *tchan, + int reg, u32 val) +{ + if (!tchan) + return; + udma_write(tchan->reg_rt, reg, val); +} + +/* RCHANRT */ +static inline u32 udma_rchanrt_read(struct udma_rchan *rchan, int reg) +{ + if (!rchan) + return 0; + return udma_read(rchan->reg_rt, reg); +} + +static inline void udma_rchanrt_write(struct udma_rchan *rchan, + int reg, u32 val) +{ + if (!rchan) + return; + udma_write(rchan->reg_rt, reg, val); +} + +static inline int udma_navss_psil_pair(struct udma_dev *ud, u32 src_thread, + u32 dst_thread) +{ + dst_thread |= UDMA_PSIL_DST_THREAD_ID_OFFSET; + return ud->tisci_psil_ops->pair(ud->tisci, + ud->tisci_navss_dev_id, + src_thread, dst_thread); +} + +static inline int udma_navss_psil_unpair(struct udma_dev *ud, u32 src_thread, + u32 dst_thread) +{ + dst_thread |= UDMA_PSIL_DST_THREAD_ID_OFFSET; + return ud->tisci_psil_ops->unpair(ud->tisci, + ud->tisci_navss_dev_id, + src_thread, dst_thread); +} + +static inline char *udma_get_dir_text(enum dma_direction dir) +{ + switch (dir) { + case DMA_DEV_TO_MEM: + return "DEV_TO_MEM"; + case DMA_MEM_TO_DEV: + return "MEM_TO_DEV"; + case DMA_MEM_TO_MEM: + return "MEM_TO_MEM"; + case DMA_DEV_TO_DEV: + return "DEV_TO_DEV"; + default: + break; + } + + return "invalid"; +} + +static inline bool udma_is_chan_running(struct udma_chan *uc) +{ + u32 trt_ctl = 0; + u32 rrt_ctl = 0; + + switch (uc->dir) { + case DMA_DEV_TO_MEM: + rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG); + pr_debug("%s: rrt_ctl: 0x%08x (peer: 0x%08x)\n", + __func__, rrt_ctl, + udma_rchanrt_read(uc->rchan, + UDMA_RCHAN_RT_PEER_RT_EN_REG)); + break; + case DMA_MEM_TO_DEV: + trt_ctl = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG); + pr_debug("%s: trt_ctl: 0x%08x (peer: 0x%08x)\n", + __func__, trt_ctl, + udma_tchanrt_read(uc->tchan, + UDMA_TCHAN_RT_PEER_RT_EN_REG)); + break; + case DMA_MEM_TO_MEM: + trt_ctl = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG); + rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG); + break; + default: + break; + } + + if (trt_ctl & UDMA_CHAN_RT_CTL_EN || rrt_ctl & UDMA_CHAN_RT_CTL_EN) + return true; + + return false; +} + +static int udma_is_coherent(struct udma_chan *uc) +{ + return uc->ud->is_coherent; +} + +static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr) +{ + struct k3_nav_ring *ring = NULL; + int ret = -ENOENT; + + switch (uc->dir) { + case DMA_DEV_TO_MEM: + ring = uc->rchan->r_ring; + break; + case DMA_MEM_TO_DEV: + ring = uc->tchan->tc_ring; + break; + case DMA_MEM_TO_MEM: + ring = uc->tchan->tc_ring; + break; + default: + break; + } + + if (ring && k3_nav_ringacc_ring_get_occ(ring)) + ret = k3_nav_ringacc_ring_pop(ring, addr); + + return ret; +} + +static void udma_reset_rings(struct udma_chan *uc) +{ + struct k3_nav_ring *ring1 = NULL; + struct k3_nav_ring *ring2 = NULL; + + switch (uc->dir) { + case DMA_DEV_TO_MEM: + ring1 = uc->rchan->fd_ring; + ring2 = uc->rchan->r_ring; + break; + case DMA_MEM_TO_DEV: + ring1 = uc->tchan->t_ring; + ring2 = uc->tchan->tc_ring; + break; + case DMA_MEM_TO_MEM: + ring1 = uc->tchan->t_ring; + ring2 = uc->tchan->tc_ring; + break; + default: + break; + } + + if (ring1) + k3_nav_ringacc_ring_reset_dma(ring1, 0); + if (ring2) + k3_nav_ringacc_ring_reset(ring2); +} + +static void udma_reset_counters(struct udma_chan *uc) +{ + u32 val; + + if (uc->tchan) { + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_BCNT_REG); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_BCNT_REG, val); + + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_SBCNT_REG); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_SBCNT_REG, val); + + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PCNT_REG); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PCNT_REG, val); + + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG, val); + } + + if (uc->rchan) { + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_BCNT_REG); + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_BCNT_REG, val); + + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_SBCNT_REG); + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_SBCNT_REG, val); + + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PCNT_REG); + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PCNT_REG, val); + + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PEER_BCNT_REG); + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_BCNT_REG, val); + } + + uc->bcnt = 0; +} + +static inline int udma_stop_hard(struct udma_chan *uc) +{ + pr_debug("%s: ENTER (chan%d)\n", __func__, uc->id); + + switch (uc->dir) { + case DMA_DEV_TO_MEM: + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, 0); + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0); + break; + case DMA_MEM_TO_DEV: + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, 0); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_RT_EN_REG, 0); + break; + case DMA_MEM_TO_MEM: + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int udma_start(struct udma_chan *uc) +{ + /* Channel is already running, no need to proceed further */ + if (udma_is_chan_running(uc)) + goto out; + + pr_debug("%s: chan:%d dir:%s (static_tr_type: %d)\n", + __func__, uc->id, udma_get_dir_text(uc->dir), + uc->static_tr_type); + + /* Make sure that we clear the teardown bit, if it is set */ + udma_stop_hard(uc); + + /* Reset all counters */ + udma_reset_counters(uc); + + switch (uc->dir) { + case DMA_DEV_TO_MEM: + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, + UDMA_CHAN_RT_CTL_EN); + + /* Enable remote */ + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, + UDMA_PEER_RT_EN_ENABLE); + + pr_debug("%s(rx): RT_CTL:0x%08x PEER RT_ENABLE:0x%08x\n", + __func__, + udma_rchanrt_read(uc->rchan, + UDMA_RCHAN_RT_CTL_REG), + udma_rchanrt_read(uc->rchan, + UDMA_RCHAN_RT_PEER_RT_EN_REG)); + break; + case DMA_MEM_TO_DEV: + /* Enable remote */ + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_RT_EN_REG, + UDMA_PEER_RT_EN_ENABLE); + + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, + UDMA_CHAN_RT_CTL_EN); + + pr_debug("%s(tx): RT_CTL:0x%08x PEER RT_ENABLE:0x%08x\n", + __func__, + udma_rchanrt_read(uc->rchan, + UDMA_TCHAN_RT_CTL_REG), + udma_rchanrt_read(uc->rchan, + UDMA_TCHAN_RT_PEER_RT_EN_REG)); + break; + case DMA_MEM_TO_MEM: + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, + UDMA_CHAN_RT_CTL_EN); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, + UDMA_CHAN_RT_CTL_EN); + + break; + default: + return -EINVAL; + } + + pr_debug("%s: DONE chan:%d\n", __func__, uc->id); +out: + return 0; +} + +static inline void udma_stop_mem2dev(struct udma_chan *uc, bool sync) +{ + int i = 0; + u32 val; + + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, + UDMA_CHAN_RT_CTL_EN | + UDMA_CHAN_RT_CTL_TDOWN); + + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG); + + while (sync && (val & UDMA_CHAN_RT_CTL_EN)) { + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_CTL_REG); + udelay(1); + if (i > 1000) { + printf(" %s TIMEOUT !\n", __func__); + break; + } + i++; + } + + val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_RT_EN_REG); + if (val & UDMA_PEER_RT_EN_ENABLE) + printf("%s: peer not stopped TIMEOUT !\n", __func__); +} + +static inline void udma_stop_dev2mem(struct udma_chan *uc, bool sync) +{ + int i = 0; + u32 val; + + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, + UDMA_PEER_RT_EN_ENABLE | + UDMA_PEER_RT_EN_TEARDOWN); + + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG); + + while (sync && (val & UDMA_CHAN_RT_CTL_EN)) { + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG); + udelay(1); + if (i > 1000) { + printf("%s TIMEOUT !\n", __func__); + break; + } + i++; + } + + val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG); + if (val & UDMA_PEER_RT_EN_ENABLE) + printf("%s: peer not stopped TIMEOUT !\n", __func__); +} + +static inline int udma_stop(struct udma_chan *uc) +{ + pr_debug("%s: chan:%d dir:%s\n", + __func__, uc->id, udma_get_dir_text(uc->dir)); + + udma_reset_counters(uc); + switch (uc->dir) { + case DMA_DEV_TO_MEM: + udma_stop_dev2mem(uc, true); + break; + case DMA_MEM_TO_DEV: + udma_stop_mem2dev(uc, true); + break; + case DMA_MEM_TO_MEM: + udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0); + udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_CTL_REG, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void udma_poll_completion(struct udma_chan *uc, dma_addr_t *paddr) +{ + int i = 1; + + while (udma_pop_from_ring(uc, paddr)) { + udelay(1); + if (!(i % 1000000)) + printf("."); + i++; + } +} + +#define UDMA_RESERVE_RESOURCE(res) \ +static struct udma_##res *__udma_reserve_##res(struct udma_dev *ud, \ + int id) \ +{ \ + if (id >= 0) { \ + if (test_bit(id, ud->res##_map)) { \ + dev_err(ud->dev, "res##%d is in use\n", id); \ + return ERR_PTR(-ENOENT); \ + } \ + } else { \ + id = find_first_zero_bit(ud->res##_map, ud->res##_cnt); \ + if (id == ud->res##_cnt) { \ + return ERR_PTR(-ENOENT); \ + } \ + } \ + \ + __set_bit(id, ud->res##_map); \ + return &ud->res##s[id]; \ +} + +UDMA_RESERVE_RESOURCE(tchan); +UDMA_RESERVE_RESOURCE(rchan); +UDMA_RESERVE_RESOURCE(rflow); + +static int udma_get_tchan(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + + if (uc->tchan) { + dev_dbg(ud->dev, "chan%d: already have tchan%d allocated\n", + uc->id, uc->tchan->id); + return 0; + } + + uc->tchan = __udma_reserve_tchan(ud, -1); + if (IS_ERR(uc->tchan)) + return PTR_ERR(uc->tchan); + + pr_debug("chan%d: got tchan%d\n", uc->id, uc->tchan->id); + + if (udma_is_chan_running(uc)) { + dev_warn(ud->dev, "chan%d: tchan%d is running!\n", uc->id, + uc->tchan->id); + udma_stop(uc); + if (udma_is_chan_running(uc)) + dev_err(ud->dev, "chan%d: won't stop!\n", uc->id); + } + + return 0; +} + +static int udma_get_rchan(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + + if (uc->rchan) { + dev_dbg(ud->dev, "chan%d: already have rchan%d allocated\n", + uc->id, uc->rchan->id); + return 0; + } + + uc->rchan = __udma_reserve_rchan(ud, -1); + if (IS_ERR(uc->rchan)) + return PTR_ERR(uc->rchan); + + pr_debug("chan%d: got rchan%d\n", uc->id, uc->rchan->id); + + if (udma_is_chan_running(uc)) { + dev_warn(ud->dev, "chan%d: rchan%d is running!\n", uc->id, + uc->rchan->id); + udma_stop(uc); + if (udma_is_chan_running(uc)) + dev_err(ud->dev, "chan%d: won't stop!\n", uc->id); + } + + return 0; +} + +static int udma_get_chan_pair(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + int chan_id, end; + + if ((uc->tchan && uc->rchan) && uc->tchan->id == uc->rchan->id) { + dev_info(ud->dev, "chan%d: already have %d pair allocated\n", + uc->id, uc->tchan->id); + return 0; + } + + if (uc->tchan) { + dev_err(ud->dev, "chan%d: already have tchan%d allocated\n", + uc->id, uc->tchan->id); + return -EBUSY; + } else if (uc->rchan) { + dev_err(ud->dev, "chan%d: already have rchan%d allocated\n", + uc->id, uc->rchan->id); + return -EBUSY; + } + + /* Can be optimized, but let's have it like this for now */ + end = min(ud->tchan_cnt, ud->rchan_cnt); + for (chan_id = 0; chan_id < end; chan_id++) { + if (!test_bit(chan_id, ud->tchan_map) && + !test_bit(chan_id, ud->rchan_map)) + break; + } + + if (chan_id == end) + return -ENOENT; + + __set_bit(chan_id, ud->tchan_map); + __set_bit(chan_id, ud->rchan_map); + uc->tchan = &ud->tchans[chan_id]; + uc->rchan = &ud->rchans[chan_id]; + + pr_debug("chan%d: got t/rchan%d pair\n", uc->id, chan_id); + + if (udma_is_chan_running(uc)) { + dev_warn(ud->dev, "chan%d: t/rchan%d pair is running!\n", + uc->id, chan_id); + udma_stop(uc); + if (udma_is_chan_running(uc)) + dev_err(ud->dev, "chan%d: won't stop!\n", uc->id); + } + + return 0; +} + +static int udma_get_rflow(struct udma_chan *uc, int flow_id) +{ + struct udma_dev *ud = uc->ud; + + if (uc->rflow) { + dev_dbg(ud->dev, "chan%d: already have rflow%d allocated\n", + uc->id, uc->rflow->id); + return 0; + } + + if (!uc->rchan) + dev_warn(ud->dev, "chan%d: does not have rchan??\n", uc->id); + + uc->rflow = __udma_reserve_rflow(ud, flow_id); + if (IS_ERR(uc->rflow)) + return PTR_ERR(uc->rflow); + + pr_debug("chan%d: got rflow%d\n", uc->id, uc->rflow->id); + return 0; +} + +static void udma_put_rchan(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + + if (uc->rchan) { + dev_dbg(ud->dev, "chan%d: put rchan%d\n", uc->id, + uc->rchan->id); + __clear_bit(uc->rchan->id, ud->rchan_map); + uc->rchan = NULL; + } +} + +static void udma_put_tchan(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + + if (uc->tchan) { + dev_dbg(ud->dev, "chan%d: put tchan%d\n", uc->id, + uc->tchan->id); + __clear_bit(uc->tchan->id, ud->tchan_map); + uc->tchan = NULL; + } +} + +static void udma_put_rflow(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + + if (uc->rflow) { + dev_dbg(ud->dev, "chan%d: put rflow%d\n", uc->id, + uc->rflow->id); + __clear_bit(uc->rflow->id, ud->rflow_map); + uc->rflow = NULL; + } +} + +static void udma_free_tx_resources(struct udma_chan *uc) +{ + if (!uc->tchan) + return; + + k3_nav_ringacc_ring_free(uc->tchan->t_ring); + k3_nav_ringacc_ring_free(uc->tchan->tc_ring); + uc->tchan->t_ring = NULL; + uc->tchan->tc_ring = NULL; + + udma_put_tchan(uc); +} + +static int udma_alloc_tx_resources(struct udma_chan *uc) +{ + struct k3_nav_ring_cfg ring_cfg; + struct udma_dev *ud = uc->ud; + int ret; + + ret = udma_get_tchan(uc); + if (ret) + return ret; + + uc->tchan->t_ring = k3_nav_ringacc_request_ring( + ud->ringacc, uc->tchan->id, + RINGACC_RING_USE_PROXY); + if (!uc->tchan->t_ring) { + ret = -EBUSY; + goto err_tx_ring; + } + + uc->tchan->tc_ring = k3_nav_ringacc_request_ring( + ud->ringacc, -1, RINGACC_RING_USE_PROXY); + if (!uc->tchan->tc_ring) { + ret = -EBUSY; + goto err_txc_ring; + } + + memset(&ring_cfg, 0, sizeof(ring_cfg)); + ring_cfg.size = 16; + ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8; + ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_MESSAGE; + + ret = k3_nav_ringacc_ring_cfg(uc->tchan->t_ring, &ring_cfg); + ret |= k3_nav_ringacc_ring_cfg(uc->tchan->tc_ring, &ring_cfg); + + if (ret) + goto err_ringcfg; + + return 0; + +err_ringcfg: + k3_nav_ringacc_ring_free(uc->tchan->tc_ring); + uc->tchan->tc_ring = NULL; +err_txc_ring: + k3_nav_ringacc_ring_free(uc->tchan->t_ring); + uc->tchan->t_ring = NULL; +err_tx_ring: + udma_put_tchan(uc); + + return ret; +} + +static void udma_free_rx_resources(struct udma_chan *uc) +{ + if (!uc->rchan) + return; + + k3_nav_ringacc_ring_free(uc->rchan->fd_ring); + k3_nav_ringacc_ring_free(uc->rchan->r_ring); + uc->rchan->fd_ring = NULL; + uc->rchan->r_ring = NULL; + + udma_put_rflow(uc); + udma_put_rchan(uc); +} + +static int udma_alloc_rx_resources(struct udma_chan *uc) +{ + struct k3_nav_ring_cfg ring_cfg; + struct udma_dev *ud = uc->ud; + int fd_ring_id; + int ret; + + ret = udma_get_rchan(uc); + if (ret) + return ret; + + /* For MEM_TO_MEM we don't need rflow or rings */ + if (uc->dir == DMA_MEM_TO_MEM) + return 0; + + ret = udma_get_rflow(uc, uc->rchan->id); + if (ret) { + ret = -EBUSY; + goto err_rflow; + } + + fd_ring_id = ud->tchan_cnt + ud->echan_cnt + uc->rchan->id; + + uc->rchan->fd_ring = k3_nav_ringacc_request_ring( + ud->ringacc, fd_ring_id, + RINGACC_RING_USE_PROXY); + if (!uc->rchan->fd_ring) { + ret = -EBUSY; + goto err_rx_ring; + } + + uc->rchan->r_ring = k3_nav_ringacc_request_ring( + ud->ringacc, -1, RINGACC_RING_USE_PROXY); + if (!uc->rchan->r_ring) { + ret = -EBUSY; + goto err_rxc_ring; + } + + memset(&ring_cfg, 0, sizeof(ring_cfg)); + ring_cfg.size = 16; + ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8; + ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_MESSAGE; + + ret = k3_nav_ringacc_ring_cfg(uc->rchan->fd_ring, &ring_cfg); + ret |= k3_nav_ringacc_ring_cfg(uc->rchan->r_ring, &ring_cfg); + + if (ret) + goto err_ringcfg; + + return 0; + +err_ringcfg: + k3_nav_ringacc_ring_free(uc->rchan->r_ring); + uc->rchan->r_ring = NULL; +err_rxc_ring: + k3_nav_ringacc_ring_free(uc->rchan->fd_ring); + uc->rchan->fd_ring = NULL; +err_rx_ring: + udma_put_rflow(uc); +err_rflow: + udma_put_rchan(uc); + + return ret; +} + +static int udma_alloc_tchan_sci_req(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); + struct ti_sci_msg_rm_udmap_tx_ch_cfg req; + u32 mode; + int ret; + + if (uc->pkt_mode) + mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; + else + mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; + + req.valid_params = TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID; + req.nav_id = ud->tisci_dev_id; + req.index = uc->tchan->id; + req.tx_chan_type = mode; + if (uc->dir == DMA_MEM_TO_MEM) + req.tx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; + else + req.tx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib, + uc->psd_size, + 0) >> 2; + req.txcq_qnum = tc_ring; + + ret = ud->tisci_udmap_ops->tx_ch_cfg(ud->tisci, &req); + if (ret) + dev_err(ud->dev, "tisci tx alloc failed %d\n", ret); + + return ret; +} + +static int udma_alloc_rchan_sci_req(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + int fd_ring = k3_nav_ringacc_get_ring_id(uc->rchan->fd_ring); + int rx_ring = k3_nav_ringacc_get_ring_id(uc->rchan->r_ring); + int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); + struct ti_sci_msg_rm_udmap_rx_ch_cfg req = { 0 }; + struct ti_sci_msg_rm_udmap_flow_cfg flow_req = { 0 }; + u32 mode; + int ret; + + if (uc->pkt_mode) + mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; + else + mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; + + req.valid_params = TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID; + req.nav_id = ud->tisci_dev_id; + req.index = uc->rchan->id; + req.rx_chan_type = mode; + if (uc->dir == DMA_MEM_TO_MEM) { + req.rx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; + req.rxcq_qnum = tc_ring; + } else { + req.rx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib, + uc->psd_size, + 0) >> 2; + req.rxcq_qnum = rx_ring; + } + if (uc->rflow->id != uc->rchan->id && uc->dir != DMA_MEM_TO_MEM) { + req.flowid_start = uc->rflow->id; + req.flowid_cnt = 1; + req.valid_params |= + TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID; + } + + ret = ud->tisci_udmap_ops->rx_ch_cfg(ud->tisci, &req); + if (ret) { + dev_err(ud->dev, "tisci rx %u cfg failed %d\n", + uc->rchan->id, ret); + return ret; + } + if (uc->dir == DMA_MEM_TO_MEM) + return ret; + + flow_req.valid_params = + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID | + TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PS_LOCATION_VALID; + + flow_req.nav_id = ud->tisci_dev_id; + flow_req.flow_index = uc->rflow->id; + + if (uc->needs_epib) + flow_req.rx_einfo_present = 1; + else + flow_req.rx_einfo_present = 0; + + if (uc->psd_size) + flow_req.rx_psinfo_present = 1; + else + flow_req.rx_psinfo_present = 0; + + flow_req.rx_error_handling = 0; + flow_req.rx_desc_type = 0; + flow_req.rx_dest_qnum = rx_ring; + flow_req.rx_src_tag_hi_sel = 2; + flow_req.rx_src_tag_lo_sel = 4; + flow_req.rx_dest_tag_hi_sel = 5; + flow_req.rx_dest_tag_lo_sel = 4; + flow_req.rx_fdq0_sz0_qnum = fd_ring; + flow_req.rx_fdq1_qnum = fd_ring; + flow_req.rx_fdq2_qnum = fd_ring; + flow_req.rx_fdq3_qnum = fd_ring; + flow_req.rx_ps_location = 0; + + ret = ud->tisci_udmap_ops->rx_flow_cfg(ud->tisci, &flow_req); + if (ret) + dev_err(ud->dev, "tisci rx %u flow %u cfg failed %d\n", + uc->rchan->id, uc->rflow->id, ret); + + return ret; +} + +static int udma_alloc_chan_resources(struct udma_chan *uc) +{ + struct udma_dev *ud = uc->ud; + int ret; + + pr_debug("%s: chan:%d as %s\n", + __func__, uc->id, udma_get_dir_text(uc->dir)); + + switch (uc->dir) { + case DMA_MEM_TO_MEM: + /* Non synchronized - mem to mem type of transfer */ + ret = udma_get_chan_pair(uc); + if (ret) + return ret; + + ret = udma_alloc_tx_resources(uc); + if (ret) + goto err_free_res; + + ret = udma_alloc_rx_resources(uc); + if (ret) + goto err_free_res; + + uc->src_thread = ud->psil_base + uc->tchan->id; + uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; + break; + case DMA_MEM_TO_DEV: + /* Slave transfer synchronized - mem to dev (TX) trasnfer */ + ret = udma_alloc_tx_resources(uc); + if (ret) + goto err_free_res; + + uc->src_thread = ud->psil_base + uc->tchan->id; + uc->dst_thread = uc->slave_thread_id; + if (!(uc->dst_thread & 0x8000)) + uc->dst_thread |= 0x8000; + + break; + case DMA_DEV_TO_MEM: + /* Slave transfer synchronized - dev to mem (RX) trasnfer */ + ret = udma_alloc_rx_resources(uc); + if (ret) + goto err_free_res; + + uc->src_thread = uc->slave_thread_id; + uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; + + break; + default: + /* Can not happen */ + pr_debug("%s: chan:%d invalid direction (%u)\n", + __func__, uc->id, uc->dir); + return -EINVAL; + } + + /* We have channel indexes and rings */ + if (uc->dir == DMA_MEM_TO_MEM) { + ret = udma_alloc_tchan_sci_req(uc); + if (ret) + goto err_free_res; + + ret = udma_alloc_rchan_sci_req(uc); + if (ret) + goto err_free_res; + } else { + /* Slave transfer */ + if (uc->dir == DMA_MEM_TO_DEV) { + ret = udma_alloc_tchan_sci_req(uc); + if (ret) + goto err_free_res; + } else { + ret = udma_alloc_rchan_sci_req(uc); + if (ret) + goto err_free_res; + } + } + + /* PSI-L pairing */ + ret = udma_navss_psil_pair(ud, uc->src_thread, uc->dst_thread); + if (ret) { + dev_err(ud->dev, "k3_nav_psil_request_link fail\n"); + goto err_free_res; + } + + return 0; + +err_free_res: + udma_free_tx_resources(uc); + udma_free_rx_resources(uc); + uc->slave_thread_id = -1; + return ret; +} + +static void udma_free_chan_resources(struct udma_chan *uc) +{ + /* Some configuration to UDMA-P channel: disable, reset, whatever */ + + /* Release PSI-L pairing */ + udma_navss_psil_unpair(uc->ud, uc->src_thread, uc->dst_thread); + + /* Reset the rings for a new start */ + udma_reset_rings(uc); + udma_free_tx_resources(uc); + udma_free_rx_resources(uc); + + uc->slave_thread_id = -1; + uc->dir = DMA_MEM_TO_MEM; +} + +static int udma_get_mmrs(struct udevice *dev) +{ + struct udma_dev *ud = dev_get_priv(dev); + int i; + + for (i = 0; i < MMR_LAST; i++) { + ud->mmrs[i] = (uint32_t *)devfdt_get_addr_name(dev, + mmr_names[i]); + if (!ud->mmrs[i]) + return -EINVAL; + } + + return 0; +} + +#define UDMA_MAX_CHANNELS 192 + +static int udma_probe(struct udevice *dev) +{ + struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct udma_dev *ud = dev_get_priv(dev); + int i, ret; + u32 cap2, cap3; + struct udevice *tmp; + struct udevice *tisci_dev = NULL; + + ret = udma_get_mmrs(dev); + if (ret) + return ret; + + ret = uclass_get_device_by_phandle(UCLASS_MISC, dev, + "ti,ringacc", &tmp); + ud->ringacc = dev_get_priv(tmp); + if (IS_ERR(ud->ringacc)) + return PTR_ERR(ud->ringacc); + + ud->psil_base = dev_read_u32_default(dev, "ti,psil-base", 0); + if (!ud->psil_base) { + dev_info(dev, + "Missing ti,psil-base property, using %d.\n", ret); + return -EINVAL; + } + + ret = uclass_get_device_by_name(UCLASS_FIRMWARE, "dmsc", &tisci_dev); + if (ret) { + debug("TISCI RA RM get failed (%d)\n", ret); + ud->tisci = NULL; + return 0; + } + ud->tisci = (struct ti_sci_handle *) + (ti_sci_get_handle_from_sysfw(tisci_dev)); + + ret = dev_read_u32_default(dev, "ti,sci", 0); + if (!ret) { + dev_err(dev, "TISCI RA RM disabled\n"); + ud->tisci = NULL; + } + + if (ud->tisci) { + ofnode navss_ofnode = ofnode_get_parent(dev_ofnode(dev)); + + ud->tisci_dev_id = -1; + ret = dev_read_u32(dev, "ti,sci-dev-id", &ud->tisci_dev_id); + if (ret) { + dev_err(dev, "ti,sci-dev-id read failure %d\n", ret); + return ret; + } + + ud->tisci_navss_dev_id = -1; + ret = ofnode_read_u32(navss_ofnode, "ti,sci-dev-id", + &ud->tisci_navss_dev_id); + if (ret) { + dev_err(dev, "navss sci-dev-id read failure %d\n", ret); + return ret; + } + + ud->tisci_udmap_ops = &ud->tisci->ops.rm_udmap_ops; + ud->tisci_psil_ops = &ud->tisci->ops.rm_psil_ops; + } + + ud->is_coherent = dev_read_bool(dev, "dma-coherent"); + + cap2 = udma_read(ud->mmrs[MMR_GCFG], 0x28); + cap3 = udma_read(ud->mmrs[MMR_GCFG], 0x2c); + + ud->rflow_cnt = cap3 & 0x3fff; + ud->tchan_cnt = cap2 & 0x1ff; + ud->echan_cnt = (cap2 >> 9) & 0x1ff; + ud->rchan_cnt = (cap2 >> 18) & 0x1ff; + ud->ch_count = ud->tchan_cnt + ud->rchan_cnt; + + dev_info(dev, + "Number of channels: %u (tchan: %u, echan: %u, rchan: %u dev-id %u)\n", + ud->ch_count, ud->tchan_cnt, ud->echan_cnt, ud->rchan_cnt, + ud->tisci_dev_id); + dev_info(dev, "Number of rflows: %u\n", ud->rflow_cnt); + + ud->channels = devm_kcalloc(dev, ud->ch_count, sizeof(*ud->channels), + GFP_KERNEL); + ud->tchan_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->tchan_cnt), + sizeof(unsigned long), GFP_KERNEL); + ud->tchans = devm_kcalloc(dev, ud->tchan_cnt, + sizeof(*ud->tchans), GFP_KERNEL); + ud->rchan_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->rchan_cnt), + sizeof(unsigned long), GFP_KERNEL); + ud->rchans = devm_kcalloc(dev, ud->rchan_cnt, + sizeof(*ud->rchans), GFP_KERNEL); + ud->rflow_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->rflow_cnt), + sizeof(unsigned long), GFP_KERNEL); + ud->rflows = devm_kcalloc(dev, ud->rflow_cnt, + sizeof(*ud->rflows), GFP_KERNEL); + + if (!ud->channels || !ud->tchan_map || !ud->rchan_map || + !ud->rflow_map || !ud->tchans || !ud->rchans || !ud->rflows) + return -ENOMEM; + + for (i = 0; i < ud->tchan_cnt; i++) { + struct udma_tchan *tchan = &ud->tchans[i]; + + tchan->id = i; + tchan->reg_rt = ud->mmrs[MMR_TCHANRT] + UDMA_CH_1000(i); + } + + for (i = 0; i < ud->rchan_cnt; i++) { + struct udma_rchan *rchan = &ud->rchans[i]; + + rchan->id = i; + rchan->reg_rt = ud->mmrs[MMR_RCHANRT] + UDMA_CH_1000(i); + } + + for (i = 0; i < ud->rflow_cnt; i++) { + struct udma_rflow *rflow = &ud->rflows[i]; + + rflow->id = i; + } + + for (i = 0; i < ud->ch_count; i++) { + struct udma_chan *uc = &ud->channels[i]; + + uc->ud = ud; + uc->id = i; + uc->slave_thread_id = -1; + uc->tchan = NULL; + uc->rchan = NULL; + uc->dir = DMA_MEM_TO_MEM; + sprintf(uc->name, "UDMA chan%d\n", i); + if (!i) + uc->in_use = true; + } + + pr_debug("UDMA(rev: 0x%08x) CAP0-3: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + udma_read(ud->mmrs[MMR_GCFG], 0), + udma_read(ud->mmrs[MMR_GCFG], 0x20), + udma_read(ud->mmrs[MMR_GCFG], 0x24), + udma_read(ud->mmrs[MMR_GCFG], 0x28), + udma_read(ud->mmrs[MMR_GCFG], 0x2c)); + + uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM | DMA_SUPPORTS_MEM_TO_DEV; + + return ret; +} + +static int *udma_prep_dma_memcpy(struct udma_chan *uc, dma_addr_t dest, + dma_addr_t src, size_t len) +{ + u32 tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); + struct cppi5_tr_type15_t *tr_req; + int num_tr; + size_t tr_size = sizeof(struct cppi5_tr_type15_t); + u16 tr0_cnt0, tr0_cnt1, tr1_cnt0; + unsigned long dummy; + void *tr_desc; + size_t desc_size; + + if (len < SZ_64K) { + num_tr = 1; + tr0_cnt0 = len; + tr0_cnt1 = 1; + } else { + unsigned long align_to = __ffs(src | dest); + + if (align_to > 3) + align_to = 3; + /* + * Keep simple: tr0: SZ_64K-alignment blocks, + * tr1: the remaining + */ + num_tr = 2; + tr0_cnt0 = (SZ_64K - BIT(align_to)); + if (len / tr0_cnt0 >= SZ_64K) { + dev_err(uc->ud->dev, "size %zu is not supported\n", + len); + return NULL; + } + + tr0_cnt1 = len / tr0_cnt0; + tr1_cnt0 = len % tr0_cnt0; + } + + desc_size = cppi5_trdesc_calc_size(num_tr, tr_size); + tr_desc = dma_alloc_coherent(desc_size, &dummy); + if (!tr_desc) + return NULL; + memset(tr_desc, 0, desc_size); + + cppi5_trdesc_init(tr_desc, num_tr, tr_size, 0, 0); + cppi5_desc_set_pktids(tr_desc, uc->id, 0x3fff); + cppi5_desc_set_retpolicy(tr_desc, 0, tc_ring_id); + + tr_req = tr_desc + tr_size; + + cppi5_tr_init(&tr_req[0].flags, CPPI5_TR_TYPE15, false, true, + CPPI5_TR_EVENT_SIZE_COMPLETION, 1); + cppi5_tr_csf_set(&tr_req[0].flags, CPPI5_TR_CSF_SUPR_EVT); + + tr_req[0].addr = src; + tr_req[0].icnt0 = tr0_cnt0; + tr_req[0].icnt1 = tr0_cnt1; + tr_req[0].icnt2 = 1; + tr_req[0].icnt3 = 1; + tr_req[0].dim1 = tr0_cnt0; + + tr_req[0].daddr = dest; + tr_req[0].dicnt0 = tr0_cnt0; + tr_req[0].dicnt1 = tr0_cnt1; + tr_req[0].dicnt2 = 1; + tr_req[0].dicnt3 = 1; + tr_req[0].ddim1 = tr0_cnt0; + + if (num_tr == 2) { + cppi5_tr_init(&tr_req[1].flags, CPPI5_TR_TYPE15, false, true, + CPPI5_TR_EVENT_SIZE_COMPLETION, 0); + cppi5_tr_csf_set(&tr_req[1].flags, CPPI5_TR_CSF_SUPR_EVT); + + tr_req[1].addr = src + tr0_cnt1 * tr0_cnt0; + tr_req[1].icnt0 = tr1_cnt0; + tr_req[1].icnt1 = 1; + tr_req[1].icnt2 = 1; + tr_req[1].icnt3 = 1; + + tr_req[1].daddr = dest + tr0_cnt1 * tr0_cnt0; + tr_req[1].dicnt0 = tr1_cnt0; + tr_req[1].dicnt1 = 1; + tr_req[1].dicnt2 = 1; + tr_req[1].dicnt3 = 1; + } + + cppi5_tr_csf_set(&tr_req[num_tr - 1].flags, CPPI5_TR_CSF_EOP); + + if (!udma_is_coherent(uc)) { + flush_dcache_range((u64)tr_desc, + ALIGN((u64)tr_desc + desc_size, + ARCH_DMA_MINALIGN)); + } + + k3_nav_ringacc_ring_push(uc->tchan->t_ring, &tr_desc); + + return 0; +} + +static int udma_transfer(struct udevice *dev, int direction, + void *dst, void *src, size_t len) +{ + struct udma_dev *ud = dev_get_priv(dev); + /* Channel0 is reserved for memcpy */ + struct udma_chan *uc = &ud->channels[0]; + dma_addr_t paddr = 0; + int ret; + + ret = udma_alloc_chan_resources(uc); + if (ret) + return ret; + + udma_prep_dma_memcpy(uc, (dma_addr_t)dst, (dma_addr_t)src, len); + udma_start(uc); + udma_poll_completion(uc, &paddr); + udma_stop(uc); + + udma_free_chan_resources(uc); + return 0; +} + +static int udma_request(struct dma *dma) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan *uc; + unsigned long dummy; + int ret; + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + + uc = &ud->channels[dma->id]; + ret = udma_alloc_chan_resources(uc); + if (ret) { + dev_err(dma->dev, "alloc dma res failed %d\n", ret); + return -EINVAL; + } + + uc->hdesc_size = cppi5_hdesc_calc_size(uc->needs_epib, + uc->psd_size, 0); + uc->hdesc_size = ALIGN(uc->hdesc_size, ARCH_DMA_MINALIGN); + + if (uc->dir == DMA_MEM_TO_DEV) { + uc->desc_tx = dma_alloc_coherent(uc->hdesc_size, &dummy); + memset(uc->desc_tx, 0, uc->hdesc_size); + } else { + uc->desc_rx = dma_alloc_coherent( + uc->hdesc_size * UDMA_RX_DESC_NUM, &dummy); + memset(uc->desc_rx, 0, uc->hdesc_size * UDMA_RX_DESC_NUM); + } + + uc->in_use = true; + uc->desc_rx_cur = 0; + uc->num_rx_bufs = 0; + + return 0; +} + +static int udma_free(struct dma *dma) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan *uc; + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + uc = &ud->channels[dma->id]; + + if (udma_is_chan_running(uc)) + udma_stop(uc); + udma_free_chan_resources(uc); + + uc->in_use = false; + + return 0; +} + +static int udma_enable(struct dma *dma) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan *uc; + int ret; + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + uc = &ud->channels[dma->id]; + + ret = udma_start(uc); + + return ret; +} + +static int udma_disable(struct dma *dma) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan *uc; + int ret = 0; + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + uc = &ud->channels[dma->id]; + + if (udma_is_chan_running(uc)) + ret = udma_stop(uc); + else + dev_err(dma->dev, "%s not running\n", __func__); + + return ret; +} + +static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct cppi5_host_desc_t *desc_tx; + dma_addr_t dma_src = (dma_addr_t)src; + struct ti_udma_drv_packet_data packet_data = { 0 }; + dma_addr_t paddr; + struct udma_chan *uc; + u32 tc_ring_id; + int ret; + + if (!metadata) + packet_data = *((struct ti_udma_drv_packet_data *)metadata); + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + uc = &ud->channels[dma->id]; + + if (uc->dir != DMA_MEM_TO_DEV) + return -EINVAL; + + tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); + + desc_tx = uc->desc_tx; + + cppi5_hdesc_reset_hbdesc(desc_tx); + + cppi5_hdesc_init(desc_tx, + uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, + uc->psd_size); + cppi5_hdesc_set_pktlen(desc_tx, len); + cppi5_hdesc_attach_buf(desc_tx, dma_src, len, dma_src, len); + cppi5_desc_set_pktids(&desc_tx->hdr, uc->id, 0x3fff); + cppi5_desc_set_retpolicy(&desc_tx->hdr, 0, tc_ring_id); + /* pass below information from caller */ + cppi5_hdesc_set_pkttype(desc_tx, packet_data.pkt_type); + cppi5_desc_set_tags_ids(&desc_tx->hdr, 0, packet_data.dest_tag); + + if (!udma_is_coherent(uc)) { + flush_dcache_range((u64)dma_src, + ALIGN((u64)dma_src + len, + ARCH_DMA_MINALIGN)); + flush_dcache_range((u64)desc_tx, + ALIGN((u64)desc_tx + uc->hdesc_size, + ARCH_DMA_MINALIGN)); + } + + ret = k3_nav_ringacc_ring_push(uc->tchan->t_ring, &uc->desc_tx); + if (ret) { + dev_err(dma->dev, "TX dma push fail ch_id %lu %d\n", + dma->id, ret); + return ret; + } + + udma_poll_completion(uc, &paddr); + + return 0; +} + +static int udma_receive(struct dma *dma, void **dst, void *metadata) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct cppi5_host_desc_t *desc_rx; + dma_addr_t buf_dma; + struct udma_chan *uc; + u32 buf_dma_len, pkt_len; + u32 port_id = 0; + int ret; + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + uc = &ud->channels[dma->id]; + + if (uc->dir != DMA_DEV_TO_MEM) + return -EINVAL; + if (!uc->num_rx_bufs) + return -EINVAL; + + ret = k3_nav_ringacc_ring_pop(uc->rchan->r_ring, &desc_rx); + if (ret && ret != -ENODATA) { + dev_err(dma->dev, "rx dma fail ch_id:%lu %d\n", dma->id, ret); + return ret; + } else if (ret == -ENODATA) { + return 0; + } + + /* invalidate cache data */ + if (!udma_is_coherent(uc)) { + invalidate_dcache_range((ulong)desc_rx, + (ulong)(desc_rx + uc->hdesc_size)); + } + + cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); + pkt_len = cppi5_hdesc_get_pktlen(desc_rx); + + /* invalidate cache data */ + if (!udma_is_coherent(uc)) { + invalidate_dcache_range((ulong)buf_dma, + (ulong)(buf_dma + buf_dma_len)); + } + + cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL); + + *dst = (void *)buf_dma; + uc->num_rx_bufs--; + + return pkt_len; +} + +static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan *uc = &ud->channels[0]; + ofnode chconf_node, slave_node; + char prop[50]; + u32 val; + + for (val = 0; val < ud->ch_count; val++) { + uc = &ud->channels[val]; + if (!uc->in_use) + break; + } + + if (val == ud->ch_count) + return -EBUSY; + + uc->dir = DMA_DEV_TO_MEM; + if (args->args[2] == UDMA_DIR_TX) + uc->dir = DMA_MEM_TO_DEV; + + slave_node = ofnode_get_by_phandle(args->args[0]); + if (!ofnode_valid(slave_node)) { + dev_err(ud->dev, "slave node is missing\n"); + return -EINVAL; + } + + snprintf(prop, sizeof(prop), "ti,psil-config%u", args->args[1]); + chconf_node = ofnode_find_subnode(slave_node, prop); + if (!ofnode_valid(chconf_node)) { + dev_err(ud->dev, "Channel configuration node is missing\n"); + return -EINVAL; + } + + if (!ofnode_read_u32(chconf_node, "linux,udma-mode", &val)) { + if (val == UDMA_PKT_MODE) + uc->pkt_mode = true; + } + + if (!ofnode_read_u32(chconf_node, "statictr-type", &val)) + uc->static_tr_type = val; + + uc->needs_epib = ofnode_read_bool(chconf_node, "ti,needs-epib"); + if (!ofnode_read_u32(chconf_node, "ti,psd-size", &val)) + uc->psd_size = val; + uc->metadata_size = (uc->needs_epib ? 16 : 0) + uc->psd_size; + + if (ofnode_read_u32(slave_node, "ti,psil-base", &val)) { + dev_err(ud->dev, "ti,psil-base is missing\n"); + return -EINVAL; + } + + uc->slave_thread_id = val + args->args[1]; + + dma->id = uc->id; + pr_debug("Allocated dma chn:%lu epib:%d psdata:%u meta:%u thread_id:%x\n", + dma->id, uc->needs_epib, + uc->psd_size, uc->metadata_size, + uc->slave_thread_id); + + return 0; +} + +int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size) +{ + struct udma_dev *ud = dev_get_priv(dma->dev); + struct cppi5_host_desc_t *desc_rx; + dma_addr_t dma_dst; + struct udma_chan *uc; + u32 desc_num; + + if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) { + dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id); + return -EINVAL; + } + uc = &ud->channels[dma->id]; + + if (uc->dir != DMA_DEV_TO_MEM) + return -EINVAL; + + if (uc->num_rx_bufs >= UDMA_RX_DESC_NUM) + return -EINVAL; + + desc_num = uc->desc_rx_cur % UDMA_RX_DESC_NUM; + desc_rx = uc->desc_rx + (desc_num * uc->hdesc_size); + dma_dst = (dma_addr_t)dst; + + cppi5_hdesc_reset_hbdesc(desc_rx); + + cppi5_hdesc_init(desc_rx, + uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, + uc->psd_size); + cppi5_hdesc_set_pktlen(desc_rx, size); + cppi5_hdesc_attach_buf(desc_rx, dma_dst, size, dma_dst, size); + + if (!udma_is_coherent(uc)) { + flush_dcache_range((u64)desc_rx, + ALIGN((u64)desc_rx + uc->hdesc_size, + ARCH_DMA_MINALIGN)); + } + + k3_nav_ringacc_ring_push(uc->rchan->fd_ring, &desc_rx); + + uc->num_rx_bufs++; + uc->desc_rx_cur++; + + return 0; +} + +static const struct dma_ops udma_ops = { + .transfer = udma_transfer, + .of_xlate = udma_of_xlate, + .request = udma_request, + .free = udma_free, + .enable = udma_enable, + .disable = udma_disable, + .send = udma_send, + .receive = udma_receive, + .prepare_rcv_buf = udma_prepare_rcv_buf, +}; + +static const struct udevice_id udma_ids[] = { + { .compatible = "ti,k3-navss-udmap" }, + { } +}; + +U_BOOT_DRIVER(ti_edma3) = { + .name = "ti-udma", + .id = UCLASS_DMA, + .of_match = udma_ids, + .ops = &udma_ops, + .probe = udma_probe, + .priv_auto_alloc_size = sizeof(struct udma_dev), +}; diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 9148126..d47d22f 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -12,6 +12,7 @@ #include <errno.h> #include <mailbox.h> #include <dm/device.h> +#include <linux/compat.h> #include <linux/err.h> #include <linux/soc/ti/k3-sec-proxy.h> #include <linux/soc/ti/ti_sci_protocol.h> @@ -32,15 +33,36 @@ struct ti_sci_xfer { }; /** + * struct ti_sci_rm_type_map - Structure representing TISCI Resource + * management representation of dev_ids. + * @dev_id: TISCI device ID + * @type: Corresponding id as identified by TISCI RM. + * + * Note: This is used only as a work around for using RM range apis + * for AM654 SoC. For future SoCs dev_id will be used as type + * for RM range APIs. In order to maintain ABI backward compatibility + * type is not being changed for AM654 SoC. + */ +struct ti_sci_rm_type_map { + u32 dev_id; + u16 type; +}; + +/** * struct ti_sci_desc - Description of SoC integration - * @host_id: Host identifier representing the compute entity - * @max_rx_timeout_us: Timeout for communication with SoC (in Microseconds) - * @max_msg_size: Maximum size of data per message that can be handled. + * @default_host_id: Host identifier representing the compute entity + * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) + * @max_msgs: Maximum number of messages that can be pending + * simultaneously in the system + * @max_msg_size: Maximum size of data per message that can be handled. + * @rm_type_map: RM resource type mapping structure. */ struct ti_sci_desc { - u8 host_id; - int max_rx_timeout_us; + u8 default_host_id; + int max_rx_timeout_ms; + int max_msgs; int max_msg_size; + struct ti_sci_rm_type_map *rm_type_map; }; /** @@ -136,7 +158,7 @@ static inline int ti_sci_get_response(struct ti_sci_info *info, int ret; /* Receive the response */ - ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us); + ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_ms); if (ret) { dev_err(info->dev, "%s: Message receive failed. ret = %d\n", __func__, ret); @@ -1441,6 +1463,199 @@ static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) return ret; } +static int ti_sci_get_resource_type(struct ti_sci_info *info, u16 dev_id, + u16 *type) +{ + struct ti_sci_rm_type_map *rm_type_map = info->desc->rm_type_map; + bool found = false; + int i; + + /* If map is not provided then assume dev_id is used as type */ + if (!rm_type_map) { + *type = dev_id; + return 0; + } + + for (i = 0; rm_type_map[i].dev_id; i++) { + if (rm_type_map[i].dev_id == dev_id) { + *type = rm_type_map[i].type; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return 0; +} + +/** + * ti_sci_get_resource_range - Helper to get a range of resources assigned + * to a host. Resource is uniquely identified by + * type and subtype. + * @handle: Pointer to TISCI handle. + * @dev_id: TISCI device ID. + * @subtype: Resource assignment subtype that is being requested + * from the given device. + * @s_host: Host processor ID to which the resources are allocated + * @range_start: Start index of the resource range + * @range_num: Number of resources in the range + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_get_resource_range(const struct ti_sci_handle *handle, + u32 dev_id, u8 subtype, u8 s_host, + u16 *range_start, u16 *range_num) +{ + struct ti_sci_msg_resp_get_resource_range *resp; + struct ti_sci_msg_req_get_resource_range req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + u16 type; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_RESOURCE_RANGE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + ret = ti_sci_get_resource_type(info, dev_id, &type); + if (ret) { + dev_err(dev, "rm type lookup failed for %u\n", dev_id); + goto fail; + } + + req.secondary_host = s_host; + req.type = type & MSG_RM_RESOURCE_TYPE_MASK; + req.subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_resp_get_resource_range *)xfer->tx_message.buf; + if (!ti_sci_is_response_ack(resp)) { + ret = -ENODEV; + } else if (!resp->range_start && !resp->range_num) { + ret = -ENODEV; + } else { + *range_start = resp->range_start; + *range_num = resp->range_num; + }; + +fail: + return ret; +} + +/** + * ti_sci_cmd_get_resource_range - Get a range of resources assigned to host + * that is same as ti sci interface host. + * @handle: Pointer to TISCI handle. + * @dev_id: TISCI device ID. + * @subtype: Resource assignment subtype that is being requested + * from the given device. + * @range_start: Start index of the resource range + * @range_num: Number of resources in the range + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_resource_range(const struct ti_sci_handle *handle, + u32 dev_id, u8 subtype, + u16 *range_start, u16 *range_num) +{ + return ti_sci_get_resource_range(handle, dev_id, subtype, + TI_SCI_IRQ_SECONDARY_HOST_INVALID, + range_start, range_num); +} + +/** + * ti_sci_cmd_get_resource_range_from_shost - Get a range of resources + * assigned to a specified host. + * @handle: Pointer to TISCI handle. + * @dev_id: TISCI device ID. + * @subtype: Resource assignment subtype that is being requested + * from the given device. + * @s_host: Host processor ID to which the resources are allocated + * @range_start: Start index of the resource range + * @range_num: Number of resources in the range + * + * Return: 0 if all went fine, else return appropriate error. + */ +static +int ti_sci_cmd_get_resource_range_from_shost(const struct ti_sci_handle *handle, + u32 dev_id, u8 subtype, u8 s_host, + u16 *range_start, u16 *range_num) +{ + return ti_sci_get_resource_range(handle, dev_id, subtype, s_host, + range_start, range_num); +} + +/** + * ti_sci_cmd_query_msmc() - Command to query currently available msmc memory + * @handle: pointer to TI SCI handle + * @msms_start: MSMC start as returned by tisci + * @msmc_end: MSMC end as returned by tisci + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_query_msmc(const struct ti_sci_handle *handle, + u64 *msmc_start, u64 *msmc_end) +{ + struct ti_sci_msg_resp_query_msmc *resp; + struct ti_sci_msg_hdr req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_QUERY_MSMC, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_query_msmc *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + *msmc_start = ((u64)resp->msmc_start_high << TISCI_ADDR_HIGH_SHIFT) | + resp->msmc_start_low; + *msmc_end = ((u64)resp->msmc_end_high << TISCI_ADDR_HIGH_SHIFT) | + resp->msmc_end_low; + + return ret; +} + /** * ti_sci_cmd_proc_request() - Command to request a physical processor control * @handle: Pointer to TI SCI handle @@ -1803,6 +2018,416 @@ static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_cmd_ring_config() - configure RA ring + * @handle: pointer to TI SCI handle + * @valid_params: Bitfield defining validity of ring configuration parameters. + * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @index: Ring index. + * @addr_lo: The ring base address lo 32 bits + * @addr_hi: The ring base address hi 32 bits + * @count: Number of ring elements. + * @mode: The mode of the ring + * @size: The ring element size. + * @order_id: Specifies the ring's bus order ID. + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_ring_cfg_req for more info. + */ +static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle, + u32 valid_params, u16 nav_id, u16 index, + u32 addr_lo, u32 addr_hi, u32 count, + u8 mode, u8 size, u8 order_id) +{ + struct ti_sci_msg_rm_ring_cfg_resp *resp; + struct ti_sci_msg_rm_ring_cfg_req req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_RING_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "RM_RA:Message config failed(%d)\n", ret); + return ret; + } + req.valid_params = valid_params; + req.nav_id = nav_id; + req.index = index; + req.addr_lo = addr_lo; + req.addr_hi = addr_hi; + req.count = count; + req.mode = mode; + req.size = size; + req.order_id = order_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "RM_RA:Mbox config send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_rm_ring_cfg_resp *)xfer->tx_message.buf; + + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + dev_dbg(info->dev, "RM_RA:config ring %u ret:%d\n", index, ret); + return ret; +} + +/** + * ti_sci_cmd_ring_get_config() - get RA ring configuration + * @handle: pointer to TI SCI handle + * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @index: Ring index. + * @addr_lo: returns ring's base address lo 32 bits + * @addr_hi: returns ring's base address hi 32 bits + * @count: returns number of ring elements. + * @mode: returns mode of the ring + * @size: returns ring element size. + * @order_id: returns ring's bus order ID. + * + * Return: 0 if all went well, else returns appropriate error value. + * + * See @ti_sci_msg_rm_ring_get_cfg_req for more info. + */ +static int ti_sci_cmd_ring_get_config(const struct ti_sci_handle *handle, + u32 nav_id, u32 index, u8 *mode, + u32 *addr_lo, u32 *addr_hi, + u32 *count, u8 *size, u8 *order_id) +{ + struct ti_sci_msg_rm_ring_get_cfg_resp *resp; + struct ti_sci_msg_rm_ring_get_cfg_req req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_RING_GET_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, + "RM_RA:Message get config failed(%d)\n", ret); + return ret; + } + req.nav_id = nav_id; + req.index = index; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "RM_RA:Mbox get config send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_rm_ring_get_cfg_resp *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) { + ret = -ENODEV; + } else { + if (mode) + *mode = resp->mode; + if (addr_lo) + *addr_lo = resp->addr_lo; + if (addr_hi) + *addr_hi = resp->addr_hi; + if (count) + *count = resp->count; + if (size) + *size = resp->size; + if (order_id) + *order_id = resp->order_id; + }; + +fail: + dev_dbg(info->dev, "RM_RA:get config ring %u ret:%d\n", index, ret); + return ret; +} + +static int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle, + u32 nav_id, u32 src_thread, u32 dst_thread) +{ + struct ti_sci_msg_hdr *resp; + struct ti_sci_msg_psil_pair req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "RM_PSIL:Message alloc failed(%d)\n", ret); + return ret; + } + req.nav_id = nav_id; + req.src_thread = src_thread; + req.dst_thread = dst_thread; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "RM_PSIL:Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + dev_dbg(info->dev, "RM_PSIL: nav: %u link pair %u->%u ret:%u\n", + nav_id, src_thread, dst_thread, ret); + return ret; +} + +static int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle, + u32 nav_id, u32 src_thread, u32 dst_thread) +{ + struct ti_sci_msg_hdr *resp; + struct ti_sci_msg_psil_unpair req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "RM_PSIL:Message alloc failed(%d)\n", ret); + return ret; + } + req.nav_id = nav_id; + req.src_thread = src_thread; + req.dst_thread = dst_thread; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "RM_PSIL:Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; + +fail: + dev_dbg(info->dev, "RM_PSIL: link unpair %u->%u ret:%u\n", + src_thread, dst_thread, ret); + return ret; +} + +static int ti_sci_cmd_rm_udmap_tx_ch_cfg( + const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params) +{ + struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *resp; + struct ti_sci_msg_rm_udmap_tx_ch_cfg_req req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message TX_CH_CFG alloc failed(%d)\n", ret); + return ret; + } + req.valid_params = params->valid_params; + req.nav_id = params->nav_id; + req.index = params->index; + req.tx_pause_on_err = params->tx_pause_on_err; + req.tx_filt_einfo = params->tx_filt_einfo; + req.tx_filt_pswords = params->tx_filt_pswords; + req.tx_atype = params->tx_atype; + req.tx_chan_type = params->tx_chan_type; + req.tx_supr_tdpkt = params->tx_supr_tdpkt; + req.tx_fetch_size = params->tx_fetch_size; + req.tx_credit_count = params->tx_credit_count; + req.txcq_qnum = params->txcq_qnum; + req.tx_priority = params->tx_priority; + req.tx_qos = params->tx_qos; + req.tx_orderid = params->tx_orderid; + req.fdepth = params->fdepth; + req.tx_sched_priority = params->tx_sched_priority; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send TX_CH_CFG fail %d\n", ret); + goto fail; + } + + resp = + (struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp *)xfer->tx_message.buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + dev_dbg(info->dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret); + return ret; +} + +static int ti_sci_cmd_rm_udmap_rx_ch_cfg( + const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params) +{ + struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *resp; + struct ti_sci_msg_rm_udmap_rx_ch_cfg_req req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message RX_CH_CFG alloc failed(%d)\n", ret); + return ret; + } + + req.valid_params = params->valid_params; + req.nav_id = params->nav_id; + req.index = params->index; + req.rx_fetch_size = params->rx_fetch_size; + req.rxcq_qnum = params->rxcq_qnum; + req.rx_priority = params->rx_priority; + req.rx_qos = params->rx_qos; + req.rx_orderid = params->rx_orderid; + req.rx_sched_priority = params->rx_sched_priority; + req.flowid_start = params->flowid_start; + req.flowid_cnt = params->flowid_cnt; + req.rx_pause_on_err = params->rx_pause_on_err; + req.rx_atype = params->rx_atype; + req.rx_chan_type = params->rx_chan_type; + req.rx_ignore_short = params->rx_ignore_short; + req.rx_ignore_long = params->rx_ignore_long; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send RX_CH_CFG fail %d\n", ret); + goto fail; + } + + resp = + (struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp *)xfer->tx_message.buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + dev_dbg(info->dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret); + return ret; +} + +static int ti_sci_cmd_rm_udmap_rx_flow_cfg( + const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_flow_cfg *params) +{ + struct ti_sci_msg_rm_udmap_flow_cfg_resp *resp; + struct ti_sci_msg_rm_udmap_flow_cfg_req req; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "RX_FL_CFG: Message alloc failed(%d)\n", ret); + return ret; + } + + req.valid_params = params->valid_params; + req.nav_id = params->nav_id; + req.flow_index = params->flow_index; + req.rx_einfo_present = params->rx_einfo_present; + req.rx_psinfo_present = params->rx_psinfo_present; + req.rx_error_handling = params->rx_error_handling; + req.rx_desc_type = params->rx_desc_type; + req.rx_sop_offset = params->rx_sop_offset; + req.rx_dest_qnum = params->rx_dest_qnum; + req.rx_src_tag_hi = params->rx_src_tag_hi; + req.rx_src_tag_lo = params->rx_src_tag_lo; + req.rx_dest_tag_hi = params->rx_dest_tag_hi; + req.rx_dest_tag_lo = params->rx_dest_tag_lo; + req.rx_src_tag_hi_sel = params->rx_src_tag_hi_sel; + req.rx_src_tag_lo_sel = params->rx_src_tag_lo_sel; + req.rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel; + req.rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel; + req.rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum; + req.rx_fdq1_qnum = params->rx_fdq1_qnum; + req.rx_fdq2_qnum = params->rx_fdq2_qnum; + req.rx_fdq3_qnum = params->rx_fdq3_qnum; + req.rx_ps_location = params->rx_ps_location; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "RX_FL_CFG: Mbox send fail %d\n", ret); + goto fail; + } + + resp = + (struct ti_sci_msg_rm_udmap_flow_cfg_resp *)xfer->tx_message.buf; + ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; + +fail: + dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret); + return ret; +} + /* * ti_sci_setup_ops() - Setup the operations structures * @info: pointer to TISCI pointer @@ -1814,7 +2439,11 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) struct ti_sci_dev_ops *dops = &ops->dev_ops; struct ti_sci_clk_ops *cops = &ops->clk_ops; struct ti_sci_core_ops *core_ops = &ops->core_ops; + struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; struct ti_sci_proc_ops *pops = &ops->proc_ops; + struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops; + struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops; + struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops; bops->board_config = ti_sci_cmd_set_board_config; bops->board_config_rm = ti_sci_cmd_set_board_config_rm; @@ -1849,6 +2478,11 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) cops->get_freq = ti_sci_cmd_clk_get_freq; core_ops->reboot_device = ti_sci_cmd_core_reboot; + core_ops->query_msmc = ti_sci_cmd_query_msmc; + + rm_core_ops->get_range = ti_sci_cmd_get_resource_range; + rm_core_ops->get_range_from_shost = + ti_sci_cmd_get_resource_range_from_shost; pops->proc_request = ti_sci_cmd_proc_request; pops->proc_release = ti_sci_cmd_proc_release; @@ -1857,6 +2491,16 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl; pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image; pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status; + + rops->config = ti_sci_cmd_ring_config; + rops->get_config = ti_sci_cmd_ring_get_config; + + psilops->pair = ti_sci_cmd_rm_psil_pair; + psilops->unpair = ti_sci_cmd_rm_psil_unpair; + + udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg; + udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg; + udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg; } /** @@ -1969,7 +2613,7 @@ static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info) } info->host_id = dev_read_u32_default(dev, "ti,host-id", - info->desc->host_id); + info->desc->default_host_id); info->is_secure = dev_read_bool(dev, "ti,secure-host"); @@ -2009,17 +2653,164 @@ static int ti_sci_probe(struct udevice *dev) return ret; } +/* + * ti_sci_get_free_resource() - Get a free resource from TISCI resource. + * @res: Pointer to the TISCI resource + * + * Return: resource num if all went ok else TI_SCI_RESOURCE_NULL. + */ +u16 ti_sci_get_free_resource(struct ti_sci_resource *res) +{ + u16 set, free_bit; + + for (set = 0; set < res->sets; set++) { + free_bit = find_first_zero_bit(res->desc[set].res_map, + res->desc[set].num); + if (free_bit != res->desc[set].num) { + set_bit(free_bit, res->desc[set].res_map); + return res->desc[set].start + free_bit; + } + } + + return TI_SCI_RESOURCE_NULL; +} + +/** + * ti_sci_release_resource() - Release a resource from TISCI resource. + * @res: Pointer to the TISCI resource + */ +void ti_sci_release_resource(struct ti_sci_resource *res, u16 id) +{ + u16 set; + + for (set = 0; set < res->sets; set++) { + if (res->desc[set].start <= id && + (res->desc[set].num + res->desc[set].start) > id) + clear_bit(id - res->desc[set].start, + res->desc[set].res_map); + } +} + +/** + * devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device + * @handle: TISCI handle + * @dev: Device pointer to which the resource is assigned + * @of_prop: property name by which the resource are represented + * + * Note: This function expects of_prop to be in the form of tuples + * <type, subtype>. Allocates and initializes ti_sci_resource structure + * for each of_prop. Client driver can directly call + * ti_sci_(get_free, release)_resource apis for handling the resource. + * + * Return: Pointer to ti_sci_resource if all went well else appropriate + * error pointer. + */ +struct ti_sci_resource * +devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, + struct udevice *dev, u32 dev_id, char *of_prop) +{ + u32 resource_subtype; + u16 resource_type; + struct ti_sci_resource *res; + int sets, i, ret; + u32 *temp; + + res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL); + if (!res) + return ERR_PTR(-ENOMEM); + + sets = dev_read_size(dev, of_prop); + if (sets < 0) { + dev_err(dev, "%s resource type ids not available\n", of_prop); + return ERR_PTR(sets); + } + temp = malloc(sets); + sets /= sizeof(u32); + res->sets = sets; + + res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc), + GFP_KERNEL); + if (!res->desc) + return ERR_PTR(-ENOMEM); + + ret = ti_sci_get_resource_type(handle_to_ti_sci_info(handle), dev_id, + &resource_type); + if (ret) { + dev_err(dev, "No valid resource type for %u\n", dev_id); + return ERR_PTR(-EINVAL); + } + + ret = dev_read_u32_array(dev, of_prop, temp, res->sets); + if (ret) + return ERR_PTR(-EINVAL); + + for (i = 0; i < res->sets; i++) { + resource_subtype = temp[i]; + ret = handle->ops.rm_core_ops.get_range(handle, dev_id, + resource_subtype, + &res->desc[i].start, + &res->desc[i].num); + if (ret) { + dev_err(dev, "type %d subtype %d not allocated for host %d\n", + resource_type, resource_subtype, + handle_to_ti_sci_info(handle)->host_id); + return ERR_PTR(ret); + } + + dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n", + resource_type, resource_subtype, res->desc[i].start, + res->desc[i].num); + + res->desc[i].res_map = + devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) * + sizeof(*res->desc[i].res_map), GFP_KERNEL); + if (!res->desc[i].res_map) + return ERR_PTR(-ENOMEM); + } + + return res; +} + +/* Description for K2G */ +static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = { + .default_host_id = 2, + /* Conservative duration */ + .max_rx_timeout_ms = 10000, + /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ + .max_msgs = 20, + .max_msg_size = 64, + .rm_type_map = NULL, +}; + +static struct ti_sci_rm_type_map ti_sci_am654_rm_type_map[] = { + {.dev_id = 56, .type = 0x00b}, /* GIC_IRQ */ + {.dev_id = 179, .type = 0x000}, /* MAIN_NAV_UDMASS_IA0 */ + {.dev_id = 187, .type = 0x009}, /* MAIN_NAV_RA */ + {.dev_id = 188, .type = 0x006}, /* MAIN_NAV_UDMAP */ + {.dev_id = 194, .type = 0x007}, /* MCU_NAV_UDMAP */ + {.dev_id = 195, .type = 0x00a}, /* MCU_NAV_RA */ + {.dev_id = 0, .type = 0x000}, /* end of table */ +}; + /* Description for AM654 */ -static const struct ti_sci_desc ti_sci_sysfw_am654_desc = { - .host_id = 4, - .max_rx_timeout_us = 1000000, +static const struct ti_sci_desc ti_sci_pmmc_am654_desc = { + .default_host_id = 12, + /* Conservative duration */ + .max_rx_timeout_ms = 10000, + /* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */ + .max_msgs = 20, .max_msg_size = 60, + .rm_type_map = ti_sci_am654_rm_type_map, }; static const struct udevice_id ti_sci_ids[] = { { .compatible = "ti,k2g-sci", - .data = (ulong)&ti_sci_sysfw_am654_desc + .data = (ulong)&ti_sci_pmmc_k2g_desc + }, + { + .compatible = "ti,am654-sci", + .data = (ulong)&ti_sci_pmmc_am654_desc }, { /* Sentinel */ }, }; diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 81591fb..2d87cdd 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -25,6 +25,7 @@ #define TI_SCI_MSG_BOARD_CONFIG_RM 0x000c #define TI_SCI_MSG_BOARD_CONFIG_SECURITY 0x000d #define TI_SCI_MSG_BOARD_CONFIG_PM 0x000e +#define TISCI_MSG_QUERY_MSMC 0x0020 /* Device requests */ #define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 @@ -50,6 +51,34 @@ #define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120 #define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 +/* Resource Management Requests */ +#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 + +/* NAVSS resource management */ +/* Ringacc requests */ +#define TI_SCI_MSG_RM_RING_CFG 0x1110 +#define TI_SCI_MSG_RM_RING_GET_CFG 0x1111 + +/* PSI-L requests */ +#define TI_SCI_MSG_RM_PSIL_PAIR 0x1280 +#define TI_SCI_MSG_RM_PSIL_UNPAIR 0x1281 + +#define TI_SCI_MSG_RM_UDMAP_TX_ALLOC 0x1200 +#define TI_SCI_MSG_RM_UDMAP_TX_FREE 0x1201 +#define TI_SCI_MSG_RM_UDMAP_RX_ALLOC 0x1210 +#define TI_SCI_MSG_RM_UDMAP_RX_FREE 0x1211 +#define TI_SCI_MSG_RM_UDMAP_FLOW_CFG 0x1220 +#define TI_SCI_MSG_RM_UDMAP_OPT_FLOW_CFG 0x1221 + +#define TISCI_MSG_RM_UDMAP_TX_CH_CFG 0x1205 +#define TISCI_MSG_RM_UDMAP_TX_CH_GET_CFG 0x1206 +#define TISCI_MSG_RM_UDMAP_RX_CH_CFG 0x1215 +#define TISCI_MSG_RM_UDMAP_RX_CH_GET_CFG 0x1216 +#define TISCI_MSG_RM_UDMAP_FLOW_CFG 0x1230 +#define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_CFG 0x1231 +#define TISCI_MSG_RM_UDMAP_FLOW_GET_CFG 0x1232 +#define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_GET_CFG 0x1233 + /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values @@ -134,6 +163,24 @@ struct ti_sci_msg_board_config { } __packed; /** + * struct ti_sci_msg_resp_query_msmc - Query msmc message response structure + * @hdr: Generic Header + * @msmc_start_low: Lower 32 bit of msmc start + * @msmc_start_high: Upper 32 bit of msmc start + * @msmc_end_low: Lower 32 bit of msmc end + * @msmc_end_high: Upper 32 bit of msmc end + * + * Response to a generic message with message type TISCI_MSG_QUERY_MSMC + */ +struct ti_sci_msg_resp_query_msmc { + struct ti_sci_msg_hdr hdr; + u32 msmc_start_low; + u32 msmc_start_high; + u32 msmc_end_low; + u32 msmc_end_high; +} __packed; + +/** * struct ti_sci_msg_req_set_device_state - Set the desired state of the device * @hdr: Generic header * @id: Indicates which device to modify @@ -505,6 +552,45 @@ struct ti_sci_msg_resp_get_clock_freq { u64 freq_hz; } __packed; +#define TI_SCI_IRQ_SECONDARY_HOST_INVALID 0xff + +/** + * struct ti_sci_msg_req_get_resource_range - Request to get a host's assigned + * range of resources. + * @hdr: Generic Header + * @type: Unique resource assignment type + * @subtype: Resource assignment subtype within the resource type. + * @secondary_host: Host processing entity to which the resources are + * allocated. This is required only when the destination + * host id id different from ti sci interface host id, + * else TI_SCI_IRQ_SECONDARY_HOST_INVALID can be passed. + * + * Request type is TI_SCI_MSG_GET_RESOURCE_RANGE. Responded with requested + * resource range which is of type TI_SCI_MSG_GET_RESOURCE_RANGE. + */ +struct ti_sci_msg_req_get_resource_range { + struct ti_sci_msg_hdr hdr; +#define MSG_RM_RESOURCE_TYPE_MASK GENMASK(9, 0) +#define MSG_RM_RESOURCE_SUBTYPE_MASK GENMASK(5, 0) + u16 type; + u8 subtype; + u8 secondary_host; +} __packed; + +/** + * struct ti_sci_msg_resp_get_resource_range - Response to resource get range. + * @hdr: Generic Header + * @range_start: Start index of the resource range. + * @range_num: Number of resources in the range. + * + * Response to request TI_SCI_MSG_GET_RESOURCE_RANGE. + */ +struct ti_sci_msg_resp_get_resource_range { + struct ti_sci_msg_hdr hdr; + u16 range_start; + u16 range_num; +} __packed; + #define TISCI_ADDR_LOW_MASK GENMASK_ULL(31, 0) #define TISCI_ADDR_HIGH_MASK GENMASK_ULL(63, 32) #define TISCI_ADDR_HIGH_SHIFT 32 @@ -677,4 +763,579 @@ struct ti_sci_msg_resp_get_proc_boot_status { u32 status_flags; } __packed; +/** + * struct ti_sci_msg_rm_ring_cfg_req - Configure a Navigator Subsystem ring + * + * Configures the non-real-time registers of a Navigator Subsystem ring. + * @hdr: Generic Header + * @valid_params: Bitfield defining validity of ring configuration parameters. + * The ring configuration fields are not valid, and will not be used for + * ring configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @tisci_msg_rm_ring_cfg_req addr_lo + * 1 - Valid bit for @tisci_msg_rm_ring_cfg_req addr_hi + * 2 - Valid bit for @tisci_msg_rm_ring_cfg_req count + * 3 - Valid bit for @tisci_msg_rm_ring_cfg_req mode + * 4 - Valid bit for @tisci_msg_rm_ring_cfg_req size + * 5 - Valid bit for @tisci_msg_rm_ring_cfg_req order_id + * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @index: ring index to be configured. + * @addr_lo: 32 LSBs of ring base address to be programmed into the ring's + * RING_BA_LO register + * @addr_hi: 16 MSBs of ring base address to be programmed into the ring's + * RING_BA_HI register. + * @count: Number of ring elements. Must be even if mode is CREDENTIALS or QM + * modes. + * @mode: Specifies the mode the ring is to be configured. + * @size: Specifies encoded ring element size. To calculate the encoded size use + * the formula (log2(size_bytes) - 2), where size_bytes cannot be + * greater than 256. + * @order_id: Specifies the ring's bus order ID. + */ +struct ti_sci_msg_rm_ring_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 index; + u32 addr_lo; + u32 addr_hi; + u32 count; + u8 mode; + u8 size; + u8 order_id; +} __packed; + +/** + * struct ti_sci_msg_rm_ring_cfg_resp - Response to configuring a ring. + * + * @hdr: Generic Header + */ +struct ti_sci_msg_rm_ring_cfg_resp { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msg_rm_ring_get_cfg_req - Get RA ring's configuration + * + * Gets the configuration of the non-real-time register fields of a ring. The + * host, or a supervisor of the host, who owns the ring must be the requesting + * host. The values of the non-real-time registers are returned in + * @ti_sci_msg_rm_ring_get_cfg_resp. + * + * @hdr: Generic Header + * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @index: ring index. + */ +struct ti_sci_msg_rm_ring_get_cfg_req { + struct ti_sci_msg_hdr hdr; + u16 nav_id; + u16 index; +} __packed; + +/** + * struct ti_sci_msg_rm_ring_get_cfg_resp - Ring get configuration response + * + * Response received by host processor after RM has handled + * @ti_sci_msg_rm_ring_get_cfg_req. The response contains the ring's + * non-real-time register values. + * + * @hdr: Generic Header + * @addr_lo: Ring 32 LSBs of base address + * @addr_hi: Ring 16 MSBs of base address. + * @count: Ring number of elements. + * @mode: Ring mode. + * @size: encoded Ring element size + * @order_id: ing order ID. + */ +struct ti_sci_msg_rm_ring_get_cfg_resp { + struct ti_sci_msg_hdr hdr; + u32 addr_lo; + u32 addr_hi; + u32 count; + u8 mode; + u8 size; + u8 order_id; +} __packed; + +/** + * struct ti_sci_msg_psil_pair - Pairs a PSI-L source thread to a destination + * thread + * @hdr: Generic Header + * @nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is + * used to pair the source and destination threads. + * @src_thread: PSI-L source thread ID within the PSI-L System thread map. + * + * UDMAP transmit channels mapped to source threads will have their + * TCHAN_THRD_ID register programmed with the destination thread if the pairing + * is successful. + + * @dst_thread: PSI-L destination thread ID within the PSI-L System thread map. + * PSI-L destination threads start at index 0x8000. The request is NACK'd if + * the destination thread is not greater than or equal to 0x8000. + * + * UDMAP receive channels mapped to destination threads will have their + * RCHAN_THRD_ID register programmed with the source thread if the pairing + * is successful. + * + * Request type is TI_SCI_MSG_RM_PSIL_PAIR, response is a generic ACK or NACK + * message. + */ +struct ti_sci_msg_psil_pair { + struct ti_sci_msg_hdr hdr; + u32 nav_id; + u32 src_thread; + u32 dst_thread; +} __packed; + +/** + * struct ti_sci_msg_psil_unpair - Unpairs a PSI-L source thread from a + * destination thread + * @hdr: Generic Header + * @nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is + * used to unpair the source and destination threads. + * @src_thread: PSI-L source thread ID within the PSI-L System thread map. + * + * UDMAP transmit channels mapped to source threads will have their + * TCHAN_THRD_ID register cleared if the unpairing is successful. + * + * @dst_thread: PSI-L destination thread ID within the PSI-L System thread map. + * PSI-L destination threads start at index 0x8000. The request is NACK'd if + * the destination thread is not greater than or equal to 0x8000. + * + * UDMAP receive channels mapped to destination threads will have their + * RCHAN_THRD_ID register cleared if the unpairing is successful. + * + * Request type is TI_SCI_MSG_RM_PSIL_UNPAIR, response is a generic ACK or NACK + * message. + */ +struct ti_sci_msg_psil_unpair { + struct ti_sci_msg_hdr hdr; + u32 nav_id; + u32 src_thread; + u32 dst_thread; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * transmit channel. The channel index must be assigned to the host defined + * in the TISCI header via the RM board configuration resource assignment + * range list. + * + * @hdr: Generic Header + * + * @valid_params: Bitfield defining validity of tx channel configuration + * parameters. The tx channel configuration fields are not valid, and will not + * be used for ch configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_pause_on_err + * 1 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_atype + * 2 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_chan_type + * 3 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_fetch_size + * 4 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::txcq_qnum + * 5 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_priority + * 6 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_qos + * 7 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_orderid + * 8 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_sched_priority + * 9 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_filt_einfo + * 10 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_filt_pswords + * 11 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_supr_tdpkt + * 12 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_credit_count + * 13 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::fdepth + * + * @nav_id: SoC device ID of Navigator Subsystem where tx channel is located + * + * @index: UDMAP transmit channel index. + * + * @tx_pause_on_err: UDMAP transmit channel pause on error configuration to + * be programmed into the tx_pause_on_err field of the channel's TCHAN_TCFG + * register. + * + * @tx_filt_einfo: UDMAP transmit channel extended packet information passing + * configuration to be programmed into the tx_filt_einfo field of the + * channel's TCHAN_TCFG register. + * + * @tx_filt_pswords: UDMAP transmit channel protocol specific word passing + * configuration to be programmed into the tx_filt_pswords field of the + * channel's TCHAN_TCFG register. + * + * @tx_atype: UDMAP transmit channel non Ring Accelerator access pointer + * interpretation configuration to be programmed into the tx_atype field of + * the channel's TCHAN_TCFG register. + * + * @tx_chan_type: UDMAP transmit channel functional channel type and work + * passing mechanism configuration to be programmed into the tx_chan_type + * field of the channel's TCHAN_TCFG register. + * + * @tx_supr_tdpkt: UDMAP transmit channel teardown packet generation suppression + * configuration to be programmed into the tx_supr_tdpkt field of the channel's + * TCHAN_TCFG register. + * + * @tx_fetch_size: UDMAP transmit channel number of 32-bit descriptor words to + * fetch configuration to be programmed into the tx_fetch_size field of the + * channel's TCHAN_TCFG register. The user must make sure to set the maximum + * word count that can pass through the channel for any allowed descriptor type. + * + * @tx_credit_count: UDMAP transmit channel transfer request credit count + * configuration to be programmed into the count field of the TCHAN_TCREDIT + * register. Specifies how many credits for complete TRs are available. + * + * @txcq_qnum: UDMAP transmit channel completion queue configuration to be + * programmed into the txcq_qnum field of the TCHAN_TCQ register. The specified + * completion queue must be assigned to the host, or a subordinate of the host, + * requesting configuration of the transmit channel. + * + * @tx_priority: UDMAP transmit channel transmit priority value to be programmed + * into the priority field of the channel's TCHAN_TPRI_CTRL register. + * + * @tx_qos: UDMAP transmit channel transmit qos value to be programmed into the + * qos field of the channel's TCHAN_TPRI_CTRL register. + * + * @tx_orderid: UDMAP transmit channel bus order id value to be programmed into + * the orderid field of the channel's TCHAN_TPRI_CTRL register. + * + * @fdepth: UDMAP transmit channel FIFO depth configuration to be programmed + * into the fdepth field of the TCHAN_TFIFO_DEPTH register. Sets the number of + * Tx FIFO bytes which are allowed to be stored for the channel. Check the UDMAP + * section of the TRM for restrictions regarding this parameter. + * + * @tx_sched_priority: UDMAP transmit channel tx scheduling priority + * configuration to be programmed into the priority field of the channel's + * TCHAN_TST_SCHED register. + */ +struct ti_sci_msg_rm_udmap_tx_ch_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 index; + u8 tx_pause_on_err; + u8 tx_filt_einfo; + u8 tx_filt_pswords; + u8 tx_atype; + u8 tx_chan_type; + u8 tx_supr_tdpkt; + u16 tx_fetch_size; + u8 tx_credit_count; + u16 txcq_qnum; + u8 tx_priority; + u8 tx_qos; + u8 tx_orderid; + u16 fdepth; + u8 tx_sched_priority; +} __packed; + +/** + * Response to configuring a UDMAP transmit channel. + * + * @hdr: Standard TISCI header + */ +struct ti_sci_msg_rm_udmap_tx_ch_cfg_resp { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * receive channel. The channel index must be assigned to the host defined + * in the TISCI header via the RM board configuration resource assignment + * range list. + * + * @hdr: Generic Header + * + * @valid_params: Bitfield defining validity of rx channel configuration + * parameters. + * The rx channel configuration fields are not valid, and will not be used for + * ch configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_pause_on_err + * 1 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_atype + * 2 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_chan_type + * 3 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_fetch_size + * 4 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rxcq_qnum + * 5 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_priority + * 6 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_qos + * 7 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_orderid + * 8 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_sched_priority + * 9 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::flowid_start + * 10 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::flowid_cnt + * 11 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_short + * 12 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_long + * + * @nav_id: SoC device ID of Navigator Subsystem where rx channel is located + * + * @index: UDMAP receive channel index. + * + * @rx_fetch_size: UDMAP receive channel number of 32-bit descriptor words to + * fetch configuration to be programmed into the rx_fetch_size field of the + * channel's RCHAN_RCFG register. + * + * @rxcq_qnum: UDMAP receive channel completion queue configuration to be + * programmed into the rxcq_qnum field of the RCHAN_RCQ register. + * The specified completion queue must be assigned to the host, or a subordinate + * of the host, requesting configuration of the receive channel. + * + * @rx_priority: UDMAP receive channel receive priority value to be programmed + * into the priority field of the channel's RCHAN_RPRI_CTRL register. + * + * @rx_qos: UDMAP receive channel receive qos value to be programmed into the + * qos field of the channel's RCHAN_RPRI_CTRL register. + * + * @rx_orderid: UDMAP receive channel bus order id value to be programmed into + * the orderid field of the channel's RCHAN_RPRI_CTRL register. + * + * @rx_sched_priority: UDMAP receive channel rx scheduling priority + * configuration to be programmed into the priority field of the channel's + * RCHAN_RST_SCHED register. + * + * @flowid_start: UDMAP receive channel additional flows starting index + * configuration to program into the flow_start field of the RCHAN_RFLOW_RNG + * register. Specifies the starting index for flow IDs the receive channel is to + * make use of beyond the default flow. flowid_start and @ref flowid_cnt must be + * set as valid and configured together. The starting flow ID set by + * @ref flowid_cnt must be a flow index within the Navigator Subsystem's subset + * of flows beyond the default flows statically mapped to receive channels. + * The additional flows must be assigned to the host, or a subordinate of the + * host, requesting configuration of the receive channel. + * + * @flowid_cnt: UDMAP receive channel additional flows count configuration to + * program into the flowid_cnt field of the RCHAN_RFLOW_RNG register. + * This field specifies how many flow IDs are in the additional contiguous range + * of legal flow IDs for the channel. @ref flowid_start and flowid_cnt must be + * set as valid and configured together. Disabling the valid_params field bit + * for flowid_cnt indicates no flow IDs other than the default are to be + * allocated and used by the receive channel. @ref flowid_start plus flowid_cnt + * cannot be greater than the number of receive flows in the receive channel's + * Navigator Subsystem. The additional flows must be assigned to the host, or a + * subordinate of the host, requesting configuration of the receive channel. + * + * @rx_pause_on_err: UDMAP receive channel pause on error configuration to be + * programmed into the rx_pause_on_err field of the channel's RCHAN_RCFG + * register. + * + * @rx_atype: UDMAP receive channel non Ring Accelerator access pointer + * interpretation configuration to be programmed into the rx_atype field of the + * channel's RCHAN_RCFG register. + * + * @rx_chan_type: UDMAP receive channel functional channel type and work passing + * mechanism configuration to be programmed into the rx_chan_type field of the + * channel's RCHAN_RCFG register. + * + * @rx_ignore_short: UDMAP receive channel short packet treatment configuration + * to be programmed into the rx_ignore_short field of the RCHAN_RCFG register. + * + * @rx_ignore_long: UDMAP receive channel long packet treatment configuration to + * be programmed into the rx_ignore_long field of the RCHAN_RCFG register. + */ +struct ti_sci_msg_rm_udmap_rx_ch_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 index; + u16 rx_fetch_size; + u16 rxcq_qnum; + u8 rx_priority; + u8 rx_qos; + u8 rx_orderid; + u8 rx_sched_priority; + u16 flowid_start; + u16 flowid_cnt; + u8 rx_pause_on_err; + u8 rx_atype; + u8 rx_chan_type; + u8 rx_ignore_short; + u8 rx_ignore_long; +} __packed; + +/** + * Response to configuring a UDMAP receive channel. + * + * @hdr: Standard TISCI header + */ +struct ti_sci_msg_rm_udmap_rx_ch_cfg_resp { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP receive flow + * + * Configures a Navigator Subsystem UDMAP receive flow's registers. + * Configuration does not include the flow registers which handle size-based + * free descriptor queue routing. + * + * The flow index must be assigned to the host defined in the TISCI header via + * the RM board configuration resource assignment range list. + * + * @hdr: Standard TISCI header + * + * @valid_params + * Bitfield defining validity of rx flow configuration parameters. The + * rx flow configuration fields are not valid, and will not be used for flow + * configuration, if their corresponding valid bit is zero. Valid bit usage: + * 0 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_einfo_present + * 1 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_psinfo_present + * 2 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_error_handling + * 3 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_desc_type + * 4 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_sop_offset + * 5 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_qnum + * 6 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi + * 7 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo + * 8 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi + * 9 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo + * 10 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi_sel + * 11 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo_sel + * 12 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi_sel + * 13 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo_sel + * 14 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq0_sz0_qnum + * 15 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq1_sz0_qnum + * 16 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq2_sz0_qnum + * 17 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq3_sz0_qnum + * 18 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_ps_location + * + * @nav_id: SoC device ID of Navigator Subsystem from which the receive flow is + * allocated + * + * @flow_index: UDMAP receive flow index for non-optional configuration. + * + * @rx_einfo_present: + * UDMAP receive flow extended packet info present configuration to be + * programmed into the rx_einfo_present field of the flow's RFLOW_RFA register. + * + * @rx_psinfo_present: + * UDMAP receive flow PS words present configuration to be programmed into the + * rx_psinfo_present field of the flow's RFLOW_RFA register. + * + * @rx_error_handling: + * UDMAP receive flow error handling configuration to be programmed into the + * rx_error_handling field of the flow's RFLOW_RFA register. + * + * @rx_desc_type: + * UDMAP receive flow descriptor type configuration to be programmed into the + * rx_desc_type field field of the flow's RFLOW_RFA register. + * + * @rx_sop_offset: + * UDMAP receive flow start of packet offset configuration to be programmed + * into the rx_sop_offset field of the RFLOW_RFA register. See the UDMAP + * section of the TRM for more information on this setting. Valid values for + * this field are 0-255 bytes. + * + * @rx_dest_qnum: + * UDMAP receive flow destination queue configuration to be programmed into the + * rx_dest_qnum field of the flow's RFLOW_RFA register. The specified + * destination queue must be valid within the Navigator Subsystem and must be + * owned by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_src_tag_hi: + * UDMAP receive flow source tag high byte constant configuration to be + * programmed into the rx_src_tag_hi field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_src_tag_lo: + * UDMAP receive flow source tag low byte constant configuration to be + * programmed into the rx_src_tag_lo field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_hi: + * UDMAP receive flow destination tag high byte constant configuration to be + * programmed into the rx_dest_tag_hi field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_lo: + * UDMAP receive flow destination tag low byte constant configuration to be + * programmed into the rx_dest_tag_lo field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @rx_src_tag_hi_sel: + * UDMAP receive flow source tag high byte selector configuration to be + * programmed into the rx_src_tag_hi_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_src_tag_lo_sel: + * UDMAP receive flow source tag low byte selector configuration to be + * programmed into the rx_src_tag_lo_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_hi_sel: + * UDMAP receive flow destination tag high byte selector configuration to be + * programmed into the rx_dest_tag_hi_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_dest_tag_lo_sel: + * UDMAP receive flow destination tag low byte selector configuration to be + * programmed into the rx_dest_tag_lo_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @rx_fdq0_sz0_qnum: + * UDMAP receive flow free descriptor queue 0 configuration to be programmed + * into the rx_fdq0_sz0_qnum field of the flow's RFLOW_RFD register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_fdq1_qnum: + * UDMAP receive flow free descriptor queue 1 configuration to be programmed + * into the rx_fdq1_qnum field of the flow's RFLOW_RFD register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_fdq2_qnum: + * UDMAP receive flow free descriptor queue 2 configuration to be programmed + * into the rx_fdq2_qnum field of the flow's RFLOW_RFE register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_fdq3_qnum: + * UDMAP receive flow free descriptor queue 3 configuration to be programmed + * into the rx_fdq3_qnum field of the flow's RFLOW_RFE register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @rx_ps_location: + * UDMAP receive flow PS words location configuration to be programmed into the + * rx_ps_location field of the flow's RFLOW_RFA register. + */ +struct ti_sci_msg_rm_udmap_flow_cfg_req { + struct ti_sci_msg_hdr hdr; + u32 valid_params; + u16 nav_id; + u16 flow_index; + u8 rx_einfo_present; + u8 rx_psinfo_present; + u8 rx_error_handling; + u8 rx_desc_type; + u16 rx_sop_offset; + u16 rx_dest_qnum; + u8 rx_src_tag_hi; + u8 rx_src_tag_lo; + u8 rx_dest_tag_hi; + u8 rx_dest_tag_lo; + u8 rx_src_tag_hi_sel; + u8 rx_src_tag_lo_sel; + u8 rx_dest_tag_hi_sel; + u8 rx_dest_tag_lo_sel; + u16 rx_fdq0_sz0_qnum; + u16 rx_fdq1_qnum; + u16 rx_fdq2_qnum; + u16 rx_fdq3_qnum; + u8 rx_ps_location; +} __packed; + +/** + * Response to configuring a Navigator Subsystem UDMAP receive flow + * + * @hdr: Standard TISCI header + */ +struct ti_sci_msg_rm_udmap_flow_cfg_resp { + struct ti_sci_msg_hdr hdr; +} __packed; + #endif /* __TI_SCI_H */ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b103180..b3e4ecc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -23,7 +23,7 @@ config ALTERA_PIO config BCM6345_GPIO bool "BCM6345 GPIO driver" - depends on DM_GPIO && ARCH_BMIPS + depends on DM_GPIO && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158) help This driver supports the GPIO banks on BCM6345 SoCs. diff --git a/drivers/gpio/bcm6345_gpio.c b/drivers/gpio/bcm6345_gpio.c index d1f6cfa..71a978c 100644 --- a/drivers/gpio/bcm6345_gpio.c +++ b/drivers/gpio/bcm6345_gpio.c @@ -22,7 +22,7 @@ static int bcm6345_gpio_get_value(struct udevice *dev, unsigned offset) { struct bcm6345_gpio_priv *priv = dev_get_priv(dev); - return !!(readl_be(priv->reg_data) & BIT(offset)); + return !!(readl(priv->reg_data) & BIT(offset)); } static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset, @@ -31,9 +31,9 @@ static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset, struct bcm6345_gpio_priv *priv = dev_get_priv(dev); if (value) - setbits_be32(priv->reg_data, BIT(offset)); + setbits_32(priv->reg_data, BIT(offset)); else - clrbits_be32(priv->reg_data, BIT(offset)); + clrbits_32(priv->reg_data, BIT(offset)); return 0; } @@ -42,9 +42,9 @@ static int bcm6345_gpio_set_direction(void __iomem *dirout, unsigned offset, bool input) { if (input) - clrbits_be32(dirout, BIT(offset)); + clrbits_32(dirout, BIT(offset)); else - setbits_be32(dirout, BIT(offset)); + setbits_32(dirout, BIT(offset)); return 0; } @@ -70,7 +70,7 @@ static int bcm6345_gpio_get_function(struct udevice *dev, unsigned offset) { struct bcm6345_gpio_priv *priv = dev_get_priv(dev); - if (readl_be(priv->reg_dirout) & BIT(offset)) + if (readl(priv->reg_dirout) & BIT(offset)) return GPIOF_OUTPUT; else return GPIOF_INPUT; diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 49e23a0..e47abf1 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -593,6 +593,29 @@ int i2c_chip_ofdata_to_platdata(struct udevice *dev, struct dm_i2c_chip *chip) } #endif +static int i2c_pre_probe(struct udevice *dev) +{ +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + struct dm_i2c_bus *i2c = dev_get_uclass_priv(dev); + unsigned int max = 0; + ofnode node; + int ret; + + i2c->max_transaction_bytes = 0; + dev_for_each_subnode(node, dev) { + ret = ofnode_read_u32(node, + "u-boot,i2c-transaction-bytes", + &max); + if (!ret && max > i2c->max_transaction_bytes) + i2c->max_transaction_bytes = max; + } + + debug("%s: I2C bus: %s max transaction bytes: %d\n", __func__, + dev->name, i2c->max_transaction_bytes); +#endif + return 0; +} + static int i2c_post_probe(struct udevice *dev) { #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) @@ -674,6 +697,7 @@ UCLASS_DRIVER(i2c) = { .post_bind = i2c_post_bind, .init = i2c_uclass_init, .priv_auto_alloc_size = sizeof(struct i2c_priv), + .pre_probe = i2c_pre_probe, .post_probe = i2c_post_probe, .per_device_auto_alloc_size = sizeof(struct dm_i2c_bus), .per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip), diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index b0da67c..68f1526 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -29,11 +29,12 @@ config I2C_MUX_PCA954x tristate "TI PCA954x I2C Mux/switches" depends on I2C_MUX help - If you say yes here you get support for the TI PCA954x - I2C mux/switch devices. It is x width I2C multiplexer which enables to - partitioning I2C bus and connect multiple devices with the same address - to the same I2C controller where driver handles proper routing to - target i2c device. PCA9544 and PCA9548 are supported. + If you say yes here you get support for the TI PCA954x I2C mux/switch + devices. It is x width I2C multiplexer which enables to partitioning + I2C bus and connect multiple devices with the same address to the same + I2C controller where driver handles proper routing to target i2c + device. Supported chips are PCA9543, PCA9544, PCA9547, PCA9548 and + PCA9646. config I2C_MUX_GPIO tristate "GPIO-based I2C multiplexer" diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c index bd4e9ab..a630ce9 100644 --- a/drivers/i2c/muxes/pca954x.c +++ b/drivers/i2c/muxes/pca954x.c @@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR; enum pca_type { + PCA9543, PCA9544, PCA9547, PCA9548, @@ -22,7 +23,7 @@ enum pca_type { }; struct chip_desc { - u8 enable; + u8 enable; /* Enable mask in ctl register (used for muxes only) */ enum muxtype { pca954x_ismux = 0, pca954x_isswi, @@ -37,6 +38,10 @@ struct pca954x_priv { }; static const struct chip_desc chips[] = { + [PCA9543] = { + .muxtype = pca954x_isswi, + .width = 2, + }, [PCA9544] = { .enable = 0x4, .muxtype = pca954x_ismux, @@ -48,12 +53,10 @@ static const struct chip_desc chips[] = { .width = 8, }, [PCA9548] = { - .enable = 0x8, .muxtype = pca954x_isswi, .width = 8, }, [PCA9646] = { - .enable = 0x0, .muxtype = pca954x_isswi, .width = 4, }, @@ -89,6 +92,7 @@ static const struct i2c_mux_ops pca954x_ops = { }; static const struct udevice_id pca954x_ids[] = { + { .compatible = "nxp,pca9543", .data = PCA9543 }, { .compatible = "nxp,pca9544", .data = PCA9544 }, { .compatible = "nxp,pca9547", .data = PCA9547 }, { .compatible = "nxp,pca9548", .data = PCA9548 }, diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 9999d9f..5420afb 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -354,9 +354,10 @@ int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus) int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus) { struct udevice *bus = i2c_bus->bus; + struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus); struct gpio_desc *scl_gpio = &i2c_bus->scl_gpio; struct gpio_desc *sda_gpio = &i2c_bus->sda_gpio; - int sda, scl; + int sda, scl, idle_sclks; int i, ret = 0; ulong elapsed, start_time; @@ -380,8 +381,22 @@ int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus) if ((sda & scl) == 1) goto exit; /* Bus is idle already */ + /* + * In most cases it is just enough to generate 8 + 1 SCLK + * clocks to recover I2C slave device from 'stuck' state + * (when for example SW reset was performed, in the middle of + * I2C transmission). + * + * However, there are devices which send data in packets of + * N bytes (N > 1). In such case we do need N * 8 + 1 SCLK + * clocks. + */ + idle_sclks = 8 + 1; + + if (i2c->max_transaction_bytes > 0) + idle_sclks = i2c->max_transaction_bytes * 8 + 1; /* Send high and low on the SCL line */ - for (i = 0; i < 9; i++) { + for (i = 0; i < idle_sclks; i++) { dm_gpio_set_dir_flags(scl_gpio, GPIOD_IS_OUT); dm_gpio_set_value(scl_gpio, 0); udelay(50); diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c index 29ad87c..f25d054 100644 --- a/drivers/misc/i2c_eeprom.c +++ b/drivers/misc/i2c_eeprom.c @@ -5,6 +5,7 @@ #include <common.h> #include <linux/err.h> +#include <linux/kernel.h> #include <dm.h> #include <i2c.h> #include <i2c_eeprom.h> @@ -38,7 +39,24 @@ static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf, static int i2c_eeprom_std_write(struct udevice *dev, int offset, const uint8_t *buf, int size) { - return -ENODEV; + struct i2c_eeprom *priv = dev_get_priv(dev); + int ret; + + while (size > 0) { + int write_size = min_t(int, size, priv->pagesize); + + ret = dm_i2c_write(dev, offset, buf, write_size); + if (ret) + return ret; + + offset += write_size; + buf += write_size; + size -= write_size; + + udelay(10000); + } + + return 0; } static const struct i2c_eeprom_ops i2c_eeprom_std_ops = { @@ -50,6 +68,12 @@ static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev) { struct i2c_eeprom *priv = dev_get_priv(dev); u64 data = dev_get_driver_data(dev); + u32 pagesize; + + if (dev_read_u32(dev, "pagesize", &pagesize) == 0) { + priv->pagesize = pagesize; + return 0; + } /* 6 bit -> page size of up to 2^63 (should be sufficient) */ priv->pagewidth = data & 0x3F; diff --git a/drivers/misc/stm32mp_fuse.c b/drivers/misc/stm32mp_fuse.c index 33943a2..8dc246b 100644 --- a/drivers/misc/stm32mp_fuse.c +++ b/drivers/misc/stm32mp_fuse.c @@ -9,8 +9,10 @@ #include <errno.h> #include <dm/device.h> #include <dm/uclass.h> +#include <power/stpmic1.h> #define STM32MP_OTP_BANK 0 +#define STM32MP_NVM_BANK 1 /* * The 'fuse' command API @@ -34,6 +36,13 @@ int fuse_read(u32 bank, u32 word, u32 *val) ret = 0; break; +#ifdef CONFIG_PMIC_STPMIC1 + case STM32MP_NVM_BANK: + *val = 0; + ret = stpmic1_shadow_read_byte(word, (u8 *)val); + break; +#endif /* CONFIG_PMIC_STPMIC1 */ + default: printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); ret = -EINVAL; @@ -62,6 +71,12 @@ int fuse_prog(u32 bank, u32 word, u32 val) ret = 0; break; +#ifdef CONFIG_PMIC_STPMIC1 + case STM32MP_NVM_BANK: + ret = stpmic1_nvm_write_byte(word, (u8 *)&val); + break; +#endif /* CONFIG_PMIC_STPMIC1 */ + default: printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); ret = -EINVAL; @@ -89,6 +104,13 @@ int fuse_sense(u32 bank, u32 word, u32 *val) ret = 0; break; +#ifdef CONFIG_PMIC_STPMIC1 + case STM32MP_NVM_BANK: + *val = 0; + ret = stpmic1_nvm_read_byte(word, (u8 *)val); + break; +#endif /* CONFIG_PMIC_STPMIC1 */ + default: printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); ret = -EINVAL; @@ -117,6 +139,12 @@ int fuse_override(u32 bank, u32 word, u32 val) ret = 0; break; +#ifdef CONFIG_PMIC_STPMIC1 + case STM32MP_NVM_BANK: + ret = stpmic1_shadow_write_byte(word, (u8 *)&val); + break; +#endif /* CONFIG_PMIC_STPMIC1 */ + default: printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 826a39f..133cdc1 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -264,7 +264,7 @@ static unsigned char mmc_board_init(struct mmc *mmc) !CONFIG_IS_ENABLED(DM_REGULATOR) /* PBIAS config needed for MMC1 only */ if (mmc_get_blk_desc(mmc)->devnum == 0) - vmmc_pbias_config(LDO_VOLT_3V0); + vmmc_pbias_config(LDO_VOLT_3V3); #endif return 0; @@ -418,7 +418,7 @@ static void omap_hsmmc_conf_bus_power(struct mmc *mmc, uint signal_voltage) switch (signal_voltage) { case MMC_SIGNAL_VOLTAGE_330: - hctl |= SDVS_3V0; + hctl |= SDVS_3V3; break; case MMC_SIGNAL_VOLTAGE_180: hctl |= SDVS_1V8; @@ -514,10 +514,9 @@ static int omap_hsmmc_set_signal_voltage(struct mmc *mmc) return -EINVAL; if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { - /* Use 3.0V rather than 3.3V */ - mv = 3000; - capa_mask = VS30_3V0SUP; - palmas_ldo_volt = LDO_VOLT_3V0; + mv = 3300; + capa_mask = VS33_3V3SUP; + palmas_ldo_volt = LDO_VOLT_3V3; } else if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) { capa_mask = VS18_1V8SUP; palmas_ldo_volt = LDO_VOLT_1V8; @@ -556,13 +555,13 @@ static uint32_t omap_hsmmc_set_capabilities(struct mmc *mmc) val = readl(&mmc_base->capa); if (priv->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { - val |= (VS30_3V0SUP | VS18_1V8SUP); + val |= (VS33_3V3SUP | VS18_1V8SUP); } else if (priv->controller_flags & OMAP_HSMMC_NO_1_8_V) { - val |= VS30_3V0SUP; + val |= VS33_3V3SUP; val &= ~VS18_1V8SUP; } else { val |= VS18_1V8SUP; - val &= ~VS30_3V0SUP; + val &= ~VS33_3V3SUP; } writel(val, &mmc_base->capa); @@ -842,11 +841,11 @@ static int omap_hsmmc_init_setup(struct mmc *mmc) #if CONFIG_IS_ENABLED(DM_MMC) reg_val = omap_hsmmc_set_capabilities(mmc); - omap_hsmmc_conf_bus_power(mmc, (reg_val & VS30_3V0SUP) ? + omap_hsmmc_conf_bus_power(mmc, (reg_val & VS33_3V3SUP) ? MMC_SIGNAL_VOLTAGE_330 : MMC_SIGNAL_VOLTAGE_180); #else writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); - writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP, + writel(readl(&mmc_base->capa) | VS33_3V3SUP | VS18_1V8SUP, &mmc_base->capa); #endif diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 7f76e5e..dc087ab 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -256,6 +256,17 @@ config NAND_ZYNQ_USE_BOOTLOADER1_TIMINGS This flag prevent U-boot reconfigure NAND flash controller and reuse the NAND timing from 1st stage bootloader. +config NAND_STM32_FMC2 + bool "Support for NAND controller on STM32MP SoCs" + depends on ARCH_STM32MP + select SYS_NAND_SELF_INIT + imply CMD_NAND + help + Enables support for NAND Flash chips on SoCs containing the FMC2 + NAND controller. This controller is found on STM32MP SoCs. + The controller supports a maximum 8k page size and supports + a maximum 8-bit correction error per sector of 512 bytes. + comment "Generic NAND options" config SYS_NAND_BLOCK_SIZE diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index c61e3f3..b10e718 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o obj-$(CONFIG_NAND_PLAT) += nand_plat.o obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o +obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o else # minimal SPL drivers diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c new file mode 100644 index 0000000..2bb749d --- /dev/null +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -0,0 +1,1092 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) STMicroelectronics 2019 + * Author: Christophe Kerello <christophe.kerello@st.com> + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <nand.h> +#include <reset.h> +#include <linux/iopoll.h> +#include <linux/ioport.h> + +/* Bad block marker length */ +#define FMC2_BBM_LEN 2 + +/* ECC step size */ +#define FMC2_ECC_STEP_SIZE 512 + +/* Command delay */ +#define FMC2_RB_DELAY_US 30 + +/* Max chip enable */ +#define FMC2_MAX_CE 2 + +/* Timings */ +#define FMC2_THIZ 1 +#define FMC2_TIO 8000 +#define FMC2_TSYNC 3000 +#define FMC2_PCR_TIMING_MASK 0xf +#define FMC2_PMEM_PATT_TIMING_MASK 0xff + +/* FMC2 Controller Registers */ +#define FMC2_BCR1 0x0 +#define FMC2_PCR 0x80 +#define FMC2_SR 0x84 +#define FMC2_PMEM 0x88 +#define FMC2_PATT 0x8c +#define FMC2_HECCR 0x94 +#define FMC2_BCHISR 0x254 +#define FMC2_BCHICR 0x258 +#define FMC2_BCHPBR1 0x260 +#define FMC2_BCHPBR2 0x264 +#define FMC2_BCHPBR3 0x268 +#define FMC2_BCHPBR4 0x26c +#define FMC2_BCHDSR0 0x27c +#define FMC2_BCHDSR1 0x280 +#define FMC2_BCHDSR2 0x284 +#define FMC2_BCHDSR3 0x288 +#define FMC2_BCHDSR4 0x28c + +/* Register: FMC2_BCR1 */ +#define FMC2_BCR1_FMC2EN BIT(31) + +/* Register: FMC2_PCR */ +#define FMC2_PCR_PWAITEN BIT(1) +#define FMC2_PCR_PBKEN BIT(2) +#define FMC2_PCR_PWID_MASK GENMASK(5, 4) +#define FMC2_PCR_PWID(x) (((x) & 0x3) << 4) +#define FMC2_PCR_PWID_BUSWIDTH_8 0 +#define FMC2_PCR_PWID_BUSWIDTH_16 1 +#define FMC2_PCR_ECCEN BIT(6) +#define FMC2_PCR_ECCALG BIT(8) +#define FMC2_PCR_TCLR_MASK GENMASK(12, 9) +#define FMC2_PCR_TCLR(x) (((x) & 0xf) << 9) +#define FMC2_PCR_TCLR_DEFAULT 0xf +#define FMC2_PCR_TAR_MASK GENMASK(16, 13) +#define FMC2_PCR_TAR(x) (((x) & 0xf) << 13) +#define FMC2_PCR_TAR_DEFAULT 0xf +#define FMC2_PCR_ECCSS_MASK GENMASK(19, 17) +#define FMC2_PCR_ECCSS(x) (((x) & 0x7) << 17) +#define FMC2_PCR_ECCSS_512 1 +#define FMC2_PCR_ECCSS_2048 3 +#define FMC2_PCR_BCHECC BIT(24) +#define FMC2_PCR_WEN BIT(25) + +/* Register: FMC2_SR */ +#define FMC2_SR_NWRF BIT(6) + +/* Register: FMC2_PMEM */ +#define FMC2_PMEM_MEMSET(x) (((x) & 0xff) << 0) +#define FMC2_PMEM_MEMWAIT(x) (((x) & 0xff) << 8) +#define FMC2_PMEM_MEMHOLD(x) (((x) & 0xff) << 16) +#define FMC2_PMEM_MEMHIZ(x) (((x) & 0xff) << 24) +#define FMC2_PMEM_DEFAULT 0x0a0a0a0a + +/* Register: FMC2_PATT */ +#define FMC2_PATT_ATTSET(x) (((x) & 0xff) << 0) +#define FMC2_PATT_ATTWAIT(x) (((x) & 0xff) << 8) +#define FMC2_PATT_ATTHOLD(x) (((x) & 0xff) << 16) +#define FMC2_PATT_ATTHIZ(x) (((x) & 0xff) << 24) +#define FMC2_PATT_DEFAULT 0x0a0a0a0a + +/* Register: FMC2_BCHISR */ +#define FMC2_BCHISR_DERF BIT(1) +#define FMC2_BCHISR_EPBRF BIT(4) + +/* Register: FMC2_BCHICR */ +#define FMC2_BCHICR_CLEAR_IRQ GENMASK(4, 0) + +/* Register: FMC2_BCHDSR0 */ +#define FMC2_BCHDSR0_DUE BIT(0) +#define FMC2_BCHDSR0_DEF BIT(1) +#define FMC2_BCHDSR0_DEN_MASK GENMASK(7, 4) +#define FMC2_BCHDSR0_DEN_SHIFT 4 + +/* Register: FMC2_BCHDSR1 */ +#define FMC2_BCHDSR1_EBP1_MASK GENMASK(12, 0) +#define FMC2_BCHDSR1_EBP2_MASK GENMASK(28, 16) +#define FMC2_BCHDSR1_EBP2_SHIFT 16 + +/* Register: FMC2_BCHDSR2 */ +#define FMC2_BCHDSR2_EBP3_MASK GENMASK(12, 0) +#define FMC2_BCHDSR2_EBP4_MASK GENMASK(28, 16) +#define FMC2_BCHDSR2_EBP4_SHIFT 16 + +/* Register: FMC2_BCHDSR3 */ +#define FMC2_BCHDSR3_EBP5_MASK GENMASK(12, 0) +#define FMC2_BCHDSR3_EBP6_MASK GENMASK(28, 16) +#define FMC2_BCHDSR3_EBP6_SHIFT 16 + +/* Register: FMC2_BCHDSR4 */ +#define FMC2_BCHDSR4_EBP7_MASK GENMASK(12, 0) +#define FMC2_BCHDSR4_EBP8_MASK GENMASK(28, 16) +#define FMC2_BCHDSR4_EBP8_SHIFT 16 + +#define FMC2_NSEC_PER_SEC 1000000000L + +enum stm32_fmc2_ecc { + FMC2_ECC_HAM = 1, + FMC2_ECC_BCH4 = 4, + FMC2_ECC_BCH8 = 8 +}; + +struct stm32_fmc2_timings { + u8 tclr; + u8 tar; + u8 thiz; + u8 twait; + u8 thold_mem; + u8 tset_mem; + u8 thold_att; + u8 tset_att; +}; + +struct stm32_fmc2_nand { + struct nand_chip chip; + struct stm32_fmc2_timings timings; + int ncs; + int cs_used[FMC2_MAX_CE]; +}; + +static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip) +{ + return container_of(chip, struct stm32_fmc2_nand, chip); +} + +struct stm32_fmc2_nfc { + struct nand_hw_control base; + struct stm32_fmc2_nand nand; + struct nand_ecclayout ecclayout; + void __iomem *io_base; + void __iomem *data_base[FMC2_MAX_CE]; + void __iomem *cmd_base[FMC2_MAX_CE]; + void __iomem *addr_base[FMC2_MAX_CE]; + struct clk clk; + + u8 cs_assigned; + int cs_sel; +}; + +static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base) +{ + return container_of(base, struct stm32_fmc2_nfc, base); +} + +/* Timings configuration */ +static void stm32_fmc2_timings_init(struct nand_chip *chip) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); + struct stm32_fmc2_timings *timings = &nand->timings; + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + u32 pmem, patt; + + /* Set tclr/tar timings */ + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(timings->tclr); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(timings->tar); + + /* Set tset/twait/thold/thiz timings in common bank */ + pmem = FMC2_PMEM_MEMSET(timings->tset_mem); + pmem |= FMC2_PMEM_MEMWAIT(timings->twait); + pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem); + pmem |= FMC2_PMEM_MEMHIZ(timings->thiz); + + /* Set tset/twait/thold/thiz timings in attribut bank */ + patt = FMC2_PATT_ATTSET(timings->tset_att); + patt |= FMC2_PATT_ATTWAIT(timings->twait); + patt |= FMC2_PATT_ATTHOLD(timings->thold_att); + patt |= FMC2_PATT_ATTHIZ(timings->thiz); + + writel(pcr, fmc2->io_base + FMC2_PCR); + writel(pmem, fmc2->io_base + FMC2_PMEM); + writel(patt, fmc2->io_base + FMC2_PATT); +} + +/* Controller configuration */ +static void stm32_fmc2_setup(struct nand_chip *chip) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + + /* Configure ECC algorithm (default configuration is Hamming) */ + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + if (chip->ecc.strength == FMC2_ECC_BCH8) { + pcr |= FMC2_PCR_ECCALG; + pcr |= FMC2_PCR_BCHECC; + } else if (chip->ecc.strength == FMC2_ECC_BCH4) { + pcr |= FMC2_PCR_ECCALG; + } + + /* Set buswidth */ + pcr &= ~FMC2_PCR_PWID_MASK; + if (chip->options & NAND_BUSWIDTH_16) + pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); + + /* Set ECC sector size */ + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); + + writel(pcr, fmc2->io_base + FMC2_PCR); +} + +/* Select target */ +static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); + + if (chipnr < 0 || chipnr >= nand->ncs) + return; + + if (nand->cs_used[chipnr] == fmc2->cs_sel) + return; + + fmc2->cs_sel = nand->cs_used[chipnr]; + chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel]; + chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel]; + + /* FMC2 setup routine */ + stm32_fmc2_setup(chip); + + /* Apply timings */ + stm32_fmc2_timings_init(chip); +} + +/* Set bus width to 16-bit or 8-bit */ +static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set) +{ + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + + pcr &= ~FMC2_PCR_PWID_MASK; + if (set) + pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16); + writel(pcr, fmc2->io_base + FMC2_PCR); +} + +/* Enable/disable ECC */ +static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable) +{ + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + + pcr &= ~FMC2_PCR_ECCEN; + if (enable) + pcr |= FMC2_PCR_ECCEN; + writel(pcr, fmc2->io_base + FMC2_PCR); +} + +/* Clear irq sources in case of bch is used */ +static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2) +{ + writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR); +} + +/* Send command and address cycles */ +static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) { + writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]); + return; + } + + writeb(cmd, fmc2->addr_base[fmc2->cs_sel]); +} + +/* + * Enable ECC logic and reset syndrome/parity bits previously calculated + * Syndrome/parity bits is cleared by setting the ECCEN bit to 0 + */ +static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + + stm32_fmc2_set_ecc(fmc2, false); + + if (chip->ecc.strength != FMC2_ECC_HAM) { + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + + if (mode == NAND_ECC_WRITE) + pcr |= FMC2_PCR_WEN; + else + pcr &= ~FMC2_PCR_WEN; + writel(pcr, fmc2->io_base + FMC2_PCR); + + stm32_fmc2_clear_bch_irq(fmc2); + } + + stm32_fmc2_set_ecc(fmc2, true); +} + +/* + * ECC Hamming calculation + * ECC is 3 bytes for 512 bytes of data (supports error correction up to + * max of 1-bit) + */ +static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data, + u8 *ecc) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 heccr, sr; + int ret; + + ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr, + sr & FMC2_SR_NWRF, 10000); + if (ret < 0) { + pr_err("Ham timeout\n"); + return ret; + } + + heccr = readl(fmc2->io_base + FMC2_HECCR); + + ecc[0] = heccr; + ecc[1] = heccr >> 8; + ecc[2] = heccr >> 16; + + /* Disable ecc */ + stm32_fmc2_set_ecc(fmc2, false); + + return 0; +} + +static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat, + u8 *read_ecc, u8 *calc_ecc) +{ + u8 bit_position = 0, b0, b1, b2; + u32 byte_addr = 0, b; + u32 i, shifting = 1; + + /* Indicate which bit and byte is faulty (if any) */ + b0 = read_ecc[0] ^ calc_ecc[0]; + b1 = read_ecc[1] ^ calc_ecc[1]; + b2 = read_ecc[2] ^ calc_ecc[2]; + b = b0 | (b1 << 8) | (b2 << 16); + + /* No errors */ + if (likely(!b)) + return 0; + + /* Calculate bit position */ + for (i = 0; i < 3; i++) { + switch (b % 4) { + case 2: + bit_position += shifting; + case 1: + break; + default: + return -EBADMSG; + } + shifting <<= 1; + b >>= 2; + } + + /* Calculate byte position */ + shifting = 1; + for (i = 0; i < 9; i++) { + switch (b % 4) { + case 2: + byte_addr += shifting; + case 1: + break; + default: + return -EBADMSG; + } + shifting <<= 1; + b >>= 2; + } + + /* Flip the bit */ + dat[byte_addr] ^= (1 << bit_position); + + return 1; +} + +/* + * ECC BCH calculation and correction + * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to + * max of 4-bit/8-bit) + */ + +static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data, + u8 *ecc) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 bchpbr, bchisr; + int ret; + + /* Wait until the BCH code is ready */ + ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr, + bchisr & FMC2_BCHISR_EPBRF, 10000); + if (ret < 0) { + pr_err("Bch timeout\n"); + return ret; + } + + /* Read parity bits */ + bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1); + ecc[0] = bchpbr; + ecc[1] = bchpbr >> 8; + ecc[2] = bchpbr >> 16; + ecc[3] = bchpbr >> 24; + + bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2); + ecc[4] = bchpbr; + ecc[5] = bchpbr >> 8; + ecc[6] = bchpbr >> 16; + + if (chip->ecc.strength == FMC2_ECC_BCH8) { + ecc[7] = bchpbr >> 24; + + bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3); + ecc[8] = bchpbr; + ecc[9] = bchpbr >> 8; + ecc[10] = bchpbr >> 16; + ecc[11] = bchpbr >> 24; + + bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4); + ecc[12] = bchpbr; + } + + /* Disable ecc */ + stm32_fmc2_set_ecc(fmc2, false); + + return 0; +} + +/* BCH algorithm correction */ +static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat, + u8 *read_ecc, u8 *calc_ecc) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr; + u16 pos[8]; + int i, ret, den, eccsize = chip->ecc.size; + unsigned int nb_errs = 0; + + /* Wait until the decoding error is ready */ + ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr, + bchisr & FMC2_BCHISR_DERF, 10000); + if (ret < 0) { + pr_err("Bch timeout\n"); + return ret; + } + + bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0); + bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1); + bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2); + bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3); + bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4); + + /* Disable ECC */ + stm32_fmc2_set_ecc(fmc2, false); + + /* No errors found */ + if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF))) + return 0; + + /* Too many errors detected */ + if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE)) + return -EBADMSG; + + pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; + pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; + pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; + pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; + pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; + pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; + pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; + pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; + + den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; + for (i = 0; i < den; i++) { + if (pos[i] < eccsize * 8) { + __change_bit(pos[i], (unsigned long *)dat); + nb_errs++; + } + } + + return nb_errs; +} + +static int stm32_fmc2_read_page(struct mtd_info *mtd, + struct nand_chip *chip, u8 *buf, + int oob_required, int page) +{ + int i, s, stat, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + int eccstrength = chip->ecc.strength; + u8 *p = buf; + u8 *ecc_calc = chip->buffers->ecccalc; + u8 *ecc_code = chip->buffers->ecccode; + unsigned int max_bitflips = 0; + + for (i = mtd->writesize + FMC2_BBM_LEN, s = 0; s < eccsteps; + s++, i += eccbytes, p += eccsize) { + chip->ecc.hwctl(mtd, NAND_ECC_READ); + + /* Read the nand page sector (512 bytes) */ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, s * eccsize, -1); + chip->read_buf(mtd, p, eccsize); + + /* Read the corresponding ECC bytes */ + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, i, -1); + chip->read_buf(mtd, ecc_code, eccbytes); + + /* Correct the data */ + stat = chip->ecc.correct(mtd, p, ecc_code, ecc_calc); + if (stat == -EBADMSG) + /* Check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, eccsize, + ecc_code, eccbytes, + NULL, 0, + eccstrength); + + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } + } + + /* Read oob */ + if (oob_required) { + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + } + + return max_bitflips; +} + +/* Controller initialization */ +static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2) +{ + u32 pcr = readl(fmc2->io_base + FMC2_PCR); + u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1); + + /* Set CS used to undefined */ + fmc2->cs_sel = -1; + + /* Enable wait feature and nand flash memory bank */ + pcr |= FMC2_PCR_PWAITEN; + pcr |= FMC2_PCR_PBKEN; + + /* Set buswidth to 8 bits mode for identification */ + pcr &= ~FMC2_PCR_PWID_MASK; + + /* ECC logic is disabled */ + pcr &= ~FMC2_PCR_ECCEN; + + /* Default mode */ + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + pcr &= ~FMC2_PCR_WEN; + + /* Set default ECC sector size */ + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); + + /* Set default tclr/tar timings */ + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); + + /* Enable FMC2 controller */ + bcr1 |= FMC2_BCR1_FMC2EN; + + writel(bcr1, fmc2->io_base + FMC2_BCR1); + writel(pcr, fmc2->io_base + FMC2_PCR); + writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM); + writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT); +} + +/* Controller timings */ +static void stm32_fmc2_calc_timings(struct nand_chip *chip, + const struct nand_sdr_timings *sdrt) +{ + struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller); + struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); + struct stm32_fmc2_timings *tims = &nand->timings; + unsigned long hclk = clk_get_rate(&fmc2->clk); + unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000); + int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att; + + tar = hclkp; + if (tar < sdrt->tAR_min) + tar = sdrt->tAR_min; + tims->tar = DIV_ROUND_UP(tar, hclkp) - 1; + if (tims->tar > FMC2_PCR_TIMING_MASK) + tims->tar = FMC2_PCR_TIMING_MASK; + + tclr = hclkp; + if (tclr < sdrt->tCLR_min) + tclr = sdrt->tCLR_min; + tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1; + if (tims->tclr > FMC2_PCR_TIMING_MASK) + tims->tclr = FMC2_PCR_TIMING_MASK; + + tims->thiz = FMC2_THIZ; + thiz = (tims->thiz + 1) * hclkp; + + /* + * tWAIT > tRP + * tWAIT > tWP + * tWAIT > tREA + tIO + */ + twait = hclkp; + if (twait < sdrt->tRP_min) + twait = sdrt->tRP_min; + if (twait < sdrt->tWP_min) + twait = sdrt->tWP_min; + if (twait < sdrt->tREA_max + FMC2_TIO) + twait = sdrt->tREA_max + FMC2_TIO; + tims->twait = DIV_ROUND_UP(twait, hclkp); + if (tims->twait == 0) + tims->twait = 1; + else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK) + tims->twait = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tSETUP_MEM > tCS - tWAIT + * tSETUP_MEM > tALS - tWAIT + * tSETUP_MEM > tDS - (tWAIT - tHIZ) + */ + tset_mem = hclkp; + if (sdrt->tCS_min > twait && (tset_mem < sdrt->tCS_min - twait)) + tset_mem = sdrt->tCS_min - twait; + if (sdrt->tALS_min > twait && (tset_mem < sdrt->tALS_min - twait)) + tset_mem = sdrt->tALS_min - twait; + if (twait > thiz && (sdrt->tDS_min > twait - thiz) && + (tset_mem < sdrt->tDS_min - (twait - thiz))) + tset_mem = sdrt->tDS_min - (twait - thiz); + tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp); + if (tims->tset_mem == 0) + tims->tset_mem = 1; + else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK) + tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tHOLD_MEM > tCH + * tHOLD_MEM > tREH - tSETUP_MEM + * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) + */ + thold_mem = hclkp; + if (thold_mem < sdrt->tCH_min) + thold_mem = sdrt->tCH_min; + if (sdrt->tREH_min > tset_mem && + (thold_mem < sdrt->tREH_min - tset_mem)) + thold_mem = sdrt->tREH_min - tset_mem; + if ((sdrt->tRC_min > tset_mem + twait) && + (thold_mem < sdrt->tRC_min - (tset_mem + twait))) + thold_mem = sdrt->tRC_min - (tset_mem + twait); + if ((sdrt->tWC_min > tset_mem + twait) && + (thold_mem < sdrt->tWC_min - (tset_mem + twait))) + thold_mem = sdrt->tWC_min - (tset_mem + twait); + tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp); + if (tims->thold_mem == 0) + tims->thold_mem = 1; + else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK) + tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tSETUP_ATT > tCS - tWAIT + * tSETUP_ATT > tCLS - tWAIT + * tSETUP_ATT > tALS - tWAIT + * tSETUP_ATT > tRHW - tHOLD_MEM + * tSETUP_ATT > tDS - (tWAIT - tHIZ) + */ + tset_att = hclkp; + if (sdrt->tCS_min > twait && (tset_att < sdrt->tCS_min - twait)) + tset_att = sdrt->tCS_min - twait; + if (sdrt->tCLS_min > twait && (tset_att < sdrt->tCLS_min - twait)) + tset_att = sdrt->tCLS_min - twait; + if (sdrt->tALS_min > twait && (tset_att < sdrt->tALS_min - twait)) + tset_att = sdrt->tALS_min - twait; + if (sdrt->tRHW_min > thold_mem && + (tset_att < sdrt->tRHW_min - thold_mem)) + tset_att = sdrt->tRHW_min - thold_mem; + if (twait > thiz && (sdrt->tDS_min > twait - thiz) && + (tset_att < sdrt->tDS_min - (twait - thiz))) + tset_att = sdrt->tDS_min - (twait - thiz); + tims->tset_att = DIV_ROUND_UP(tset_att, hclkp); + if (tims->tset_att == 0) + tims->tset_att = 1; + else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK) + tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK; + + /* + * tHOLD_ATT > tALH + * tHOLD_ATT > tCH + * tHOLD_ATT > tCLH + * tHOLD_ATT > tCOH + * tHOLD_ATT > tDH + * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM + * tHOLD_ATT > tADL - tSETUP_MEM + * tHOLD_ATT > tWH - tSETUP_MEM + * tHOLD_ATT > tWHR - tSETUP_MEM + * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) + * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) + */ + thold_att = hclkp; + if (thold_att < sdrt->tALH_min) + thold_att = sdrt->tALH_min; + if (thold_att < sdrt->tCH_min) + thold_att = sdrt->tCH_min; + if (thold_att < sdrt->tCLH_min) + thold_att = sdrt->tCLH_min; + if (thold_att < sdrt->tCOH_min) + thold_att = sdrt->tCOH_min; + if (thold_att < sdrt->tDH_min) + thold_att = sdrt->tDH_min; + if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) && + (thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem)) + thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem; + if (sdrt->tADL_min > tset_mem && + (thold_att < sdrt->tADL_min - tset_mem)) + thold_att = sdrt->tADL_min - tset_mem; + if (sdrt->tWH_min > tset_mem && + (thold_att < sdrt->tWH_min - tset_mem)) + thold_att = sdrt->tWH_min - tset_mem; + if (sdrt->tWHR_min > tset_mem && + (thold_att < sdrt->tWHR_min - tset_mem)) + thold_att = sdrt->tWHR_min - tset_mem; + if ((sdrt->tRC_min > tset_att + twait) && + (thold_att < sdrt->tRC_min - (tset_att + twait))) + thold_att = sdrt->tRC_min - (tset_att + twait); + if ((sdrt->tWC_min > tset_att + twait) && + (thold_att < sdrt->tWC_min - (tset_att + twait))) + thold_att = sdrt->tWC_min - (tset_att + twait); + tims->thold_att = DIV_ROUND_UP(thold_att, hclkp); + if (tims->thold_att == 0) + tims->thold_att = 1; + else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK) + tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK; +} + +static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr, + const struct nand_data_interface *conf) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + const struct nand_sdr_timings *sdrt; + + sdrt = nand_get_sdr_timings(conf); + if (IS_ERR(sdrt)) + return PTR_ERR(sdrt); + + if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) + return 0; + + stm32_fmc2_calc_timings(chip, sdrt); + + /* Apply timings */ + stm32_fmc2_timings_init(chip); + + return 0; +} + +/* NAND callbacks setup */ +static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip) +{ + chip->ecc.hwctl = stm32_fmc2_hwctl; + + /* + * Specific callbacks to read/write a page depending on + * the algo used (Hamming, BCH). + */ + if (chip->ecc.strength == FMC2_ECC_HAM) { + /* Hamming is used */ + chip->ecc.calculate = stm32_fmc2_ham_calculate; + chip->ecc.correct = stm32_fmc2_ham_correct; + chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3; + chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK; + return; + } + + /* BCH is used */ + chip->ecc.read_page = stm32_fmc2_read_page; + chip->ecc.calculate = stm32_fmc2_bch_calculate; + chip->ecc.correct = stm32_fmc2_bch_correct; + + if (chip->ecc.strength == FMC2_ECC_BCH8) + chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13; + else + chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7; +} + +/* FMC2 caps */ +static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength) +{ + /* Hamming */ + if (strength == FMC2_ECC_HAM) + return 4; + + /* BCH8 */ + if (strength == FMC2_ECC_BCH8) + return 14; + + /* BCH4 */ + return 8; +} + +NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes, + FMC2_ECC_STEP_SIZE, + FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8); + +/* FMC2 probe */ +static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2, + ofnode node) +{ + struct stm32_fmc2_nand *nand = &fmc2->nand; + u32 cs[FMC2_MAX_CE]; + int ret, i; + + if (!ofnode_get_property(node, "reg", &nand->ncs)) + return -EINVAL; + + nand->ncs /= sizeof(u32); + if (!nand->ncs) { + pr_err("Invalid reg property size\n"); + return -EINVAL; + } + + ret = ofnode_read_u32_array(node, "reg", cs, nand->ncs); + if (ret < 0) { + pr_err("Could not retrieve reg property\n"); + return -EINVAL; + } + + for (i = 0; i < nand->ncs; i++) { + if (cs[i] > FMC2_MAX_CE) { + pr_err("Invalid reg value: %d\n", + nand->cs_used[i]); + return -EINVAL; + } + + if (fmc2->cs_assigned & BIT(cs[i])) { + pr_err("Cs already assigned: %d\n", + nand->cs_used[i]); + return -EINVAL; + } + + fmc2->cs_assigned |= BIT(cs[i]); + nand->cs_used[i] = cs[i]; + } + + nand->chip.flash_node = ofnode_to_offset(node); + + return 0; +} + +static int stm32_fmc2_parse_dt(struct udevice *dev, + struct stm32_fmc2_nfc *fmc2) +{ + ofnode child; + int ret, nchips = 0; + + dev_for_each_subnode(child, dev) + nchips++; + + if (!nchips) { + pr_err("NAND chip not defined\n"); + return -EINVAL; + } + + if (nchips > 1) { + pr_err("Too many NAND chips defined\n"); + return -EINVAL; + } + + dev_for_each_subnode(child, dev) { + ret = stm32_fmc2_parse_child(fmc2, child); + if (ret) + return ret; + } + + return 0; +} + +static int stm32_fmc2_probe(struct udevice *dev) +{ + struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev); + struct stm32_fmc2_nand *nand = &fmc2->nand; + struct nand_chip *chip = &nand->chip; + struct mtd_info *mtd = &chip->mtd; + struct nand_ecclayout *ecclayout; + struct resource resource; + struct reset_ctl reset; + int oob_index, chip_cs, mem_region, ret, i; + + spin_lock_init(&fmc2->controller.lock); + init_waitqueue_head(&fmc2->controller.wq); + + ret = stm32_fmc2_parse_dt(dev, fmc2); + if (ret) + return ret; + + /* Get resources */ + ret = dev_read_resource(dev, 0, &resource); + if (ret) { + pr_err("Resource io_base not found"); + return ret; + } + fmc2->io_base = (void __iomem *)resource.start; + + for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE; + chip_cs++, mem_region += 3) { + if (!(fmc2->cs_assigned & BIT(chip_cs))) + continue; + + ret = dev_read_resource(dev, mem_region, &resource); + if (ret) { + pr_err("Resource data_base not found for cs%d", + chip_cs); + return ret; + } + fmc2->data_base[chip_cs] = (void __iomem *)resource.start; + + ret = dev_read_resource(dev, mem_region + 1, &resource); + if (ret) { + pr_err("Resource cmd_base not found for cs%d", + chip_cs); + return ret; + } + fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start; + + ret = dev_read_resource(dev, mem_region + 2, &resource); + if (ret) { + pr_err("Resource addr_base not found for cs%d", + chip_cs); + return ret; + } + fmc2->addr_base[chip_cs] = (void __iomem *)resource.start; + } + + /* Enable the clock */ + ret = clk_get_by_index(dev, 0, &fmc2->clk); + if (ret) + return ret; + + ret = clk_enable(&fmc2->clk); + if (ret) + return ret; + + /* Reset */ + ret = reset_get_by_index(dev, 0, &reset); + if (!ret) { + reset_assert(&reset); + udelay(2); + reset_deassert(&reset); + } + + /* FMC2 init routine */ + stm32_fmc2_init(fmc2); + + chip->controller = &fmc2->base; + chip->select_chip = stm32_fmc2_select_chip; + chip->setup_data_interface = stm32_fmc2_setup_interface; + chip->cmd_ctrl = stm32_fmc2_cmd_ctrl; + chip->chip_delay = FMC2_RB_DELAY_US; + chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | + NAND_USE_BOUNCE_BUFFER; + + /* Default ECC settings */ + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = FMC2_ECC_STEP_SIZE; + chip->ecc.strength = FMC2_ECC_BCH8; + + /* Scan to find existence of the device */ + ret = nand_scan_ident(mtd, nand->ncs, NULL); + if (ret) + return ret; + + /* + * Only NAND_ECC_HW mode is actually supported + * Hamming => ecc.strength = 1 + * BCH4 => ecc.strength = 4 + * BCH8 => ecc.strength = 8 + * ECC sector size = 512 + */ + if (chip->ecc.mode != NAND_ECC_HW) { + pr_err("Nand_ecc_mode is not well defined in the DT\n"); + return -EINVAL; + } + + ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps, + mtd->oobsize - FMC2_BBM_LEN); + if (ret) { + pr_err("No valid ECC settings set\n"); + return ret; + } + + if (chip->bbt_options & NAND_BBT_USE_FLASH) + chip->bbt_options |= NAND_BBT_NO_OOB; + + /* NAND callbacks setup */ + stm32_fmc2_nand_callbacks_setup(chip); + + /* Define ECC layout */ + ecclayout = &fmc2->ecclayout; + ecclayout->eccbytes = chip->ecc.bytes * + (mtd->writesize / chip->ecc.size); + oob_index = FMC2_BBM_LEN; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; + ecclayout->oobfree->offset = oob_index; + ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; + chip->ecc.layout = ecclayout; + + /* Configure bus width to 16-bit */ + if (chip->options & NAND_BUSWIDTH_16) + stm32_fmc2_set_buswidth_16(fmc2, true); + + /* Scan the device to fill MTD data-structures */ + ret = nand_scan_tail(mtd); + if (ret) + return ret; + + return nand_register(0, mtd); +} + +static const struct udevice_id stm32_fmc2_match[] = { + { .compatible = "st,stm32mp15-fmc2" }, + { /* Sentinel */ } +}; + +U_BOOT_DRIVER(stm32_fmc2_nand) = { + .name = "stm32_fmc2_nand", + .id = UCLASS_MTD, + .of_match = stm32_fmc2_match, + .probe = stm32_fmc2_probe, + .priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_GET_DRIVER(stm32_fmc2_nand), + &dev); + if (ret && ret != -ENODEV) + pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n", + ret); +} diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c index 8146c31..7f1dee4 100644 --- a/drivers/net/ag7xxx.c +++ b/drivers/net/ag7xxx.c @@ -3,6 +3,7 @@ * Atheros AR71xx / AR9xxx GMAC driver * * Copyright (C) 2016 Marek Vasut <marex@denx.de> + * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com> */ #include <common.h> @@ -23,6 +24,8 @@ DECLARE_GLOBAL_DATA_PTR; enum ag7xxx_model { AG7XXX_MODEL_AG933X, AG7XXX_MODEL_AG934X, + AG7XXX_MODEL_AG953X, + AG7XXX_MODEL_AG956X }; /* MAC Configuration 1 */ @@ -99,8 +102,29 @@ enum ag7xxx_model { /* Rx Status */ #define AG7XXX_ETH_DMA_RX_STATUS 0x194 +/* Custom register at 0x1805002C */ +#define AG7XXX_ETH_XMII 0x2C +#define AG7XXX_ETH_XMII_TX_INVERT BIT(31) +#define AG7XXX_ETH_XMII_RX_DELAY_LSB 28 +#define AG7XXX_ETH_XMII_RX_DELAY_MASK 0x30000000 +#define AG7XXX_ETH_XMII_RX_DELAY_SET(x) \ + (((x) << AG7XXX_ETH_XMII_RX_DELAY_LSB) & AG7XXX_ETH_XMII_RX_DELAY_MASK) +#define AG7XXX_ETH_XMII_TX_DELAY_LSB 26 +#define AG7XXX_ETH_XMII_TX_DELAY_MASK 0x0c000000 +#define AG7XXX_ETH_XMII_TX_DELAY_SET(x) \ + (((x) << AG7XXX_ETH_XMII_TX_DELAY_LSB) & AG7XXX_ETH_XMII_TX_DELAY_MASK) +#define AG7XXX_ETH_XMII_GIGE BIT(25) + /* Custom register at 0x18070000 */ #define AG7XXX_GMAC_ETH_CFG 0x00 +#define AG7XXX_ETH_CFG_RXDV_DELAY_LSB 16 +#define AG7XXX_ETH_CFG_RXDV_DELAY_MASK 0x00030000 +#define AG7XXX_ETH_CFG_RXDV_DELAY_SET(x) \ + (((x) << AG7XXX_ETH_CFG_RXDV_DELAY_LSB) & AG7XXX_ETH_CFG_RXDV_DELAY_MASK) +#define AG7XXX_ETH_CFG_RXD_DELAY_LSB 14 +#define AG7XXX_ETH_CFG_RXD_DELAY_MASK 0x0000c000 +#define AG7XXX_ETH_CFG_RXD_DELAY_SET(x) \ + (((x) << AG7XXX_ETH_CFG_RXD_DELAY_LSB) & AG7XXX_ETH_CFG_RXD_DELAY_MASK) #define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP BIT(8) #define AG7XXX_ETH_CFG_SW_PHY_SWAP BIT(7) #define AG7XXX_ETH_CFG_SW_ONLY_MODE BIT(6) @@ -197,24 +221,33 @@ static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val) u32 reg_addr; u32 phy_temp; u32 reg_temp; + u32 reg_temp_w = (reg & 0xfffffffc) >> 1; u16 rv = 0; int ret; - if (priv->model == AG7XXX_MODEL_AG933X) { + if (priv->model == AG7XXX_MODEL_AG933X || + priv->model == AG7XXX_MODEL_AG953X) { phy_addr = 0x1f; reg_addr = 0x10; - } else if (priv->model == AG7XXX_MODEL_AG934X) { + } else if (priv->model == AG7XXX_MODEL_AG934X || + priv->model == AG7XXX_MODEL_AG956X) { phy_addr = 0x18; reg_addr = 0x00; } else return -EINVAL; - ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9); + if (priv->model == AG7XXX_MODEL_AG956X) + ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff); + else + ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9); if (ret) return ret; phy_temp = ((reg >> 6) & 0x7) | 0x10; - reg_temp = (reg >> 1) & 0x1e; + if (priv->model == AG7XXX_MODEL_AG956X) + reg_temp = reg_temp_w & 0x1f; + else + reg_temp = (reg >> 1) & 0x1e; *val = 0; ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv); @@ -222,7 +255,13 @@ static int ag7xxx_switch_reg_read(struct mii_dev *bus, int reg, u32 *val) return ret; *val |= rv; - ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv); + if (priv->model == AG7XXX_MODEL_AG956X) { + phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10; + reg_temp = (reg_temp_w + 1) & 0x1f; + ret = ag7xxx_switch_read(bus, phy_temp, reg_temp, &rv); + } else { + ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv); + } if (ret < 0) return ret; *val |= (rv << 16); @@ -237,23 +276,34 @@ static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val) u32 reg_addr; u32 phy_temp; u32 reg_temp; + u32 reg_temp_w = (reg & 0xfffffffc) >> 1; int ret; - if (priv->model == AG7XXX_MODEL_AG933X) { + if (priv->model == AG7XXX_MODEL_AG933X || + priv->model == AG7XXX_MODEL_AG953X) { phy_addr = 0x1f; reg_addr = 0x10; - } else if (priv->model == AG7XXX_MODEL_AG934X) { + } else if (priv->model == AG7XXX_MODEL_AG934X || + priv->model == AG7XXX_MODEL_AG956X) { phy_addr = 0x18; reg_addr = 0x00; } else return -EINVAL; - ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9); + if (priv->model == AG7XXX_MODEL_AG956X) + ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff); + else + ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9); if (ret) return ret; - phy_temp = ((reg >> 6) & 0x7) | 0x10; - reg_temp = (reg >> 1) & 0x1e; + if (priv->model == AG7XXX_MODEL_AG956X) { + reg_temp = (reg_temp_w + 1) & 0x1f; + phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10; + } else { + phy_temp = ((reg >> 6) & 0x7) | 0x10; + reg_temp = (reg >> 1) & 0x1e; + } /* * The switch on AR933x has some special register behavior, which @@ -272,10 +322,18 @@ static int ag7xxx_switch_reg_write(struct mii_dev *bus, int reg, u32 val) if (ret < 0) return ret; } else { - ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16); + if (priv->model == AG7XXX_MODEL_AG956X) + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp, val >> 16); + else + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16); if (ret < 0) return ret; + if (priv->model == AG7XXX_MODEL_AG956X) { + phy_temp = ((reg_temp_w >> 5) & 0x7) | 0x10; + reg_temp = reg_temp_w & 0x1f; + } + ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff); if (ret < 0) return ret; @@ -598,10 +656,19 @@ static int ag7xxx_mii_setup(struct udevice *dev) return 0; } - if (priv->model == AG7XXX_MODEL_AG934X) { - writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | 0x4, + if (priv->model == AG7XXX_MODEL_AG934X) + reg = 0x4; + else if (priv->model == AG7XXX_MODEL_AG953X) + reg = 0x2; + else if (priv->model == AG7XXX_MODEL_AG956X) + reg = 0x7; + + if (priv->model == AG7XXX_MODEL_AG934X || + priv->model == AG7XXX_MODEL_AG953X || + priv->model == AG7XXX_MODEL_AG956X) { + writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); - writel(0x4, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); + writel(reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG); return 0; } @@ -698,14 +765,126 @@ static int ag933x_phy_setup_lan(struct udevice *dev) return 0; } +static int ag953x_phy_setup_wan(struct udevice *dev) +{ + int ret; + u32 reg = 0; + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + + /* Set wan port connect to GE0 */ + ret = ag7xxx_switch_reg_read(priv->bus, 0x8, ®); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x8, reg | BIT(28)); + if (ret) + return ret; + + /* Configure switch port 4 (GMAC0) */ + ret = ag7xxx_switch_write(priv->bus, 4, MII_BMCR, 0x9000); + if (ret) + return ret; + + return 0; +} + +static int ag953x_phy_setup_lan(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int i, ret; + u32 reg = 0; + + /* Reset the switch */ + ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0, reg | BIT(31)); + if (ret) + return ret; + + do { + ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); + if (ret) + return ret; + } while (reg & BIT(31)); + + ret = ag7xxx_switch_reg_write(priv->bus, 0x100, 0x4e); + if (ret) + return ret; + + /* Set GMII mode */ + ret = ag7xxx_switch_reg_read(priv->bus, 0x4, ®); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x4, reg | BIT(6)); + if (ret) + return ret; + + /* Configure switch ports 0...4 (GMAC1) */ + for (i = 0; i < 5; i++) { + ret = ag7xxx_switch_write(priv->bus, i, MII_BMCR, 0x9000); + if (ret) + return ret; + } + + for (i = 0; i < 5; i++) { + ret = ag7xxx_switch_reg_write(priv->bus, (i + 2) * 0x100, BIT(9)); + if (ret) + return ret; + } + + /* QM Control */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e); + if (ret) + return ret; + + /* Disable Atheros header */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004); + if (ret) + return ret; + + /* Tag priority mapping */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50); + if (ret) + return ret; + + /* Enable ARP packets to the CPU */ + ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, ®); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg | 0x100000); + if (ret) + return ret; + + /* Enable broadcast packets to the CPU */ + ret = ag7xxx_switch_reg_read(priv->bus, 0x2c, ®); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x2c, reg | BIT(25) | BIT(26)); + if (ret) + return ret; + + return 0; +} + static int ag933x_phy_setup_reset_set(struct udevice *dev, int port) { struct ar7xxx_eth_priv *priv = dev_get_priv(dev); int ret; - ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | - ADVERTISE_PAUSE_ASYM); + if (priv->model == AG7XXX_MODEL_AG953X || + priv->model == AG7XXX_MODEL_AG956X) { + ret = ag7xxx_switch_write(priv->bus, port, MII_ADVERTISE, + ADVERTISE_ALL); + } else { + ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE, + ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + } if (ret) return ret; @@ -714,8 +893,18 @@ static int ag933x_phy_setup_reset_set(struct udevice *dev, int port) ADVERTISE_1000FULL); if (ret) return ret; + } else if (priv->model == AG7XXX_MODEL_AG956X) { + ret = ag7xxx_switch_write(priv->bus, port, MII_CTRL1000, + ADVERTISE_1000FULL); + if (ret) + return ret; } + if (priv->model == AG7XXX_MODEL_AG953X || + priv->model == AG7XXX_MODEL_AG956X) + return ag7xxx_switch_write(priv->bus, port, MII_BMCR, + BMCR_ANENABLE | BMCR_RESET); + return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR, BMCR_ANENABLE | BMCR_RESET); } @@ -724,13 +913,24 @@ static int ag933x_phy_setup_reset_fin(struct udevice *dev, int port) { struct ar7xxx_eth_priv *priv = dev_get_priv(dev); int ret; + u16 reg; - do { - ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR); - if (ret < 0) - return ret; - mdelay(10); - } while (ret & BMCR_RESET); + if (priv->model == AG7XXX_MODEL_AG953X || + priv->model == AG7XXX_MODEL_AG956X) { + do { + ret = ag7xxx_switch_read(priv->bus, port, MII_BMCR, ®); + if (ret < 0) + return ret; + mdelay(10); + } while (reg & BMCR_RESET); + } else { + do { + ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR); + if (ret < 0) + return ret; + mdelay(10); + } while (ret & BMCR_RESET); + } return 0; } @@ -739,10 +939,13 @@ static int ag933x_phy_setup_common(struct udevice *dev) { struct ar7xxx_eth_priv *priv = dev_get_priv(dev); int i, ret, phymax; + u16 reg; if (priv->model == AG7XXX_MODEL_AG933X) phymax = 4; - else if (priv->model == AG7XXX_MODEL_AG934X) + else if (priv->model == AG7XXX_MODEL_AG934X || + priv->model == AG7XXX_MODEL_AG953X || + priv->model == AG7XXX_MODEL_AG956X) phymax = 5; else return -EINVAL; @@ -757,7 +960,10 @@ static int ag933x_phy_setup_common(struct udevice *dev) return ret; /* Read out link status */ - ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR); + if (priv->model == AG7XXX_MODEL_AG953X) + ret = ag7xxx_switch_read(priv->bus, phymax, MII_MIPSCR, ®); + else + ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR); if (ret < 0) return ret; @@ -779,7 +985,11 @@ static int ag933x_phy_setup_common(struct udevice *dev) for (i = 0; i < phymax; i++) { /* Read out link status */ - ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR); + if (priv->model == AG7XXX_MODEL_AG953X || + priv->model == AG7XXX_MODEL_AG956X) + ret = ag7xxx_switch_read(priv->bus, i, MII_MIPSCR, ®); + else + ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR); if (ret < 0) return ret; } @@ -841,6 +1051,63 @@ static int ag934x_phy_setup(struct udevice *dev) return 0; } +static int ag956x_phy_setup(struct udevice *dev) +{ + struct ar7xxx_eth_priv *priv = dev_get_priv(dev); + int i, ret; + u32 reg, ctrl; + + ret = ag7xxx_switch_reg_read(priv->bus, 0x0, ®); + if (ret) + return ret; + if ((reg & 0xffff) >= 0x1301) + ctrl = 0xc74164de; + else + ctrl = 0xc74164d0; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x4, BIT(7)); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0xe0, ctrl); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f); + if (ret) + return ret; + + /* + * Values suggested by the switch team when s17 in sgmii + * configuration. 0x10(S17_PWS_REG) = 0x602613a0 + */ + ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x602613a0); + if (ret) + return ret; + + ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e); + if (ret) + return ret; + + /* AR8337/AR8334 v1.0 fixup */ + ret = ag7xxx_switch_reg_read(priv->bus, 0, ®); + if (ret) + return ret; + if ((reg & 0xffff) == 0x1301) { + for (i = 0; i < 5; i++) { + /* Turn on Gigabit clock */ + ret = ag7xxx_switch_write(priv->bus, i, 0x1d, 0x3d); + if (ret) + return ret; + ret = ag7xxx_switch_write(priv->bus, i, 0x1e, 0x6820); + if (ret) + return ret; + } + } + + return 0; +} + static int ag7xxx_mac_probe(struct udevice *dev) { struct ar7xxx_eth_priv *priv = dev_get_priv(dev); @@ -858,8 +1125,15 @@ static int ag7xxx_mac_probe(struct udevice *dev) ret = ag933x_phy_setup_wan(dev); else ret = ag933x_phy_setup_lan(dev); + } else if (priv->model == AG7XXX_MODEL_AG953X) { + if (priv->interface == PHY_INTERFACE_MODE_RMII) + ret = ag953x_phy_setup_wan(dev); + else + ret = ag953x_phy_setup_lan(dev); } else if (priv->model == AG7XXX_MODEL_AG934X) { ret = ag934x_phy_setup(dev); + } else if (priv->model == AG7XXX_MODEL_AG956X) { + ret = ag956x_phy_setup(dev); } else { return -EINVAL; } @@ -997,6 +1271,8 @@ static int ag7xxx_eth_ofdata_to_platdata(struct udevice *dev) static const struct udevice_id ag7xxx_eth_ids[] = { { .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X }, { .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X }, + { .compatible = "qca,ag953x-mac", .data = AG7XXX_MODEL_AG953X }, + { .compatible = "qca,ag956x-mac", .data = AG7XXX_MODEL_AG956X }, { } }; diff --git a/drivers/net/mscc_eswitch/Kconfig b/drivers/net/mscc_eswitch/Kconfig index 88e5a97..6359d0b 100644 --- a/drivers/net/mscc_eswitch/Kconfig +++ b/drivers/net/mscc_eswitch/Kconfig @@ -15,3 +15,17 @@ config MSCC_LUTON_SWITCH select PHYLIB help This driver supports the Luton network switch device. + +config MSCC_JR2_SWITCH + bool "Jaguar2 switch driver" + depends on DM_ETH && ARCH_MSCC + select PHYLIB + help + This driver supports the Jaguar2 network switch device. + +config MSCC_SERVALT_SWITCH + bool "Servalt switch driver" + depends on DM_ETH && ARCH_MSCC + select PHYLIB + help + This driver supports the Servalt network switch device. diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile index 751a839..bffd8ec 100644 --- a/drivers/net/mscc_eswitch/Makefile +++ b/drivers/net/mscc_eswitch/Makefile @@ -1,3 +1,5 @@ obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o +obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o +obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c new file mode 100644 index 0000000..60d408f --- /dev/null +++ b/drivers/net/mscc_eswitch/jr2_switch.c @@ -0,0 +1,1075 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2018 Microsemi Corporation + */ + +#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/of_access.h> +#include <dm/of_addr.h> +#include <fdt_support.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <miiphy.h> +#include <net.h> +#include <wait_bit.h> + +#include <dt-bindings/mscc/jr2_data.h> +#include "mscc_xfer.h" + +#define GCB_MIIM_MII_STATUS 0x0 +#define GCB_MIIM_STAT_BUSY BIT(3) +#define GCB_MIIM_MII_CMD 0x8 +#define GCB_MIIM_MII_CMD_SCAN BIT(0) +#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1) +#define GCB_MIIM_MII_CMD_OPR_READ BIT(2) +#define GCB_MIIM_MII_CMD_SINGLE_SCAN BIT(3) +#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4) +#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20) +#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25) +#define GCB_MIIM_MII_CMD_VLD BIT(31) +#define GCB_MIIM_DATA 0xC +#define GCB_MIIM_DATA_ERROR (0x3 << 16) + +#define ANA_AC_RAM_CTRL_RAM_INIT 0x94358 +#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x94370 + +#define ANA_CL_PORT_VLAN_CFG(x) (0x24018 + 0xc8 * (x)) +#define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19) +#define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17) + +#define ANA_L2_COMMON_FWD_CFG 0x8a2a8 +#define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6) + +#define ASM_CFG_STAT_CFG 0x3508 +#define ASM_CFG_PORT(x) (0x36c4 + 0x4 * (x)) +#define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8) +#define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1) +#define ASM_RAM_CTRL_RAM_INIT 0x39b8 + +#define DEV_DEV_CFG_DEV_RST_CTRL 0x0 +#define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20) +#define DEV_MAC_CFG_MAC_ENA 0x1c +#define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4) +#define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0) +#define DEV_MAC_CFG_MAC_IFG 0x34 +#define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x) +#define DEV_PCS1G_CFG_PCS1G_CFG 0x40 +#define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0) +#define DEV_PCS1G_CFG_PCS1G_MODE 0x44 +#define DEV_PCS1G_CFG_PCS1G_SD 0x48 +#define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c +#define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16) + +#define DSM_RAM_CTRL_RAM_INIT 0x8 + +#define HSIO_ANA_SERDES1G_DES_CFG 0xac +#define HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x) ((x) << 1) +#define HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x) ((x) << 5) +#define HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_IB_CFG 0xb0 +#define HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x) ((x) << 6) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP BIT(9) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV BIT(11) +#define HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM BIT(13) +#define HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x) ((x) << 19) +#define HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x) ((x) << 24) +#define HSIO_ANA_SERDES1G_OB_CFG 0xb4 +#define HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x) ((x) << 4) +#define HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES1G_OB_CFG_SLP(x) ((x) << 17) +#define HSIO_ANA_SERDES1G_SER_CFG 0xb8 +#define HSIO_ANA_SERDES1G_COMMON_CFG 0xbc +#define HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE BIT(0) +#define HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE BIT(18) +#define HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST BIT(31) +#define HSIO_ANA_SERDES1G_PLL_CFG 0xc0 +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA BIT(7) +#define HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8) +#define HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2 BIT(21) +#define HSIO_DIG_SERDES1G_DFT_CFG0 0xc8 +#define HSIO_DIG_SERDES1G_TP_CFG 0xd4 +#define HSIO_DIG_SERDES1G_MISC_CFG 0xdc +#define HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES1G_CFG 0xe8 +#define HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES1G_CFG_ADDR(x) (x) + +#define HSIO_ANA_SERDES6G_DES_CFG 0x11c +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA BIT(0) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x) ((x) << 1) +#define HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST BIT(4) +#define HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG 0x120 +#define HSIO_ANA_SERDES6G_IB_CFG_REG_ENA BIT(0) +#define HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA BIT(1) +#define HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA BIT(2) +#define HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG_CONCUR BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x) ((x) << 7) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x) ((x) << 9) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x) ((x) << 13) +#define HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x) ((x) << 15) +#define HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x) ((x) << 20) +#define HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x) ((x) << 24) +#define HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL BIT(28) +#define HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x) ((x) << 29) +#define HSIO_ANA_SERDES6G_IB_CFG1 0x124 +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET BIT(4) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP BIT(5) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID BIT(6) +#define HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP BIT(7) +#define HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x) ((x) << 8) +#define HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x) ((x) << 17) +#define HSIO_ANA_SERDES6G_IB_CFG2 0x128 +#define HSIO_ANA_SERDES6G_IB_CFG2_UREG(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x) ((x) << 3) +#define HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x) ((x) << 5) +#define HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x) ((x) << 10) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x) ((x) << 16) +#define HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x) ((x) << 22) +#define HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x) ((x) << 27) +#define HSIO_ANA_SERDES6G_IB_CFG3 0x12c +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG4 0x130 +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_IB_CFG5 0x134 +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x) (x) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x) ((x) << 12) +#define HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG 0x138 +#define HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG_SR(x) ((x) << 4) +#define HSIO_ANA_SERDES6G_OB_CFG_SR_H BIT(8) +#define HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL BIT(9) +#define HSIO_ANA_SERDES6G_OB_CFG_R_COR BIT(10) +#define HSIO_ANA_SERDES6G_OB_CFG_POST1(x) ((x) << 11) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR BIT(16) +#define HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX BIT(17) +#define HSIO_ANA_SERDES6G_OB_CFG_PREC(x) ((x) << 18) +#define HSIO_ANA_SERDES6G_OB_CFG_POST0(x) ((x) << 23) +#define HSIO_ANA_SERDES6G_OB_CFG_POL BIT(29) +#define HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x) ((x) << 30) +#define HSIO_ANA_SERDES6G_OB_CFG_IDLE BIT(31) +#define HSIO_ANA_SERDES6G_OB_CFG1 0x13c +#define HSIO_ANA_SERDES6G_OB_CFG1_LEV(x) (x) +#define HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_SER_CFG 0x140 +#define HSIO_ANA_SERDES6G_COMMON_CFG 0x144 +#define HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x) (x) +#define HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x) (x << 2) +#define HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE BIT(14) +#define HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST BIT(16) +#define HSIO_ANA_SERDES6G_PLL_CFG 0x148 +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ BIT(0) +#define HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR BIT(1) +#define HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL BIT(2) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA BIT(3) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA BIT(4) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA BIT(5) +#define HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 6) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT BIT(14) +#define HSIO_ANA_SERDES6G_PLL_CFG_DIV4 BIT(15) +#define HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x) ((x) << 16) +#define HSIO_DIG_SERDES6G_MISC_CFG 0x108 +#define HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST BIT(0) +#define HSIO_MCB_SERDES6G_CFG 0x168 +#define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31) +#define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x) +#define HSIO_HW_CFGSTAT_HW_CFG 0x16c + +#define LRN_COMMON_ACCESS_CTRL 0x0 +#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0) +#define LRN_COMMON_MAC_ACCESS_CFG0 0x4 +#define LRN_COMMON_MAC_ACCESS_CFG1 0x8 +#define LRN_COMMON_MAC_ACCESS_CFG2 0xc +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24) + +#define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4 * (x)) +#define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17) + +#define QS_XTR_GRP_CFG(x) (0x0 + 4 * (x)) +#define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4) + +#define QSYS_SYSTEM_RESET_CFG 0xf0 +#define QSYS_CALCFG_CAL_AUTO(x) (0x3d4 + 4 * (x)) +#define QSYS_CALCFG_CAL_CTRL 0x3e8 +#define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11) +#define QSYS_RAM_CTRL_RAM_INIT 0x3ec + +#define REW_RAM_CTRL_RAM_INIT 0x53528 + +#define VOP_RAM_CTRL_RAM_INIT 0x43638 + +#define XTR_VALID_BYTES(x) (4 - ((x) & 3)) +#define MAC_VID 0 +#define CPU_PORT 53 +#define IFH_LEN 7 +#define JR2_BUF_CELL_SZ 60 +#define ETH_ALEN 6 +#define PGID_BROADCAST 510 +#define PGID_UNICAST 511 + +static const char * const regs_names[] = { + "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7", + "port8", "port9", "port10", "port11", "port12", "port13", "port14", + "port15", "port16", "port17", "port18", "port19", "port20", "port21", + "port22", "port23", "port24", "port25", "port26", "port27", "port28", + "port29", "port30", "port31", "port32", "port33", "port34", "port35", + "port36", "port37", "port38", "port39", "port40", "port41", "port42", + "port43", "port44", "port45", "port46", "port47", + "ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn", + "qfwd", "qs", "qsys", "rew", +}; + +#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1 +#define MAX_PORT 48 + +enum jr2_ctrl_regs { + ANA_AC = MAX_PORT, + ANA_CL, + ANA_L2, + ASM, + HSIO, + LRN, + QFWD, + QS, + QSYS, + REW, +}; + +#define JR2_MIIM_BUS_COUNT 3 + +struct jr2_phy_port_t { + size_t phy_addr; + struct mii_dev *bus; + u8 serdes_index; + u8 phy_mode; +}; + +struct jr2_private { + void __iomem *regs[REGS_NAMES_COUNT]; + struct mii_dev *bus[JR2_MIIM_BUS_COUNT]; + struct jr2_phy_port_t ports[MAX_PORT]; +}; + +struct jr2_miim_dev { + void __iomem *regs; + phys_addr_t miim_base; + unsigned long miim_size; + struct mii_dev *bus; +}; + +static const unsigned long jr2_regs_qs[] = { + [MSCC_QS_XTR_RD] = 0x8, + [MSCC_QS_XTR_FLUSH] = 0x18, + [MSCC_QS_XTR_DATA_PRESENT] = 0x1c, + [MSCC_QS_INJ_WR] = 0x2c, + [MSCC_QS_INJ_CTRL] = 0x34, +}; + +static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT]; +static int miim_count = -1; + +static int mscc_miim_wait_ready(struct jr2_miim_dev *miim) +{ + unsigned long deadline; + u32 val; + + deadline = timer_get_us() + 250000; + + do { + val = readl(miim->regs + GCB_MIIM_MII_STATUS); + } while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY)); + + if (val & GCB_MIIM_STAT_BUSY) + return -ETIMEDOUT; + + return 0; +} + +static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv; + u32 val; + int ret; + + ret = mscc_miim_wait_ready(miim); + if (ret) + goto out; + + writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) | + GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ, + miim->regs + GCB_MIIM_MII_CMD); + + ret = mscc_miim_wait_ready(miim); + if (ret) + goto out; + + val = readl(miim->regs + GCB_MIIM_DATA); + if (val & GCB_MIIM_DATA_ERROR) { + ret = -EIO; + goto out; + } + + ret = val & 0xFFFF; + out: + return ret; +} + +static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv; + int ret; + + ret = mscc_miim_wait_ready(miim); + if (ret < 0) + goto out; + + writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) | + GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) | + GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD); + + out: + return ret; +} + +static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base, + unsigned long miim_size) +{ + struct mii_dev *bus; + + bus = mdio_alloc(); + if (!bus) + return NULL; + + ++miim_count; + sprintf(bus->name, "miim-bus%d", miim_count); + + miim[miim_count].regs = ioremap(miim_base, miim_size); + miim[miim_count].miim_base = miim_base; + miim[miim_count].miim_size = miim_size; + bus->priv = &miim[miim_count]; + bus->read = mscc_miim_read; + bus->write = mscc_miim_write; + + if (mdio_register(bus)) + return NULL; + + miim[miim_count].bus = bus; + return bus; +} + +static void jr2_cpu_capture_setup(struct jr2_private *priv) +{ + /* ASM: No preamble and IFH prefix on CPU injected frames */ + writel(ASM_CFG_PORT_NO_PREAMBLE_ENA | + ASM_CFG_PORT_INJ_FORMAT_CFG(1), + priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT)); + + /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */ + writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0)); + + /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */ + writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0)); + + /* Enable CPU port for any frame transfer */ + setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT), + QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA); + + /* Send a copy to CPU when found as forwarding entry */ + setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG, + ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA); +} + +static void jr2_port_init(struct jr2_private *priv, int port) +{ + void __iomem *regs = priv->regs[port]; + + /* Enable PCS */ + writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA, + regs + DEV_PCS1G_CFG_PCS1G_CFG); + + /* Disable Signal Detect */ + writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD); + + /* Enable MAC RX and TX */ + writel(DEV_MAC_CFG_MAC_ENA_RX_ENA | + DEV_MAC_CFG_MAC_ENA_TX_ENA, + regs + DEV_MAC_CFG_MAC_ENA); + + /* Clear sgmii_mode_ena */ + writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE); + + /* + * Clear sw_resolve_ena(bit 0) and set adv_ability to + * something meaningful just in case + */ + writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20), + regs + DEV_PCS1G_CFG_PCS1G_ANEG); + + /* Set MAC IFG Gaps */ + writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) | + DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) | + DEV_MAC_CFG_MAC_IFG_RX_IFG2(1), + regs + DEV_MAC_CFG_MAC_IFG); + + /* Set link speed and release all resets */ + writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2), + regs + DEV_DEV_CFG_DEV_RST_CTRL); + + /* Make VLAN aware for CPU traffic */ + writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA | + ANA_CL_PORT_VLAN_CFG_POP_CNT(1) | + MAC_VID, + priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port)); + + /* Enable CPU port for any frame transfer */ + setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port), + QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA); +} + +static void serdes6g_write(void __iomem *base, u32 addr) +{ + u32 data; + + writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT | + HSIO_MCB_SERDES6G_CFG_ADDR(addr), + base + HSIO_MCB_SERDES6G_CFG); + + do { + data = readl(base + HSIO_MCB_SERDES6G_CFG); + } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT); +} + +static void serdes6g_setup(void __iomem *base, uint32_t addr, + phy_interface_t interface) +{ + u32 ib_if_mode = 0; + u32 ib_qrate = 0; + u32 ib_cal_ena = 0; + u32 ib1_tsdet = 0; + u32 ob_lev = 0; + u32 ob_ena_cas = 0; + u32 ob_ena1v_mode = 0; + u32 des_bw_ana = 0; + u32 pll_fsm_ctrl_data = 0; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + ib_if_mode = 1; + ib_qrate = 1; + ib_cal_ena = 1; + ib1_tsdet = 3; + ob_lev = 48; + ob_ena_cas = 2; + ob_ena1v_mode = 1; + des_bw_ana = 3; + pll_fsm_ctrl_data = 60; + break; + case PHY_INTERFACE_MODE_QSGMII: + ib_if_mode = 3; + ib1_tsdet = 16; + ob_lev = 24; + des_bw_ana = 5; + pll_fsm_ctrl_data = 120; + break; + default: + pr_err("Interface not supported\n"); + return; + } + + if (interface == PHY_INTERFACE_MODE_QSGMII) + writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG); + + writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3), + base + HSIO_ANA_SERDES6G_COMMON_CFG); + writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) | + HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3), + base + HSIO_ANA_SERDES6G_PLL_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP | + HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) | + HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) | + HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8), + base + HSIO_ANA_SERDES6G_IB_CFG1); + writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST, + base + HSIO_DIG_SERDES6G_MISC_CFG); + + serdes6g_write(base, addr); + + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP | + HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) | + HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) | + HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8), + base + HSIO_ANA_SERDES6G_IB_CFG1); + + writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG); + writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) | + HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) | + HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE | + HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST, + base + HSIO_ANA_SERDES6G_COMMON_CFG); + writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST, + base + HSIO_DIG_SERDES6G_MISC_CFG); + + writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) | + HSIO_ANA_SERDES6G_OB_CFG_SR(7) | + HSIO_ANA_SERDES6G_OB_CFG_SR_H | + HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) | + HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG); + writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) | + HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas), + base + HSIO_ANA_SERDES6G_OB_CFG1); + + writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) | + HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) | + HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) | + HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6), + base + HSIO_ANA_SERDES6G_DES_CFG); + writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) | + HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3), + base + HSIO_ANA_SERDES6G_PLL_CFG); + + serdes6g_write(base, addr); + + /* set pll_fsm_ena = 1 */ + writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA | + HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) | + HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3), + base + HSIO_ANA_SERDES6G_PLL_CFG); + + serdes6g_write(base, addr); + + /* wait 20ms for pll bringup */ + mdelay(20); + + /* start IB calibration by setting ib_cal_ena and clearing lane_rst */ + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG); + + serdes6g_write(base, addr); + + /* wait 60 for calibration */ + mdelay(60); + + /* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */ + writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA | + HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA | + HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA | + HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) | + HSIO_ANA_SERDES6G_IB_CFG_CONCUR | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) | + HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) | + HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) | + HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) | + HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) | + HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) | + HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL | + HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1), + base + HSIO_ANA_SERDES6G_IB_CFG); + writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID | + HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP | + HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) | + HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) | + HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8), + base + HSIO_ANA_SERDES6G_IB_CFG1); + + serdes6g_write(base, addr); +} + +static void serdes1g_write(void __iomem *base, u32 addr) +{ + u32 data; + + writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT | + HSIO_MCB_SERDES1G_CFG_ADDR(addr), + base + HSIO_MCB_SERDES1G_CFG); + + do { + data = readl(base + HSIO_MCB_SERDES1G_CFG); + } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT); +} + +static void serdes1g_setup(void __iomem *base, uint32_t addr, + phy_interface_t interface) +{ + writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG); + writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG); + writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0); + writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) | + HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) | + HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) | + HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) | + HSIO_ANA_SERDES1G_OB_CFG_SLP(3), + base + HSIO_ANA_SERDES1G_OB_CFG); + writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) | + HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) | + HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP | + HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV | + HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM | + HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) | + HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1), + base + HSIO_ANA_SERDES1G_IB_CFG); + writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) | + HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) | + HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) | + HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6), + base + HSIO_ANA_SERDES1G_DES_CFG); + writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST, + base + HSIO_DIG_SERDES1G_MISC_CFG); + writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA | + HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) | + HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2, + base + HSIO_ANA_SERDES1G_PLL_CFG); + writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE | + HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE | + HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST, + base + HSIO_ANA_SERDES1G_COMMON_CFG); + + serdes1g_write(base, addr); + + setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG, + HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST); + + serdes1g_write(base, addr); + + clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG, + HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST); + + serdes1g_write(base, addr); +} + +static int ram_init(u32 val, void __iomem *addr) +{ + writel(val, addr); + + if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) { + printf("Timeout in memory reset, reg = 0x%08x\n", val); + return 1; + } + + return 0; +} + +static int jr2_switch_init(struct jr2_private *priv) +{ + /* Initialize memories */ + ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT); + + /* Reset counters */ + writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET); + writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG); + + /* Enable switch-core and queue system */ + writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG); + + return 0; +} + +static void jr2_switch_config(struct jr2_private *priv) +{ + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0)); + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1)); + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2)); + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3)); + + writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) | + QSYS_CALCFG_CAL_CTRL_CAL_MODE(8), + priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL); +} + +static int jr2_initialize(struct jr2_private *priv) +{ + int ret, i; + + /* Initialize switch memories, enable core */ + ret = jr2_switch_init(priv); + if (ret) + return ret; + + jr2_switch_config(priv); + + for (i = 0; i < MAX_PORT; i++) + jr2_port_init(priv, i); + + jr2_cpu_capture_setup(priv); + + return 0; +} + +static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv) +{ + if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL, + LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, + false, 2000, false)) + return -ETIMEDOUT; + + return 0; +} + +static int jr2_mac_table_add(struct jr2_private *priv, + const unsigned char mac[ETH_ALEN], int pgid) +{ + u32 macl = 0, mach = 0; + + /* + * Set the MAC address to handle and the vlan associated in a format + * understood by the hardware. + */ + mach |= MAC_VID << 16; + mach |= ((u32)mac[0]) << 8; + mach |= ((u32)mac[1]) << 0; + macl |= ((u32)mac[2]) << 24; + macl |= ((u32)mac[3]) << 16; + macl |= ((u32)mac[4]) << 8; + macl |= ((u32)mac[5]) << 0; + + writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0); + writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1); + + writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED, + priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2); + + writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, + priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL); + + return jr2_vlant_wait_for_completion(priv); +} + +static int jr2_write_hwaddr(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST); +} + +static void serdes_setup(struct jr2_private *priv) +{ + size_t mask; + int i = 0; + + for (i = 0; i < MAX_PORT; ++i) { + if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff) + continue; + + mask = BIT(priv->ports[i].serdes_index); + if (priv->ports[i].serdes_index < SERDES1G_MAX) { + serdes1g_setup(priv->regs[HSIO], mask, + priv->ports[i].phy_mode); + } else { + mask >>= SERDES6G(0); + serdes6g_setup(priv->regs[HSIO], mask, + priv->ports[i].phy_mode); + } + } +} + +static int jr2_start(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, + 0xff }; + int ret; + + ret = jr2_initialize(priv); + if (ret) + return ret; + + /* Set MAC address tables entries for CPU redirection */ + ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST); + if (ret) + return ret; + + ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST); + if (ret) + return ret; + + serdes_setup(priv); + + return 0; +} + +static void jr2_stop(struct udevice *dev) +{ +} + +static int jr2_send(struct udevice *dev, void *packet, int length) +{ + struct jr2_private *priv = dev_get_priv(dev); + u32 ifh[IFH_LEN]; + u32 *buf = packet; + + memset(ifh, '\0', IFH_LEN); + + /* Set DST PORT_MASK */ + ifh[0] = htonl(0); + ifh[1] = htonl(0x1FFFFF); + ifh[2] = htonl(~0); + /* Set DST_MODE to INJECT and UPDATE_FCS */ + ifh[5] = htonl(0x4c0); + + return mscc_send(priv->regs[QS], jr2_regs_qs, + ifh, IFH_LEN, buf, length); +} + +static int jr2_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct jr2_private *priv = dev_get_priv(dev); + u32 *rxbuf = (u32 *)net_rx_packets[0]; + int byte_cnt = 0; + + byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN, + false); + + *packetp = net_rx_packets[0]; + + return byte_cnt; +} + +static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size) +{ + int i = 0; + + for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i) + if (miim[i].miim_base == base && miim[i].miim_size == size) + return miim[i].bus; + + return NULL; +} + +static void add_port_entry(struct jr2_private *priv, size_t index, + size_t phy_addr, struct mii_dev *bus, + u8 serdes_index, u8 phy_mode) +{ + priv->ports[index].phy_addr = phy_addr; + priv->ports[index].bus = bus; + priv->ports[index].serdes_index = serdes_index; + priv->ports[index].phy_mode = phy_mode; +} + +static int jr2_probe(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + int i; + int ret; + struct resource res; + fdt32_t faddr; + phys_addr_t addr_base; + unsigned long addr_size; + ofnode eth_node, node, mdio_node; + size_t phy_addr; + struct mii_dev *bus; + struct ofnode_phandle_args phandle; + struct phy_device *phy; + + if (!priv) + return -EINVAL; + + /* Get registers and map them to the private structure */ + for (i = 0; i < ARRAY_SIZE(regs_names); i++) { + priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]); + if (!priv->regs[i]) { + debug + ("Error can't get regs base addresses for %s\n", + regs_names[i]); + return -ENOMEM; + } + } + + /* Initialize miim buses */ + memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT); + + /* iterate all the ports and find out on which bus they are */ + i = 0; + eth_node = dev_read_first_subnode(dev); + for (node = ofnode_first_subnode(eth_node); + ofnode_valid(node); + node = ofnode_next_subnode(node)) { + if (ofnode_read_resource(node, 0, &res)) + return -ENOMEM; + i = res.start; + + ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL, + 0, 0, &phandle); + if (ret) + continue; + + /* Get phy address on mdio bus */ + if (ofnode_read_resource(phandle.node, 0, &res)) + return -ENOMEM; + phy_addr = res.start; + + /* Get mdio node */ + mdio_node = ofnode_get_parent(phandle.node); + + if (ofnode_read_resource(mdio_node, 0, &res)) + return -ENOMEM; + faddr = cpu_to_fdt32(res.start); + + addr_base = ofnode_translate_address(mdio_node, &faddr); + addr_size = res.end - res.start; + + /* If the bus is new then create a new bus */ + if (!get_mdiobus(addr_base, addr_size)) + priv->bus[miim_count] = + jr2_mdiobus_init(addr_base, addr_size); + + /* Connect mdio bus with the port */ + bus = get_mdiobus(addr_base, addr_size); + + /* Get serdes info */ + ret = ofnode_parse_phandle_with_args(node, "phys", NULL, + 3, 0, &phandle); + if (ret) + return -ENOMEM; + + add_port_entry(priv, i, phy_addr, bus, phandle.args[1], + phandle.args[2]); + } + + for (i = 0; i < MAX_PORT; i++) { + if (!priv->ports[i].bus) + continue; + + phy = phy_connect(priv->ports[i].bus, + priv->ports[i].phy_addr, dev, + PHY_INTERFACE_MODE_NONE); + if (phy) + board_phy_config(phy); + } + + return 0; +} + +static int jr2_remove(struct udevice *dev) +{ + struct jr2_private *priv = dev_get_priv(dev); + int i; + + for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) { + mdio_unregister(priv->bus[i]); + mdio_free(priv->bus[i]); + } + + return 0; +} + +static const struct eth_ops jr2_ops = { + .start = jr2_start, + .stop = jr2_stop, + .send = jr2_send, + .recv = jr2_recv, + .write_hwaddr = jr2_write_hwaddr, +}; + +static const struct udevice_id mscc_jr2_ids[] = { + {.compatible = "mscc,vsc7454-switch" }, + { /* Sentinel */ } +}; + +U_BOOT_DRIVER(jr2) = { + .name = "jr2-switch", + .id = UCLASS_ETH, + .of_match = mscc_jr2_ids, + .probe = jr2_probe, + .remove = jr2_remove, + .ops = &jr2_ops, + .priv_auto_alloc_size = sizeof(struct jr2_private), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; diff --git a/drivers/net/mscc_eswitch/ocelot_switch.c b/drivers/net/mscc_eswitch/ocelot_switch.c index bf08c35..815c2da 100644 --- a/drivers/net/mscc_eswitch/ocelot_switch.c +++ b/drivers/net/mscc_eswitch/ocelot_switch.c @@ -142,18 +142,16 @@ static const unsigned long ocelot_regs_ana_table[] = { static struct mscc_miim_dev miim[NUM_PHY]; -static int mscc_miim_reset(struct mii_dev *bus) +static void mscc_phy_reset(void) { - struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv; - - if (miim->phy_regs) { - writel(0, miim->phy_regs + PHY_CFG); - writel(PHY_CFG_RST | PHY_CFG_COMMON_RST - | PHY_CFG_ENA, miim->phy_regs + PHY_CFG); - mdelay(500); + writel(0, miim[INTERNAL].phy_regs + PHY_CFG); + writel(PHY_CFG_RST | PHY_CFG_COMMON_RST + | PHY_CFG_ENA, miim[INTERNAL].phy_regs + PHY_CFG); + if (wait_for_bit_le32(miim[INTERNAL].phy_regs + PHY_STAT, + PHY_STAT_SUPERVISOR_COMPLETE, + true, 2000, false)) { + pr_err("Timeout in phy reset\n"); } - - return 0; } /* For now only setup the internal mdio bus */ @@ -194,7 +192,6 @@ static struct mii_dev *ocelot_mdiobus_init(struct udevice *dev) miim[INTERNAL].phy_regs = ioremap(phy_base[PHY], phy_size[PHY]); miim[INTERNAL].regs = ioremap(phy_base[MIIM], phy_size[MIIM]); bus->priv = &miim[INTERNAL]; - bus->reset = mscc_miim_reset; bus->read = mscc_miim_read; bus->write = mscc_miim_write; @@ -210,13 +207,8 @@ __weak void mscc_switch_reset(void) static void ocelot_stop(struct udevice *dev) { - struct ocelot_private *priv = dev_get_priv(dev); - int i; - mscc_switch_reset(); - for (i = 0; i < NUM_PHY; i++) - if (priv->bus[i]) - mscc_miim_reset(priv->bus[i]); + mscc_phy_reset(); } static void ocelot_cpu_capture_setup(struct ocelot_private *priv) @@ -473,6 +465,7 @@ static int ocelot_probe(struct udevice *dev) } priv->bus[INTERNAL] = ocelot_mdiobus_init(dev); + mscc_phy_reset(); for (i = 0; i < 4; i++) { phy_connect(priv->bus[INTERNAL], i, dev, diff --git a/drivers/net/mscc_eswitch/servalt_switch.c b/drivers/net/mscc_eswitch/servalt_switch.c new file mode 100644 index 0000000..995c623 --- /dev/null +++ b/drivers/net/mscc_eswitch/servalt_switch.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2019 Microsemi Corporation + */ + +#include <common.h> +#include <config.h> +#include <dm.h> +#include <dm/of_access.h> +#include <dm/of_addr.h> +#include <fdt_support.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <miiphy.h> +#include <net.h> +#include <wait_bit.h> + +#include "mscc_xfer.h" + +#define GCB_MIIM_MII_STATUS 0x0 +#define GCB_MIIM_STAT_BUSY BIT(3) +#define GCB_MIIM_MII_CMD 0x8 +#define GCB_MIIM_MII_CMD_OPR_WRITE BIT(1) +#define GCB_MIIM_MII_CMD_OPR_READ BIT(2) +#define GCB_MIIM_MII_CMD_WRDATA(x) ((x) << 4) +#define GCB_MIIM_MII_CMD_REGAD(x) ((x) << 20) +#define GCB_MIIM_MII_CMD_PHYAD(x) ((x) << 25) +#define GCB_MIIM_MII_CMD_VLD BIT(31) +#define GCB_MIIM_DATA 0xC +#define GCB_MIIM_DATA_ERROR (0x3 << 16) + +#define PHY_CFG 0x0 +#define PHY_CFG_ENA 0x3 +#define PHY_CFG_COMMON_RST BIT(2) +#define PHY_CFG_RST (0x3 << 3) +#define PHY_STAT 0x4 +#define PHY_STAT_SUPERVISOR_COMPLETE BIT(0) + +#define ANA_AC_RAM_CTRL_RAM_INIT 0x14fdc +#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x15474 + +#define ANA_CL_PORT_VLAN_CFG(x) (0xa018 + 0xc8 * (x)) +#define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19) +#define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17) + +#define ANA_L2_COMMON_FWD_CFG 0x18498 +#define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6) + +#define ASM_CFG_STAT_CFG 0xb08 +#define ASM_CFG_PORT(x) (0xb74 + 0x4 * (x)) +#define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8) +#define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1) +#define ASM_RAM_CTRL_RAM_INIT 0xbfc + +#define DEV_DEV_CFG_DEV_RST_CTRL 0x0 +#define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20) +#define DEV_MAC_CFG_MAC_ENA 0x24 +#define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4) +#define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0) +#define DEV_MAC_CFG_MAC_IFG 0x3c +#define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4) +#define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x) +#define DEV_PCS1G_CFG_PCS1G_CFG 0x48 +#define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0) +#define DEV_PCS1G_CFG_PCS1G_MODE 0x4c +#define DEV_PCS1G_CFG_PCS1G_SD 0x50 +#define DEV_PCS1G_CFG_PCS1G_ANEG 0x54 +#define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16) + +#define LRN_COMMON_ACCESS_CTRL 0x0 +#define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0) +#define LRN_COMMON_MAC_ACCESS_CFG0 0x4 +#define LRN_COMMON_MAC_ACCESS_CFG1 0x8 +#define LRN_COMMON_MAC_ACCESS_CFG2 0xc +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23) +#define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24) + +#define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4400 + 0x4 * (x)) +#define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17) + +#define QS_XTR_GRP_CFG(x) (4 * (x)) +#define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4) + +#define QSYS_SYSTEM_RESET_CFG 0x1048 +#define QSYS_CALCFG_CAL_AUTO 0x1134 +#define QSYS_CALCFG_CAL_CTRL 0x113c +#define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11) +#define QSYS_RAM_CTRL_RAM_INIT 0x1140 + +#define REW_RAM_CTRL_RAM_INIT 0xFFF4 + +#define MAC_VID 0 +#define CPU_PORT 11 +#define IFH_LEN 7 +#define ETH_ALEN 6 +#define PGID_BROADCAST 50 +#define PGID_UNICAST 51 + +static const char * const regs_names[] = { + "port0", "port1", + "ana_ac", "ana_cl", "ana_l2", "asm", "lrn", "qfwd", "qs", "qsys", "rew", +}; + +#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1 +#define MAX_PORT 2 + +enum servalt_ctrl_regs { + ANA_AC = MAX_PORT, + ANA_CL, + ANA_L2, + ASM, + LRN, + QFWD, + QS, + QSYS, + REW, +}; + +#define SERVALT_MIIM_BUS_COUNT 2 + +struct servalt_phy_port_t { + size_t phy_addr; + struct mii_dev *bus; +}; + +struct servalt_private { + void __iomem *regs[REGS_NAMES_COUNT]; + struct mii_dev *bus[SERVALT_MIIM_BUS_COUNT]; + struct servalt_phy_port_t ports[MAX_PORT]; +}; + +struct mscc_miim_dev { + void __iomem *regs; + phys_addr_t miim_base; + unsigned long miim_size; + struct mii_dev *bus; +}; + +static const unsigned long servalt_regs_qs[] = { + [MSCC_QS_XTR_RD] = 0x8, + [MSCC_QS_XTR_FLUSH] = 0x18, + [MSCC_QS_XTR_DATA_PRESENT] = 0x1c, + [MSCC_QS_INJ_WR] = 0x2c, + [MSCC_QS_INJ_CTRL] = 0x34, +}; + +static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT]; +static int miim_count = -1; + +static int mscc_miim_wait_ready(struct mscc_miim_dev *miim) +{ + return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS, + GCB_MIIM_STAT_BUSY, false, 250, false); +} + +static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv; + u32 val; + int ret; + + ret = mscc_miim_wait_ready(miim); + if (ret) + goto out; + + writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) | + GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ, + miim->regs + GCB_MIIM_MII_CMD); + + ret = mscc_miim_wait_ready(miim); + if (ret) + goto out; + + val = readl(miim->regs + GCB_MIIM_DATA); + if (val & GCB_MIIM_DATA_ERROR) { + ret = -EIO; + goto out; + } + + ret = val & 0xFFFF; +out: + return ret; +} + +static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv; + int ret; + + ret = mscc_miim_wait_ready(miim); + if (ret < 0) + goto out; + + writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) | + GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) | + GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD); + +out: + return ret; +} + +static struct mii_dev *servalt_mdiobus_init(phys_addr_t miim_base, + unsigned long miim_size) +{ + struct mii_dev *bus; + + bus = mdio_alloc(); + if (!bus) + return NULL; + + ++miim_count; + sprintf(bus->name, "miim-bus%d", miim_count); + + miim[miim_count].regs = ioremap(miim_base, miim_size); + miim[miim_count].miim_base = miim_base; + miim[miim_count].miim_size = miim_size; + bus->priv = &miim[miim_count]; + bus->read = mscc_miim_read; + bus->write = mscc_miim_write; + + if (mdio_register(bus)) + return NULL; + + miim[miim_count].bus = bus; + return bus; +} + +static void mscc_phy_reset(void) +{ + writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG); + writel(PHY_CFG_RST | PHY_CFG_COMMON_RST + | PHY_CFG_ENA, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG); + if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + GCB_PHY_CFG) + + PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE, + true, 2000, false)) { + pr_err("Timeout in phy reset\n"); + } +} + +static void servalt_cpu_capture_setup(struct servalt_private *priv) +{ + /* ASM: No preamble and IFH prefix on CPU injected frames */ + writel(ASM_CFG_PORT_NO_PREAMBLE_ENA | + ASM_CFG_PORT_INJ_FORMAT_CFG(1), + priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT)); + + /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */ + writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0)); + + /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */ + writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0)); + + /* Enable CPU port for any frame transfer */ + setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT), + QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA); + + /* Send a copy to CPU when found as forwarding entry */ + setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG, + ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA); +} + +static void servalt_port_init(struct servalt_private *priv, int port) +{ + void __iomem *regs = priv->regs[port]; + + /* Enable PCS */ + writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA, + regs + DEV_PCS1G_CFG_PCS1G_CFG); + + /* Disable Signal Detect */ + writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD); + + /* Enable MAC RX and TX */ + writel(DEV_MAC_CFG_MAC_ENA_RX_ENA | + DEV_MAC_CFG_MAC_ENA_TX_ENA, + regs + DEV_MAC_CFG_MAC_ENA); + + /* Clear sgmii_mode_ena */ + writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE); + + /* + * Clear sw_resolve_ena(bit 0) and set adv_ability to + * something meaningful just in case + */ + writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20), + regs + DEV_PCS1G_CFG_PCS1G_ANEG); + + /* Set MAC IFG Gaps */ + writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) | + DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) | + DEV_MAC_CFG_MAC_IFG_RX_IFG2(1), + regs + DEV_MAC_CFG_MAC_IFG); + + /* Set link speed and release all resets */ + writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2), + regs + DEV_DEV_CFG_DEV_RST_CTRL); + + /* Make VLAN aware for CPU traffic */ + writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA | + ANA_CL_PORT_VLAN_CFG_POP_CNT(1) | + MAC_VID, + priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port)); + + /* Enable CPU port for any frame transfer */ + setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port), + QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA); +} + +static int ram_init(u32 val, void __iomem *addr) +{ + writel(val, addr); + + if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) { + printf("Timeout in memory reset, reg = 0x%08x\n", val); + return 1; + } + + return 0; +} + +static int servalt_switch_init(struct servalt_private *priv) +{ + /* Initialize memories */ + ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT); + ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT); + + /* Reset counters */ + writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET); + writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG); + + /* Enable switch-core and queue system */ + writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG); + + return 0; +} + +static void servalt_switch_config(struct servalt_private *priv) +{ + writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO); + + writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) | + QSYS_CALCFG_CAL_CTRL_CAL_MODE(8), + priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL); +} + +static int servalt_initialize(struct servalt_private *priv) +{ + int ret, i; + + /* Initialize switch memories, enable core */ + ret = servalt_switch_init(priv); + if (ret) + return ret; + + servalt_switch_config(priv); + + for (i = 0; i < MAX_PORT; i++) + servalt_port_init(priv, i); + + servalt_cpu_capture_setup(priv); + + return 0; +} + +static inline +int servalt_vlant_wait_for_completion(struct servalt_private *priv) +{ + if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL, + LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, + false, 2000, false)) + return -ETIMEDOUT; + + return 0; +} + +static int servalt_mac_table_add(struct servalt_private *priv, + const unsigned char mac[ETH_ALEN], int pgid) +{ + u32 macl = 0, mach = 0; + + /* + * Set the MAC address to handle and the vlan associated in a format + * understood by the hardware. + */ + mach |= MAC_VID << 16; + mach |= ((u32)mac[0]) << 8; + mach |= ((u32)mac[1]) << 0; + macl |= ((u32)mac[2]) << 24; + macl |= ((u32)mac[3]) << 16; + macl |= ((u32)mac[4]) << 8; + macl |= ((u32)mac[5]) << 0; + + writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0); + writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1); + + writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD | + LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED, + priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2); + + writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT, + priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL); + + return servalt_vlant_wait_for_completion(priv); +} + +static int servalt_write_hwaddr(struct udevice *dev) +{ + struct servalt_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + return servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST); +} + +static int servalt_start(struct udevice *dev) +{ + struct servalt_private *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, + 0xff }; + int ret; + + ret = servalt_initialize(priv); + if (ret) + return ret; + + /* Set MAC address tables entries for CPU redirection */ + ret = servalt_mac_table_add(priv, mac, PGID_BROADCAST); + if (ret) + return ret; + + ret = servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST); + if (ret) + return ret; + + return 0; +} + +static void servalt_stop(struct udevice *dev) +{ +} + +static int servalt_send(struct udevice *dev, void *packet, int length) +{ + struct servalt_private *priv = dev_get_priv(dev); + u32 ifh[IFH_LEN]; + u32 *buf = packet; + + memset(ifh, '\0', IFH_LEN * 4); + + /* Set DST PORT_MASK */ + ifh[0] = htonl(0); + ifh[1] = htonl(0x1FFFFF); + ifh[2] = htonl(~0); + /* Set DST_MODE to INJECT and UPDATE_FCS */ + ifh[5] = htonl(0x4c0); + + return mscc_send(priv->regs[QS], servalt_regs_qs, + ifh, IFH_LEN, buf, length); +} + +static int servalt_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct servalt_private *priv = dev_get_priv(dev); + u32 *rxbuf = (u32 *)net_rx_packets[0]; + int byte_cnt = 0; + + byte_cnt = mscc_recv(priv->regs[QS], servalt_regs_qs, rxbuf, IFH_LEN, + false); + + *packetp = net_rx_packets[0]; + + return byte_cnt; +} + +static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size) +{ + int i = 0; + + for (i = 0; i < SERVALT_MIIM_BUS_COUNT; ++i) + if (miim[i].miim_base == base && miim[i].miim_size == size) + return miim[i].bus; + + return NULL; +} + +static void add_port_entry(struct servalt_private *priv, size_t index, + size_t phy_addr, struct mii_dev *bus) +{ + priv->ports[index].phy_addr = phy_addr; + priv->ports[index].bus = bus; +} + +static int servalt_probe(struct udevice *dev) +{ + struct servalt_private *priv = dev_get_priv(dev); + int i; + struct resource res; + fdt32_t faddr; + phys_addr_t addr_base; + unsigned long addr_size; + ofnode eth_node, node, mdio_node; + size_t phy_addr; + struct mii_dev *bus; + struct ofnode_phandle_args phandle; + + if (!priv) + return -EINVAL; + + /* Get registers and map them to the private structure */ + for (i = 0; i < ARRAY_SIZE(regs_names); i++) { + priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]); + if (!priv->regs[i]) { + debug + ("Error can't get regs base addresses for %s\n", + regs_names[i]); + return -ENOMEM; + } + } + + /* Initialize miim buses */ + memset(&miim, 0x0, sizeof(struct mscc_miim_dev) * + SERVALT_MIIM_BUS_COUNT); + + /* iterate all the ports and find out on which bus they are */ + i = 0; + eth_node = dev_read_first_subnode(dev); + for (node = ofnode_first_subnode(eth_node); + ofnode_valid(node); + node = ofnode_next_subnode(node)) { + if (ofnode_read_resource(node, 0, &res)) + return -ENOMEM; + i = res.start; + + ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0, + &phandle); + + /* Get phy address on mdio bus */ + if (ofnode_read_resource(phandle.node, 0, &res)) + return -ENOMEM; + phy_addr = res.start; + + /* Get mdio node */ + mdio_node = ofnode_get_parent(phandle.node); + + if (ofnode_read_resource(mdio_node, 0, &res)) + return -ENOMEM; + faddr = cpu_to_fdt32(res.start); + + addr_base = ofnode_translate_address(mdio_node, &faddr); + addr_size = res.end - res.start; + + /* If the bus is new then create a new bus */ + if (!get_mdiobus(addr_base, addr_size)) + priv->bus[miim_count] = + servalt_mdiobus_init(addr_base, addr_size); + + /* Connect mdio bus with the port */ + bus = get_mdiobus(addr_base, addr_size); + add_port_entry(priv, i, phy_addr, bus); + } + + mscc_phy_reset(); + + for (i = 0; i < MAX_PORT; i++) { + if (!priv->ports[i].bus) + continue; + + phy_connect(priv->ports[i].bus, priv->ports[i].phy_addr, dev, + PHY_INTERFACE_MODE_NONE); + } + + return 0; +} + +static int servalt_remove(struct udevice *dev) +{ + struct servalt_private *priv = dev_get_priv(dev); + int i; + + for (i = 0; i < SERVALT_MIIM_BUS_COUNT; i++) { + mdio_unregister(priv->bus[i]); + mdio_free(priv->bus[i]); + } + + return 0; +} + +static const struct eth_ops servalt_ops = { + .start = servalt_start, + .stop = servalt_stop, + .send = servalt_send, + .recv = servalt_recv, + .write_hwaddr = servalt_write_hwaddr, +}; + +static const struct udevice_id mscc_servalt_ids[] = { + {.compatible = "mscc,vsc7437-switch" }, + { /* Sentinel */ } +}; + +U_BOOT_DRIVER(servalt) = { + .name = "servalt-switch", + .id = UCLASS_ETH, + .of_match = mscc_servalt_ids, + .probe = servalt_probe, + .remove = servalt_remove, + .ops = &servalt_ops, + .priv_auto_alloc_size = sizeof(struct servalt_private), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; diff --git a/drivers/net/ti/cpsw-common.c b/drivers/net/ti/cpsw-common.c index 6c8ddbd..ac12cfe 100644 --- a/drivers/net/ti/cpsw-common.c +++ b/drivers/net/ti/cpsw-common.c @@ -16,35 +16,11 @@ DECLARE_GLOBAL_DATA_PTR; #define CTRL_MAC_REG(offset, id) ((offset) + 0x8 * (id)) -static int davinci_emac_3517_get_macid(struct udevice *dev, u16 offset, - int slave, u8 *mac_addr) +static void davinci_emac_3517_get_macid(u32 addr, u8 *mac_addr) { - void *fdt = (void *)gd->fdt_blob; - int node = dev_of_offset(dev); - u32 macid_lsb; - u32 macid_msb; - fdt32_t gmii = 0; - int syscon; - u32 addr; - - syscon = fdtdec_lookup_phandle(fdt, node, "syscon"); - if (syscon < 0) { - pr_err("Syscon offset not found\n"); - return -ENOENT; - } - - addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii), - sizeof(u32), MAP_NOCACHE); - if (addr == FDT_ADDR_T_NONE) { - pr_err("Not able to get syscon address to get mac efuse address\n"); - return -ENOENT; - } - - addr += CTRL_MAC_REG(offset, slave); - /* try reading mac address from efuse */ - macid_lsb = readl(addr); - macid_msb = readl(addr + 4); + u32 macid_lsb = readl(addr); + u32 macid_msb = readl(addr + 4); mac_addr[0] = (macid_msb >> 16) & 0xff; mac_addr[1] = (macid_msb >> 8) & 0xff; @@ -52,20 +28,62 @@ static int davinci_emac_3517_get_macid(struct udevice *dev, u16 offset, mac_addr[3] = (macid_lsb >> 16) & 0xff; mac_addr[4] = (macid_lsb >> 8) & 0xff; mac_addr[5] = macid_lsb & 0xff; +} - return 0; +static void cpsw_am33xx_cm_get_macid(u32 addr, u8 *mac_addr) +{ + /* try reading mac address from efuse */ + u32 macid_lo = readl(addr); + u32 macid_hi = readl(addr + 4); + + mac_addr[5] = (macid_lo >> 8) & 0xff; + mac_addr[4] = macid_lo & 0xff; + mac_addr[3] = (macid_hi >> 24) & 0xff; + mac_addr[2] = (macid_hi >> 16) & 0xff; + mac_addr[1] = (macid_hi >> 8) & 0xff; + mac_addr[0] = macid_hi & 0xff; +} + +void ti_cm_get_macid(struct udevice *dev, struct cpsw_platform_data *data, + u8 *mac_addr) +{ + if (!strcmp(data->macid_sel_compat, "cpsw,am33xx")) + cpsw_am33xx_cm_get_macid(data->syscon_addr, mac_addr); + else if (!strcmp(data->macid_sel_compat, "davinci,emac")) + davinci_emac_3517_get_macid(data->syscon_addr, mac_addr); } -static int cpsw_am33xx_cm_get_macid(struct udevice *dev, u16 offset, int slave, - u8 *mac_addr) +int ti_cm_get_macid_addr(struct udevice *dev, int slave, + struct cpsw_platform_data *data) { void *fdt = (void *)gd->fdt_blob; int node = dev_of_offset(dev); - u32 macid_lo; - u32 macid_hi; fdt32_t gmii = 0; int syscon; - u32 addr; + u16 offset; + + if (of_machine_is_compatible("ti,dm8148")) { + offset = 0x630; + data->macid_sel_compat = "cpsw,am33xx"; + } else if (of_machine_is_compatible("ti,am33xx")) { + offset = 0x630; + data->macid_sel_compat = "cpsw,am33xx"; + } else if (device_is_compatible(dev, "ti,am3517-emac")) { + offset = 0x110; + data->macid_sel_compat = "davinci,emac"; + } else if (device_is_compatible(dev, "ti,dm816-emac")) { + offset = 0x30; + data->macid_sel_compat = "cpsw,am33xx"; + } else if (of_machine_is_compatible("ti,am43")) { + offset = 0x630; + data->macid_sel_compat = "cpsw,am33xx"; + } else if (of_machine_is_compatible("ti,dra7")) { + offset = 0x514; + data->macid_sel_compat = "davinci,emac"; + } else { + dev_err(dev, "incompatible machine/device type for reading mac address\n"); + return -ENOENT; + } syscon = fdtdec_lookup_phandle(fdt, node, "syscon"); if (syscon < 0) { @@ -73,49 +91,16 @@ static int cpsw_am33xx_cm_get_macid(struct udevice *dev, u16 offset, int slave, return -ENOENT; } - addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, &gmii), - sizeof(u32), MAP_NOCACHE); - if (addr == FDT_ADDR_T_NONE) { + data->syscon_addr = (u32)map_physmem(fdt_translate_address(fdt, syscon, + &gmii), + sizeof(u32), MAP_NOCACHE); + if (data->syscon_addr == FDT_ADDR_T_NONE) { pr_err("Not able to get syscon address to get mac efuse address\n"); return -ENOENT; } - addr += CTRL_MAC_REG(offset, slave); - - /* try reading mac address from efuse */ - macid_lo = readl(addr); - macid_hi = readl(addr + 4); - - mac_addr[5] = (macid_lo >> 8) & 0xff; - mac_addr[4] = macid_lo & 0xff; - mac_addr[3] = (macid_hi >> 24) & 0xff; - mac_addr[2] = (macid_hi >> 16) & 0xff; - mac_addr[1] = (macid_hi >> 8) & 0xff; - mac_addr[0] = macid_hi & 0xff; + data->syscon_addr += CTRL_MAC_REG(offset, slave); return 0; -} - -int ti_cm_get_macid(struct udevice *dev, int slave, u8 *mac_addr) -{ - if (of_machine_is_compatible("ti,dm8148")) - return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr); - - if (of_machine_is_compatible("ti,am33xx")) - return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr); - - if (device_is_compatible(dev, "ti,am3517-emac")) - return davinci_emac_3517_get_macid(dev, 0x110, slave, mac_addr); - - if (device_is_compatible(dev, "ti,dm816-emac")) - return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr); - - if (of_machine_is_compatible("ti,am43")) - return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr); - - if (of_machine_is_compatible("ti,dra7")) - return davinci_emac_3517_get_macid(dev, 0x514, slave, mac_addr); - dev_err(dev, "incompatible machine/device type for reading mac address\n"); - return -ENOENT; } diff --git a/drivers/net/ti/cpsw.c b/drivers/net/ti/cpsw.c index f5fd02e..20ddb44 100644 --- a/drivers/net/ti/cpsw.c +++ b/drivers/net/ti/cpsw.c @@ -33,24 +33,6 @@ DECLARE_GLOBAL_DATA_PTR; #define GIGABITEN BIT(7) #define FULLDUPLEXEN BIT(0) #define MIIEN BIT(15) - -/* reg offset */ -#define CPSW_HOST_PORT_OFFSET 0x108 -#define CPSW_SLAVE0_OFFSET 0x208 -#define CPSW_SLAVE1_OFFSET 0x308 -#define CPSW_SLAVE_SIZE 0x100 -#define CPSW_CPDMA_OFFSET 0x800 -#define CPSW_HW_STATS 0x900 -#define CPSW_STATERAM_OFFSET 0xa00 -#define CPSW_CPTS_OFFSET 0xc00 -#define CPSW_ALE_OFFSET 0xd00 -#define CPSW_SLIVER0_OFFSET 0xd80 -#define CPSW_SLIVER1_OFFSET 0xdc0 -#define CPSW_BD_OFFSET 0x2000 -#define CPSW_MDIO_DIV 0xff - -#define AM335X_GMII_SEL_OFFSET 0x630 - /* DMA Registers */ #define CPDMA_TXCONTROL 0x004 #define CPDMA_RXCONTROL 0x014 @@ -209,10 +191,10 @@ struct cpdma_chan { #define chan_read_ptr(chan, fld) ((void *)__raw_readl((chan)->fld)) #define for_active_slave(slave, priv) \ - slave = (priv)->slaves + (priv)->data.active_slave; if (slave) + slave = (priv)->slaves + ((priv)->data)->active_slave; if (slave) #define for_each_slave(slave, priv) \ for (slave = (priv)->slaves; slave != (priv)->slaves + \ - (priv)->data.slaves; slave++) + ((priv)->data)->slaves; slave++) struct cpsw_priv { #ifdef CONFIG_DM_ETH @@ -220,7 +202,7 @@ struct cpsw_priv { #else struct eth_device *dev; #endif - struct cpsw_platform_data data; + struct cpsw_platform_data *data; int host_port; struct cpsw_regs *regs; @@ -327,7 +309,7 @@ static int cpsw_ale_match_addr(struct cpsw_priv *priv, const u8 *addr) u32 ale_entry[ALE_ENTRY_WORDS]; int type, idx; - for (idx = 0; idx < priv->data.ale_entries; idx++) { + for (idx = 0; idx < priv->data->ale_entries; idx++) { u8 entry_addr[6]; cpsw_ale_read(priv, idx, ale_entry); @@ -346,7 +328,7 @@ static int cpsw_ale_match_free(struct cpsw_priv *priv) u32 ale_entry[ALE_ENTRY_WORDS]; int type, idx; - for (idx = 0; idx < priv->data.ale_entries; idx++) { + for (idx = 0; idx < priv->data->ale_entries; idx++) { cpsw_ale_read(priv, idx, ale_entry); type = cpsw_ale_get_entry_type(ale_entry); if (type == ALE_TYPE_FREE) @@ -360,7 +342,7 @@ static int cpsw_ale_find_ageable(struct cpsw_priv *priv) u32 ale_entry[ALE_ENTRY_WORDS]; int type, idx; - for (idx = 0; idx < priv->data.ale_entries; idx++) { + for (idx = 0; idx < priv->data->ale_entries; idx++) { cpsw_ale_read(priv, idx, ale_entry); type = cpsw_ale_get_entry_type(ale_entry); if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) @@ -500,7 +482,7 @@ static int cpsw_slave_update_link(struct cpsw_slave *slave, *link = phy->link; if (phy->link) { /* link up */ - mac_control = priv->data.mac_control; + mac_control = priv->data->mac_control; if (phy->speed == 1000) mac_control |= GIGABITEN; if (phy->duplex == DUPLEX_FULL) @@ -710,7 +692,7 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) priv->desc_free = &priv->descs[0]; /* initialize channels */ - if (priv->data.version == CPSW_CTRL_VERSION_2) { + if (priv->data->version == CPSW_CTRL_VERSION_2) { memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan)); priv->rx_chan.hdp = priv->dma_regs + CPDMA_RXHDP_VER2; priv->rx_chan.cp = priv->dma_regs + CPDMA_RXCP_VER2; @@ -733,8 +715,8 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) /* clear dma state */ setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET); - if (priv->data.version == CPSW_CTRL_VERSION_2) { - for (i = 0; i < priv->data.channels; i++) { + if (priv->data->version == CPSW_CTRL_VERSION_2) { + for (i = 0; i < priv->data->channels; i++) { __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4 * i); __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 @@ -747,7 +729,7 @@ static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr) * i); } } else { - for (i = 0; i < priv->data.channels; i++) { + for (i = 0; i < priv->data->channels; i++) { __raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4 * i); __raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4 @@ -843,7 +825,7 @@ static void cpsw_slave_setup(struct cpsw_slave *slave, int slave_num, struct cpsw_priv *priv) { void *regs = priv->regs; - struct cpsw_slave_data *data = priv->data.slave_data + slave_num; + struct cpsw_slave_data *data = priv->data->slave_data + slave_num; slave->slave_num = slave_num; slave->data = data; slave->regs = regs + data->slave_reg_ofs; @@ -879,7 +861,7 @@ static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave) static void cpsw_phy_addr_update(struct cpsw_priv *priv) { - struct cpsw_platform_data *data = &priv->data; + struct cpsw_platform_data *data = priv->data; u16 alive = cpsw_mdio_get_alive(priv->bus); int active = data->active_slave; int new_addr = ffs(alive) - 1; @@ -899,7 +881,7 @@ static void cpsw_phy_addr_update(struct cpsw_priv *priv) int _cpsw_register(struct cpsw_priv *priv) { struct cpsw_slave *slave; - struct cpsw_platform_data *data = &priv->data; + struct cpsw_platform_data *data = priv->data; void *regs = (void *)data->cpsw_base; priv->slaves = malloc(sizeof(struct cpsw_slave) * data->slaves); @@ -988,7 +970,7 @@ int cpsw_register(struct cpsw_platform_data *data) } priv->dev = dev; - priv->data = *data; + priv->data = data; strcpy(dev->name, "cpsw"); dev->iobase = 0; @@ -1048,16 +1030,6 @@ static void cpsw_eth_stop(struct udevice *dev) return _cpsw_halt(priv); } - -static int cpsw_eth_probe(struct udevice *dev) -{ - struct cpsw_priv *priv = dev_get_priv(dev); - - priv->dev = dev; - - return _cpsw_register(priv); -} - static const struct eth_ops cpsw_eth_ops = { .start = cpsw_eth_start, .send = cpsw_eth_send, @@ -1079,9 +1051,9 @@ static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, u32 mask; u32 mode = 0; bool rgmii_id = false; - int slave = priv->data.active_slave; + int slave = priv->data->active_slave; - reg = readl(priv->data.gmii_sel); + reg = readl(priv->data->gmii_sel); switch (phy_mode) { case PHY_INTERFACE_MODE_RMII: @@ -1107,7 +1079,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6); mode <<= slave * 2; - if (priv->data.rmii_clock_external) { + if (priv->data->rmii_clock_external) { if (slave == 0) mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN; else @@ -1124,7 +1096,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv, reg &= ~mask; reg |= mode; - writel(reg, priv->data.gmii_sel); + writel(reg, priv->data->gmii_sel); } static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, @@ -1133,9 +1105,9 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, u32 reg; u32 mask; u32 mode = 0; - int slave = priv->data.active_slave; + int slave = priv->data->active_slave; - reg = readl(priv->data.gmii_sel); + reg = readl(priv->data->gmii_sel); switch (phy_mode) { case PHY_INTERFACE_MODE_RMII: @@ -1168,13 +1140,13 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv, return; } - if (priv->data.rmii_clock_external) + if (priv->data->rmii_clock_external) dev_err(priv->dev, "RMII External clock is not supported\n"); reg &= ~mask; reg |= mode; - writel(reg, priv->data.gmii_sel); + writel(reg, priv->data->gmii_sel); } static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, @@ -1188,13 +1160,28 @@ static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat, cpsw_gmii_sel_dra7xx(priv, phy_mode); } +static int cpsw_eth_probe(struct udevice *dev) +{ + struct cpsw_priv *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + priv->dev = dev; + priv->data = pdata->priv_pdata; + ti_cm_get_macid(dev, priv->data, pdata->enetaddr); + /* Select phy interface in control module */ + cpsw_phy_sel(priv, priv->data->phy_sel_compat, + pdata->phy_interface); + + return _cpsw_register(priv); +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); - struct cpsw_priv *priv = dev_get_priv(dev); + struct cpsw_platform_data *data; struct gpio_desc *mode_gpios; const char *phy_mode; - const char *phy_sel_compat = NULL; const void *fdt = gd->fdt_blob; int node = dev_of_offset(dev); int subnode; @@ -1203,45 +1190,47 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) int num_mode_gpios; int ret; + data = calloc(1, sizeof(struct cpsw_platform_data)); + pdata->priv_pdata = data; pdata->iobase = devfdt_get_addr(dev); - priv->data.version = CPSW_CTRL_VERSION_2; - priv->data.bd_ram_ofs = CPSW_BD_OFFSET; - priv->data.ale_reg_ofs = CPSW_ALE_OFFSET; - priv->data.cpdma_reg_ofs = CPSW_CPDMA_OFFSET; - priv->data.mdio_div = CPSW_MDIO_DIV; - priv->data.host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, + data->version = CPSW_CTRL_VERSION_2; + data->bd_ram_ofs = CPSW_BD_OFFSET; + data->ale_reg_ofs = CPSW_ALE_OFFSET; + data->cpdma_reg_ofs = CPSW_CPDMA_OFFSET; + data->mdio_div = CPSW_MDIO_DIV; + data->host_port_reg_ofs = CPSW_HOST_PORT_OFFSET, pdata->phy_interface = -1; - priv->data.cpsw_base = pdata->iobase; - priv->data.channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1); - if (priv->data.channels <= 0) { + data->cpsw_base = pdata->iobase; + data->channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1); + if (data->channels <= 0) { printf("error: cpdma_channels not found in dt\n"); return -ENOENT; } - priv->data.slaves = fdtdec_get_int(fdt, node, "slaves", -1); - if (priv->data.slaves <= 0) { + data->slaves = fdtdec_get_int(fdt, node, "slaves", -1); + if (data->slaves <= 0) { printf("error: slaves not found in dt\n"); return -ENOENT; } - priv->data.slave_data = malloc(sizeof(struct cpsw_slave_data) * - priv->data.slaves); + data->slave_data = malloc(sizeof(struct cpsw_slave_data) * + data->slaves); - priv->data.ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1); - if (priv->data.ale_entries <= 0) { + data->ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1); + if (data->ale_entries <= 0) { printf("error: ale_entries not found in dt\n"); return -ENOENT; } - priv->data.bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1); - if (priv->data.bd_ram_ofs <= 0) { + data->bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1); + if (data->bd_ram_ofs <= 0) { printf("error: bd_ram_size not found in dt\n"); return -ENOENT; } - priv->data.mac_control = fdtdec_get_int(fdt, node, "mac_control", -1); - if (priv->data.mac_control <= 0) { + data->mac_control = fdtdec_get_int(fdt, node, "mac_control", -1); + if (data->mac_control <= 0) { printf("error: ale_entries not found in dt\n"); return -ENOENT; } @@ -1256,7 +1245,7 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) } active_slave = fdtdec_get_int(fdt, node, "active_slave", 0); - priv->data.active_slave = active_slave; + data->active_slave = active_slave; fdt_for_each_subnode(subnode, fdt, node) { int len; @@ -1271,108 +1260,107 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev) pr_err("Not able to get MDIO address space\n"); return -ENOENT; } - priv->data.mdio_base = mdio_base; + data->mdio_base = mdio_base; } if (!strncmp(name, "slave", 5)) { u32 phy_id[2]; - if (slave_index >= priv->data.slaves) + if (slave_index >= data->slaves) continue; phy_mode = fdt_getprop(fdt, subnode, "phy-mode", NULL); if (phy_mode) - priv->data.slave_data[slave_index].phy_if = + data->slave_data[slave_index].phy_if = phy_get_interface_by_name(phy_mode); - priv->data.slave_data[slave_index].phy_of_handle = + data->slave_data[slave_index].phy_of_handle = fdtdec_lookup_phandle(fdt, subnode, "phy-handle"); - if (priv->data.slave_data[slave_index].phy_of_handle >= 0) { - priv->data.slave_data[slave_index].phy_addr = + if (data->slave_data[slave_index].phy_of_handle >= 0) { + data->slave_data[slave_index].phy_addr = fdtdec_get_int(gd->fdt_blob, - priv->data.slave_data[slave_index].phy_of_handle, + data->slave_data[slave_index].phy_of_handle, "reg", -1); } else { fdtdec_get_int_array(fdt, subnode, "phy_id", phy_id, 2); - priv->data.slave_data[slave_index].phy_addr = + data->slave_data[slave_index].phy_addr = phy_id[1]; } slave_index++; } if (!strncmp(name, "cpsw-phy-sel", 12)) { - priv->data.gmii_sel = cpsw_get_addr_by_node(fdt, - subnode); + data->gmii_sel = cpsw_get_addr_by_node(fdt, subnode); - if (priv->data.gmii_sel == FDT_ADDR_T_NONE) { + if (data->gmii_sel == FDT_ADDR_T_NONE) { pr_err("Not able to get gmii_sel reg address\n"); return -ENOENT; } if (fdt_get_property(fdt, subnode, "rmii-clock-ext", NULL)) - priv->data.rmii_clock_external = true; + data->rmii_clock_external = true; - phy_sel_compat = fdt_getprop(fdt, subnode, "compatible", - NULL); - if (!phy_sel_compat) { + data->phy_sel_compat = fdt_getprop(fdt, subnode, + "compatible", NULL); + if (!data->phy_sel_compat) { pr_err("Not able to get gmii_sel compatible\n"); return -ENOENT; } } } - priv->data.slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET; - priv->data.slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET; + data->slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET; + data->slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET; - if (priv->data.slaves == 2) { - priv->data.slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET; - priv->data.slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET; + if (data->slaves == 2) { + data->slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET; + data->slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET; } - ret = ti_cm_get_macid(dev, active_slave, pdata->enetaddr); + ret = ti_cm_get_macid_addr(dev, active_slave, data); if (ret < 0) { pr_err("cpsw read efuse mac failed\n"); return ret; } - pdata->phy_interface = priv->data.slave_data[active_slave].phy_if; + pdata->phy_interface = data->slave_data[active_slave].phy_if; if (pdata->phy_interface == -1) { debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); return -EINVAL; } - /* Select phy interface in control module */ - cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface); - return 0; } +static const struct udevice_id cpsw_eth_ids[] = { + { .compatible = "ti,cpsw" }, + { .compatible = "ti,am335x-cpsw" }, + { } +}; +#endif + int cpsw_get_slave_phy_addr(struct udevice *dev, int slave) { struct cpsw_priv *priv = dev_get_priv(dev); - struct cpsw_platform_data *data = &priv->data; + struct cpsw_platform_data *data = priv->data; return data->slave_data[slave].phy_addr; } -static const struct udevice_id cpsw_eth_ids[] = { - { .compatible = "ti,cpsw" }, - { .compatible = "ti,am335x-cpsw" }, - { } -}; - U_BOOT_DRIVER(eth_cpsw) = { .name = "eth_cpsw", .id = UCLASS_ETH, +#if CONFIG_IS_ENABLED(OF_CONTROL) .of_match = cpsw_eth_ids, .ofdata_to_platdata = cpsw_eth_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +#endif .probe = cpsw_eth_probe, .ops = &cpsw_eth_ops, .priv_auto_alloc_size = sizeof(struct cpsw_priv), - .platdata_auto_alloc_size = sizeof(struct eth_pdata), - .flags = DM_FLAG_ALLOC_PRIV_DMA, + .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_PRE_RELOC, }; #endif /* CONFIG_DM_ETH */ diff --git a/drivers/net/ti/keystone_net.c b/drivers/net/ti/keystone_net.c index a3ba91c..4baeeb8 100644 --- a/drivers/net/ti/keystone_net.c +++ b/drivers/net/ti/keystone_net.c @@ -88,6 +88,7 @@ struct ks2_eth_priv { struct mii_dev *mdio_bus; int phy_addr; phy_interface_t phy_if; + int phy_of_handle; int sgmii_link_type; void *mdio_base; struct rx_buff_desc net_rx_buffs; @@ -588,6 +589,10 @@ static int ks2_eth_probe(struct udevice *dev) if (priv->has_mdio) { priv->phydev = phy_connect(priv->mdio_bus, priv->phy_addr, dev, priv->phy_if); +#ifdef CONFIG_DM_ETH + if (priv->phy_of_handle) + priv->phydev->node = offset_to_ofnode(priv->phy_of_handle); +#endif phy_config(priv->phydev); } @@ -679,6 +684,7 @@ static int ks2_eth_parse_slave_interface(int netcp, int slave, int phy; int dma_count; u32 dma_channel[8]; + const char *phy_mode; priv->slave_port = fdtdec_get_int(fdt, slave, "slave-port", -1); priv->net_rx_buffs.rx_flow = priv->slave_port * 8; @@ -700,7 +706,9 @@ static int ks2_eth_parse_slave_interface(int netcp, int slave, priv->link_type = fdtdec_get_int(fdt, slave, "link-interface", -1); phy = fdtdec_lookup_phandle(fdt, slave, "phy-handle"); + if (phy >= 0) { + priv->phy_of_handle = phy; priv->phy_addr = fdtdec_get_int(fdt, phy, "reg", -1); mdio = fdt_parent_offset(fdt, phy); @@ -717,7 +725,19 @@ static int ks2_eth_parse_slave_interface(int netcp, int slave, priv->sgmii_link_type = SGMII_LINK_MAC_PHY; priv->has_mdio = true; } else if (priv->link_type == LINK_TYPE_RGMII_LINK_MAC_PHY) { - priv->phy_if = PHY_INTERFACE_MODE_RGMII; + phy_mode = fdt_getprop(fdt, slave, "phy-mode", NULL); + if (phy_mode) { + priv->phy_if = phy_get_interface_by_name(phy_mode); + if (priv->phy_if != PHY_INTERFACE_MODE_RGMII && + priv->phy_if != PHY_INTERFACE_MODE_RGMII_ID && + priv->phy_if != PHY_INTERFACE_MODE_RGMII_RXID && + priv->phy_if != PHY_INTERFACE_MODE_RGMII_TXID) { + pr_err("invalid phy-mode\n"); + return -EINVAL; + } + } else { + priv->phy_if = PHY_INTERFACE_MODE_RGMII; + } pdata->phy_interface = priv->phy_if; priv->has_mdio = true; } diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 32bbf41..102fb91 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -174,4 +174,12 @@ config KEYSTONE_USB_PHY This PHY is found on some Keystone (K2) devices supporting USB. +config MT76X8_USB_PHY + bool "MediaTek MT76x8 (7628/88) USB PHY support" + depends on PHY + help + Support the USB PHY in MT76x8 SoCs + + This PHY is found on MT76x8 devices supporting USB. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 099551d..b55917b 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o +obj-$(CONFIG_MT76X8_USB_PHY) += mt76x8-usb-phy.o diff --git a/drivers/phy/mt76x8-usb-phy.c b/drivers/phy/mt76x8-usb-phy.c new file mode 100644 index 0000000..268da8e --- /dev/null +++ b/drivers/phy/mt76x8-usb-phy.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Stefan Roese <sr@denx.de> + * + * Derived from linux/drivers/phy/ralink/phy-ralink-usb.c + * Copyright (C) 2017 John Crispin <john@phrozen.org> + */ + +#include <common.h> +#include <dm.h> +#include <generic-phy.h> +#include <regmap.h> +#include <reset-uclass.h> +#include <syscon.h> +#include <asm/io.h> + +#define RT_SYSC_REG_SYSCFG1 0x014 +#define RT_SYSC_REG_CLKCFG1 0x030 +#define RT_SYSC_REG_USB_PHY_CFG 0x05c + +#define OFS_U2_PHY_AC0 0x800 +#define OFS_U2_PHY_AC1 0x804 +#define OFS_U2_PHY_AC2 0x808 +#define OFS_U2_PHY_ACR0 0x810 +#define OFS_U2_PHY_ACR1 0x814 +#define OFS_U2_PHY_ACR2 0x818 +#define OFS_U2_PHY_ACR3 0x81C +#define OFS_U2_PHY_ACR4 0x820 +#define OFS_U2_PHY_AMON0 0x824 +#define OFS_U2_PHY_DCR0 0x860 +#define OFS_U2_PHY_DCR1 0x864 +#define OFS_U2_PHY_DTM0 0x868 +#define OFS_U2_PHY_DTM1 0x86C + +#define RT_RSTCTRL_UDEV BIT(25) +#define RT_RSTCTRL_UHST BIT(22) +#define RT_SYSCFG1_USB0_HOST_MODE BIT(10) + +#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25) +#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22) +#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20) +#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18) + +#define USB_PHY_UTMI_8B60M BIT(1) +#define UDEV_WAKEUP BIT(0) + +struct mt76x8_usb_phy { + u32 clk; + void __iomem *base; + struct regmap *sysctl; +}; + +static void u2_phy_w32(struct mt76x8_usb_phy *phy, u32 val, u32 reg) +{ + writel(val, phy->base + reg); +} + +static u32 u2_phy_r32(struct mt76x8_usb_phy *phy, u32 reg) +{ + return readl(phy->base + reg); +} + +static void mt76x8_usb_phy_init(struct mt76x8_usb_phy *phy) +{ + u2_phy_r32(phy, OFS_U2_PHY_AC2); + u2_phy_r32(phy, OFS_U2_PHY_ACR0); + u2_phy_r32(phy, OFS_U2_PHY_DCR0); + + u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0); + u2_phy_r32(phy, OFS_U2_PHY_DCR0); + u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0); + u2_phy_r32(phy, OFS_U2_PHY_DCR0); + u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0); + u2_phy_r32(phy, OFS_U2_PHY_DCR0); + u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0); + u2_phy_r32(phy, OFS_U2_PHY_DCR0); + u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0); + u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1); + u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3); + u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0); +} + +static int mt76x8_usb_phy_power_on(struct phy *_phy) +{ + struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev); + u32 t; + + /* enable the phy */ + regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1, + phy->clk, phy->clk); + + /* setup host mode */ + regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1, + RT_SYSCFG1_USB0_HOST_MODE, + RT_SYSCFG1_USB0_HOST_MODE); + + /* + * The SDK kernel had a delay of 100ms. however on device + * testing showed that 10ms is enough + */ + mdelay(10); + + if (phy->base) + mt76x8_usb_phy_init(phy); + + /* print some status info */ + regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t); + printf("remote usb device wakeup %s\n", + (t & UDEV_WAKEUP) ? "enabled" : "disabled"); + if (t & USB_PHY_UTMI_8B60M) + printf("UTMI 8bit 60MHz\n"); + else + printf("UTMI 16bit 30MHz\n"); + + return 0; +} + +static int mt76x8_usb_phy_power_off(struct phy *_phy) +{ + struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev); + + /* disable the phy */ + regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1, + phy->clk, 0); + + return 0; +} + +static int mt76x8_usb_phy_probe(struct udevice *dev) +{ + struct mt76x8_usb_phy *phy = dev_get_priv(dev); + + phy->sysctl = syscon_regmap_lookup_by_phandle(dev, "ralink,sysctl"); + if (IS_ERR(phy->sysctl)) + return PTR_ERR(phy->sysctl); + + phy->base = dev_read_addr_ptr(dev); + if (!phy->base) + return -EINVAL; + + return 0; +} + +static struct phy_ops mt76x8_usb_phy_ops = { + .power_on = mt76x8_usb_phy_power_on, + .power_off = mt76x8_usb_phy_power_off, +}; + +static const struct udevice_id mt76x8_usb_phy_ids[] = { + { .compatible = "mediatek,mt7628-usbphy" }, + { } +}; + +U_BOOT_DRIVER(mt76x8_usb_phy) = { + .name = "mt76x8_usb_phy", + .id = UCLASS_PHY, + .of_match = mt76x8_usb_phy_ids, + .ops = &mt76x8_usb_phy_ops, + .probe = mt76x8_usb_phy_probe, + .priv_auto_alloc_size = sizeof(struct mt76x8_usb_phy), +}; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index be709f7..a0ac167 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -209,6 +209,25 @@ config PINCTRL_STM32 the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_STMFX + bool "STMicroelectronics STMFX I2C GPIO expander pinctrl driver" + depends on DM && PINCTRL_FULL + help + I2C driver for STMicroelectronics Multi-Function eXpander (STMFX) + GPIO expander. + Supports pin multiplexing control on stm32 SoCs. + + The driver is controlled by a device tree node which contains both + the GPIO definitions and pin control functions for each available + multiplex function. + +config SPL_PINCTRL_STMFX + bool "STMicroelectronics STMFX I2C GPIO expander pinctrl driver in SPL" + depends on SPL_PINCTRL_FULL + help + This option is an SPL-variant of the SPL_PINCTRL_STMFX option. + See the help of PINCTRL_STMFX for details. + config ASPEED_AST2500_PINCTRL bool "Aspeed AST2500 pin control driver" depends on DM && PINCTRL_GENERIC && ASPEED_AST2500 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e2c2b15..4b080b7 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,4 +22,5 @@ obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o +obj-$(CONFIG_$(SPL_)PINCTRL_STMFX) += pinctrl-stmfx.o obj-y += broadcom/ diff --git a/drivers/pinctrl/ath79/Makefile b/drivers/pinctrl/ath79/Makefile index 1daa212..c7d1e44 100644 --- a/drivers/pinctrl/ath79/Makefile +++ b/drivers/pinctrl/ath79/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_PINCTRL_AR933X) += pinctrl_ar933x.o -obj-$(CONFIG_PINCTRL_QCA953x) += pinctrl_qca953x.o +obj-$(CONFIG_PINCTRL_QCA953X) += pinctrl_qca953x.o diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c new file mode 100644 index 0000000..5431df9 --- /dev/null +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander + * based on Linux driver : pinctrl/pinctrl-stmfx.c + */ +#include <common.h> +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <dm/device.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <linux/bitfield.h> +#include <power/regulator.h> + +/* STMFX pins = GPIO[15:0] + aGPIO[7:0] */ +#define STMFX_MAX_GPIO 16 +#define STMFX_MAX_AGPIO 8 + +/* General */ +#define STMFX_REG_CHIP_ID 0x00 /* R */ +#define STMFX_REG_FW_VERSION_MSB 0x01 /* R */ +#define STMFX_REG_FW_VERSION_LSB 0x02 /* R */ +#define STMFX_REG_SYS_CTRL 0x40 /* RW */ + +/* MFX boot time is around 10ms, so after reset, we have to wait this delay */ +#define STMFX_BOOT_TIME_MS 10 + +/* GPIOs expander */ +/* GPIO_STATE1 0x10, GPIO_STATE2 0x11, GPIO_STATE3 0x12 */ +#define STMFX_REG_GPIO_STATE 0x10 /* R */ +/* GPIO_DIR1 0x60, GPIO_DIR2 0x61, GPIO_DIR3 0x63 */ +#define STMFX_REG_GPIO_DIR 0x60 /* RW */ +/* GPIO_TYPE1 0x64, GPIO_TYPE2 0x65, GPIO_TYPE3 0x66 */ +#define STMFX_REG_GPIO_TYPE 0x64 /* RW */ +/* GPIO_PUPD1 0x68, GPIO_PUPD2 0x69, GPIO_PUPD3 0x6A */ +#define STMFX_REG_GPIO_PUPD 0x68 /* RW */ +/* GPO_SET1 0x6C, GPO_SET2 0x6D, GPO_SET3 0x6E */ +#define STMFX_REG_GPO_SET 0x6C /* RW */ +/* GPO_CLR1 0x70, GPO_CLR2 0x71, GPO_CLR3 0x72 */ +#define STMFX_REG_GPO_CLR 0x70 /* RW */ + +/* STMFX_REG_CHIP_ID bitfields */ +#define STMFX_REG_CHIP_ID_MASK GENMASK(7, 0) + +/* STMFX_REG_SYS_CTRL bitfields */ +#define STMFX_REG_SYS_CTRL_GPIO_EN BIT(0) +#define STMFX_REG_SYS_CTRL_ALTGPIO_EN BIT(3) +#define STMFX_REG_SYS_CTRL_SWRST BIT(7) + +#define NR_GPIO_REGS 3 +#define NR_GPIOS_PER_REG 8 +#define get_reg(offset) ((offset) / NR_GPIOS_PER_REG) +#define get_shift(offset) ((offset) % NR_GPIOS_PER_REG) +#define get_mask(offset) (BIT(get_shift(offset))) + +struct stmfx_pinctrl { + struct udevice *gpio; +}; + +static int stmfx_read(struct udevice *dev, uint offset) +{ + return dm_i2c_reg_read(dev_get_parent(dev), offset); +} + +static int stmfx_write(struct udevice *dev, uint offset, unsigned int val) +{ + return dm_i2c_reg_write(dev_get_parent(dev), offset, val); +} + +static int stmfx_gpio_get(struct udevice *dev, unsigned int offset) +{ + u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset); + u32 mask = get_mask(offset); + int ret; + + ret = stmfx_read(dev, reg); + + return ret < 0 ? ret : !!(ret & mask); +} + +static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value) +{ + u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR; + u32 mask = get_mask(offset); + + return stmfx_write(dev, reg + get_reg(offset), mask); +} + +static int stmfx_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); + u32 mask = get_mask(offset); + int ret; + + ret = stmfx_read(dev, reg); + + if (ret < 0) + return ret; + /* On stmfx, gpio pins direction is (0)input, (1)output. */ + + return ret & mask ? GPIOF_OUTPUT : GPIOF_INPUT; +} + +static int stmfx_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); + u32 mask = get_mask(offset); + int ret; + + ret = stmfx_read(dev, reg); + if (ret < 0) + return ret; + + ret &= ~mask; + + return stmfx_write(dev, reg, ret & ~mask); +} + +static int stmfx_gpio_direction_output(struct udevice *dev, + unsigned int offset, int value) +{ + u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset); + u32 mask = get_mask(offset); + int ret; + + ret = stmfx_gpio_set(dev, offset, value); + if (ret < 0) + return ret; + + ret = stmfx_read(dev, reg); + if (ret < 0) + return ret; + + return stmfx_write(dev, reg, ret | mask); +} + +static int stmfx_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct ofnode_phandle_args args; + u8 sys_ctrl; + + uc_priv->bank_name = "stmfx"; + uc_priv->gpio_count = STMFX_MAX_GPIO + STMFX_MAX_AGPIO; + if (!dev_read_phandle_with_args(dev, "gpio-ranges", + NULL, 3, 0, &args)) { + uc_priv->gpio_count = args.args[2]; + } + + /* enable GPIO function */ + sys_ctrl = STMFX_REG_SYS_CTRL_GPIO_EN; + if (uc_priv->gpio_count > STMFX_MAX_GPIO) + sys_ctrl |= STMFX_REG_SYS_CTRL_ALTGPIO_EN; + stmfx_write(dev, STMFX_REG_SYS_CTRL, sys_ctrl); + + return 0; +} + +static const struct dm_gpio_ops stmfx_gpio_ops = { + .set_value = stmfx_gpio_set, + .get_value = stmfx_gpio_get, + .get_function = stmfx_gpio_get_function, + .direction_input = stmfx_gpio_direction_input, + .direction_output = stmfx_gpio_direction_output, +}; + +U_BOOT_DRIVER(stmfx_gpio) = { + .name = "stmfx-gpio", + .id = UCLASS_GPIO, + .probe = stmfx_gpio_probe, + .ops = &stmfx_gpio_ops, +}; + +#if CONFIG_IS_ENABLED(PINCONF) +static const struct pinconf_param stmfx_pinctrl_conf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 }, + { "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 }, + { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, + { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 }, + { "output-high", PIN_CONFIG_OUTPUT, 1 }, + { "output-low", PIN_CONFIG_OUTPUT, 0 }, +}; + +static int stmfx_pinctrl_set_pupd(struct udevice *dev, + unsigned int pin, u32 pupd) +{ + u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin); + u32 mask = get_mask(pin); + int ret; + + ret = stmfx_read(dev, reg); + if (ret < 0) + return ret; + ret = (ret & ~mask) | (pupd ? mask : 0); + + return stmfx_write(dev, reg, ret); +} + +static int stmfx_pinctrl_set_type(struct udevice *dev, + unsigned int pin, u32 type) +{ + u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin); + u32 mask = get_mask(pin); + int ret; + + ret = stmfx_read(dev, reg); + if (ret < 0) + return ret; + ret = (ret & ~mask) | (type ? mask : 0); + + return stmfx_write(dev, reg, ret); +} + +static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin, + unsigned int param, unsigned int arg) +{ + int ret, dir; + struct stmfx_pinctrl *plat = dev_get_platdata(dev); + + dir = stmfx_gpio_get_function(plat->gpio, pin); + + if (dir < 0) + return dir; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_DOWN: + ret = stmfx_pinctrl_set_pupd(dev, pin, 0); + break; + case PIN_CONFIG_BIAS_PULL_UP: + ret = stmfx_pinctrl_set_pupd(dev, pin, 1); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (dir == GPIOF_OUTPUT) + ret = stmfx_pinctrl_set_type(dev, pin, 1); + else + ret = stmfx_pinctrl_set_type(dev, pin, 0); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (dir == GPIOF_OUTPUT) + ret = stmfx_pinctrl_set_type(dev, pin, 0); + else + ret = stmfx_pinctrl_set_type(dev, pin, 1); + break; + case PIN_CONFIG_OUTPUT: + ret = stmfx_gpio_direction_output(plat->gpio, pin, arg); + break; + default: + return -ENOTSUPP; + } + + return ret; +} +#endif + +static int stmfx_pinctrl_get_pins_count(struct udevice *dev) +{ + struct stmfx_pinctrl *plat = dev_get_platdata(dev); + struct gpio_dev_priv *uc_priv; + + uc_priv = dev_get_uclass_priv(plat->gpio); + + return uc_priv->gpio_count; +} + +/* + * STMFX pins[15:0] are called "gpio[15:0]" + * and STMFX pins[23:16] are called "agpio[7:0]" + */ +#define MAX_PIN_NAME_LEN 7 +static char pin_name[MAX_PIN_NAME_LEN]; +static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + if (selector < STMFX_MAX_GPIO) + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + else + snprintf(pin_name, MAX_PIN_NAME_LEN, "agpio%u", selector - 16); + return pin_name; +} + +static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev, + unsigned int selector, + char *buf, int size) +{ + struct stmfx_pinctrl *plat = dev_get_platdata(dev); + int func; + + func = stmfx_gpio_get_function(plat->gpio, selector); + if (func < 0) + return func; + + snprintf(buf, size, "%s", func == GPIOF_INPUT ? "input" : "output"); + + return 0; +} + +static int stmfx_pinctrl_bind(struct udevice *dev) +{ + struct stmfx_pinctrl *plat = dev_get_platdata(dev); + + return device_bind_driver_to_node(dev->parent, + "stmfx-gpio", "stmfx-gpio", + dev_ofnode(dev), &plat->gpio); +}; + +static int stmfx_pinctrl_probe(struct udevice *dev) +{ + struct stmfx_pinctrl *plat = dev_get_platdata(dev); + + return device_probe(plat->gpio); +}; + +const struct pinctrl_ops stmfx_pinctrl_ops = { + .get_pins_count = stmfx_pinctrl_get_pins_count, + .get_pin_name = stmfx_pinctrl_get_pin_name, + .set_state = pinctrl_generic_set_state, + .get_pin_muxing = stmfx_pinctrl_get_pin_muxing, +#if CONFIG_IS_ENABLED(PINCONF) + .pinconf_set = stmfx_pinctrl_conf_set, + .pinconf_num_params = ARRAY_SIZE(stmfx_pinctrl_conf_params), + .pinconf_params = stmfx_pinctrl_conf_params, +#endif +}; + +static const struct udevice_id stmfx_pinctrl_match[] = { + { .compatible = "st,stmfx-0300-pinctrl", }, +}; + +U_BOOT_DRIVER(stmfx_pinctrl) = { + .name = "stmfx-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = of_match_ptr(stmfx_pinctrl_match), + .bind = stmfx_pinctrl_bind, + .probe = stmfx_pinctrl_probe, + .ops = &stmfx_pinctrl_ops, + .platdata_auto_alloc_size = sizeof(struct stmfx_pinctrl), +}; + +static int stmfx_chip_init(struct udevice *dev) +{ + u8 id; + u8 version[2]; + int ret; + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + + id = dm_i2c_reg_read(dev, STMFX_REG_CHIP_ID); + if (id < 0) { + dev_err(dev, "error reading chip id: %d\n", id); + return ret; + } + /* + * Check that ID is the complement of the I2C address: + * STMFX I2C address follows the 7-bit format (MSB), that's why + * client->addr is shifted. + * + * STMFX_I2C_ADDR| STMFX | Linux + * input pin | I2C device address | I2C device address + *--------------------------------------------------------- + * 0 | b: 1000 010x h:0x84 | 0x42 + * 1 | b: 1000 011x h:0x86 | 0x43 + */ + if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (chip->chip_addr << 1)) { + dev_err(dev, "unknown chip id: %#x\n", id); + return -EINVAL; + } + + ret = dm_i2c_read(dev, STMFX_REG_FW_VERSION_MSB, + version, sizeof(version)); + if (ret) { + dev_err(dev, "error reading fw version: %d\n", ret); + return ret; + } + + dev_info(dev, "STMFX id: %#x, fw version: %x.%02x\n", + id, version[0], version[1]); + + ret = dm_i2c_reg_read(dev, STMFX_REG_SYS_CTRL); + + if (ret < 0) + return ret; + + ret = dm_i2c_reg_write(dev, STMFX_REG_SYS_CTRL, + ret | STMFX_REG_SYS_CTRL_SWRST); + if (ret) + return ret; + + mdelay(STMFX_BOOT_TIME_MS); + + return ret; +} + +static int stmfx_probe(struct udevice *dev) +{ + struct udevice *vdd; + int ret; + + ret = device_get_supply_regulator(dev, "vdd-supply", &vdd); + if (ret && ret != -ENOENT) { + dev_err(dev, "vdd regulator error:%d\n", ret); + return ret; + } + if (!ret) { + ret = regulator_set_enable(vdd, true); + if (ret) { + dev_err(dev, "vdd enable failed: %d\n", ret); + return ret; + } + } + + return stmfx_chip_init(dev); +} + +static const struct udevice_id stmfx_match[] = { + { .compatible = "st,stmfx-0300", }, +}; + +U_BOOT_DRIVER(stmfx) = { + .name = "stmfx", + .id = UCLASS_I2C_GENERIC, + .of_match = of_match_ptr(stmfx_match), + .probe = stmfx_probe, + .bind = dm_scan_fdt_dev, +}; diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 0e3260a..0e6c559 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -27,28 +27,6 @@ int pinctrl_decode_pin_config(const void *blob, int node) return flags; } -/* - * TODO: this function is temporary for v2019.01. - * It should be renamed to pinctrl_decode_pin_config(), - * the original pinctrl_decode_pin_config() function should - * be removed and all callers of the original function should - * be migrated to use the new one. - */ -int pinctrl_decode_pin_config_dm(struct udevice *dev) -{ - int pinconfig = 0; - - if (dev->uclass->uc_drv->id != UCLASS_PINCONFIG) - return -EINVAL; - - if (dev_read_bool(dev, "bias-pull-up")) - pinconfig |= 1 << PIN_CONFIG_BIAS_PULL_UP; - else if (dev_read_bool(dev, "bias-pull-down")) - pinconfig |= 1 << PIN_CONFIG_BIAS_PULL_DOWN; - - return pinconfig; -} - #if CONFIG_IS_ENABLED(PINCTRL_FULL) /** * pinctrl_config_one() - apply pinctrl settings for a single node @@ -149,6 +127,9 @@ static int pinconfig_post_bind(struct udevice *dev) ofnode_get_property(node, "compatible", &ret); if (ret >= 0) continue; + /* If this node has "gpio-controller" property, skip */ + if (ofnode_read_bool(node, "gpio-controller")) + continue; if (ret != -FDT_ERR_NOTFOUND) return ret; @@ -201,11 +182,14 @@ static int pinctrl_select_state_simple(struct udevice *dev) int ret; /* - * For simplicity, assume the first device of PINCTRL uclass - * is the correct one. This is most likely OK as there is - * usually only one pinctrl device on the system. + * For most system, there is only one pincontroller device. But in + * case of multiple pincontroller devices, probe the one with sequence + * number 0 (defined by alias) to avoid race condition. */ - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev); + ret = uclass_get_device_by_seq(UCLASS_PINCTRL, 0, &pctldev); + if (ret) + /* if not found, get the first one */ + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev); if (ret) return ret; diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 8cf60eb..b0cd260 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -231,10 +231,10 @@ config DM_PMIC_TPS65910 DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO pmic children. -config PMIC_STPMU1 - bool "Enable support for STMicroelectronics STPMU1 PMIC" +config PMIC_STPMIC1 + bool "Enable support for STMicroelectronics STPMIC1 PMIC" depends on DM_PMIC && DM_I2C ---help--- - The STPMU1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches. + The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches. It is accessed via an I2C interface. The device is used with STM32MP1 SoCs. This driver implements register read/write operations. diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 637352a..ce250cb 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_DM_PMIC_TPS65910) += pmic_tps65910_dm.o obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o -obj-$(CONFIG_PMIC_STPMU1) += stpmu1.o +obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o diff --git a/drivers/power/pmic/stpmic1.c b/drivers/power/pmic/stpmic1.c new file mode 100644 index 0000000..65296c5 --- /dev/null +++ b/drivers/power/pmic/stpmic1.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <i2c.h> +#include <sysreset.h> +#include <dm/device.h> +#include <dm/lists.h> +#include <power/pmic.h> +#include <power/stpmic1.h> + +#define STPMIC1_NUM_OF_REGS 0x100 + +#define STPMIC1_NVM_SIZE 8 +#define STPMIC1_NVM_POLL_TIMEOUT 100000 +#define STPMIC1_NVM_START_ADDRESS 0xf8 + +enum pmic_nvm_op { + SHADOW_READ, + SHADOW_WRITE, + NVM_READ, + NVM_WRITE, +}; + +#if CONFIG_IS_ENABLED(DM_REGULATOR) +static const struct pmic_child_info stpmic1_children_info[] = { + { .prefix = "ldo", .driver = "stpmic1_ldo" }, + { .prefix = "buck", .driver = "stpmic1_buck" }, + { .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" }, + { .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" }, + { .prefix = "boost", .driver = "stpmic1_boost" }, + { }, +}; +#endif /* DM_REGULATOR */ + +static int stpmic1_reg_count(struct udevice *dev) +{ + return STPMIC1_NUM_OF_REGS; +} + +static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff, + int len) +{ + int ret; + + ret = dm_i2c_write(dev, reg, buff, len); + if (ret) + dev_err(dev, "%s: failed to write register %#x :%d", + __func__, reg, ret); + + return ret; +} + +static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len) +{ + int ret; + + ret = dm_i2c_read(dev, reg, buff, len); + if (ret) + dev_err(dev, "%s: failed to read register %#x : %d", + __func__, reg, ret); + + return ret; +} + +static int stpmic1_bind(struct udevice *dev) +{ +#if CONFIG_IS_ENABLED(DM_REGULATOR) + ofnode regulators_node; + int children; + + regulators_node = dev_read_subnode(dev, "regulators"); + if (!ofnode_valid(regulators_node)) { + dev_dbg(dev, "regulators subnode not found!"); + return -ENXIO; + } + dev_dbg(dev, "found regulators subnode\n"); + + children = pmic_bind_children(dev, regulators_node, + stpmic1_children_info); + if (!children) + dev_dbg(dev, "no child found\n"); +#endif /* DM_REGULATOR */ + + if (CONFIG_IS_ENABLED(SYSRESET)) + return device_bind_driver(dev, "stpmic1-sysreset", + "stpmic1-sysreset", NULL); + + return 0; +} + +static struct dm_pmic_ops stpmic1_ops = { + .reg_count = stpmic1_reg_count, + .read = stpmic1_read, + .write = stpmic1_write, +}; + +static const struct udevice_id stpmic1_ids[] = { + { .compatible = "st,stpmic1" }, + { } +}; + +U_BOOT_DRIVER(pmic_stpmic1) = { + .name = "stpmic1_pmic", + .id = UCLASS_PMIC, + .of_match = stpmic1_ids, + .bind = stpmic1_bind, + .ops = &stpmic1_ops, +}; + +#ifndef CONFIG_SPL_BUILD +static int stpmic1_nvm_rw(u8 addr, u8 *buf, int buf_len, enum pmic_nvm_op op) +{ + struct udevice *dev; + unsigned long timeout; + u8 cmd = STPMIC1_NVM_CMD_READ; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_PMIC, + DM_GET_DRIVER(pmic_stpmic1), &dev); + if (ret) + /* No PMIC on power discrete board */ + return -EOPNOTSUPP; + + if (addr < STPMIC1_NVM_START_ADDRESS) + return -EACCES; + + if (op == SHADOW_READ) + return pmic_read(dev, addr, buf, buf_len); + + if (op == SHADOW_WRITE) + return pmic_write(dev, addr, buf, buf_len); + + if (op == NVM_WRITE) { + cmd = STPMIC1_NVM_CMD_PROGRAM; + + ret = pmic_write(dev, addr, buf, buf_len); + if (ret < 0) + return ret; + } + + ret = pmic_reg_read(dev, STPMIC1_NVM_CR); + if (ret < 0) + return ret; + + ret = pmic_reg_write(dev, STPMIC1_NVM_CR, ret | cmd); + if (ret < 0) + return ret; + + timeout = timer_get_us() + STPMIC1_NVM_POLL_TIMEOUT; + for (;;) { + ret = pmic_reg_read(dev, STPMIC1_NVM_SR); + if (ret < 0) + return ret; + + if (!(ret & STPMIC1_NVM_BUSY)) + break; + + if (time_after(timer_get_us(), timeout)) + break; + } + + if (ret & STPMIC1_NVM_BUSY) + return -ETIMEDOUT; + + if (op == NVM_READ) { + ret = pmic_read(dev, addr, buf, buf_len); + if (ret < 0) + return ret; + } + + return 0; +} + +int stpmic1_shadow_read_byte(u8 addr, u8 *buf) +{ + return stpmic1_nvm_rw(addr, buf, 1, SHADOW_READ); +} + +int stpmic1_shadow_write_byte(u8 addr, u8 *buf) +{ + return stpmic1_nvm_rw(addr, buf, 1, SHADOW_WRITE); +} + +int stpmic1_nvm_read_byte(u8 addr, u8 *buf) +{ + return stpmic1_nvm_rw(addr, buf, 1, NVM_READ); +} + +int stpmic1_nvm_write_byte(u8 addr, u8 *buf) +{ + return stpmic1_nvm_rw(addr, buf, 1, NVM_WRITE); +} + +int stpmic1_nvm_read_all(u8 *buf, int buf_len) +{ + if (buf_len != STPMIC1_NVM_SIZE) + return -EINVAL; + + return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS, + buf, buf_len, NVM_READ); +} + +int stpmic1_nvm_write_all(u8 *buf, int buf_len) +{ + if (buf_len != STPMIC1_NVM_SIZE) + return -EINVAL; + + return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS, + buf, buf_len, NVM_WRITE); +} +#endif /* CONFIG_SPL_BUILD */ + +#ifdef CONFIG_SYSRESET +static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + struct udevice *pmic_dev; + int ret; + + if (type != SYSRESET_POWER) + return -EPROTONOSUPPORT; + + ret = uclass_get_device_by_driver(UCLASS_PMIC, + DM_GET_DRIVER(pmic_stpmic1), + &pmic_dev); + + if (ret) + return -EOPNOTSUPP; + + ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR); + if (ret < 0) + return ret; + + ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR, + ret | STPMIC1_SWOFF | STPMIC1_RREQ_EN); + if (ret < 0) + return ret; + + return -EINPROGRESS; +} + +static struct sysreset_ops stpmic1_sysreset_ops = { + .request = stpmic1_sysreset_request, +}; + +U_BOOT_DRIVER(stpmic1_sysreset) = { + .name = "stpmic1-sysreset", + .id = UCLASS_SYSRESET, + .ops = &stpmic1_sysreset_ops, +}; +#endif diff --git a/drivers/power/pmic/stpmu1.c b/drivers/power/pmic/stpmu1.c deleted file mode 100644 index 47af012..0000000 --- a/drivers/power/pmic/stpmu1.c +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -/* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - */ - -#include <common.h> -#include <dm.h> -#include <errno.h> -#include <i2c.h> -#include <power/pmic.h> -#include <power/stpmu1.h> - -#define STMPU1_NUM_OF_REGS 0x100 - -#ifndef CONFIG_SPL_BUILD -static const struct pmic_child_info stpmu1_children_info[] = { - { .prefix = "ldo", .driver = "stpmu1_ldo" }, - { .prefix = "buck", .driver = "stpmu1_buck" }, - { .prefix = "vref_ddr", .driver = "stpmu1_vref_ddr" }, - { .prefix = "pwr_sw", .driver = "stpmu1_pwr_sw" }, - { .prefix = "boost", .driver = "stpmu1_boost" }, - { }, -}; -#endif /* CONFIG_SPL_BUILD */ - -static int stpmu1_reg_count(struct udevice *dev) -{ - return STMPU1_NUM_OF_REGS; -} - -static int stpmu1_write(struct udevice *dev, uint reg, const uint8_t *buff, - int len) -{ - int ret; - - ret = dm_i2c_write(dev, reg, buff, len); - if (ret) - dev_err(dev, "%s: failed to write register %#x :%d", - __func__, reg, ret); - - return ret; -} - -static int stpmu1_read(struct udevice *dev, uint reg, uint8_t *buff, int len) -{ - int ret; - - ret = dm_i2c_read(dev, reg, buff, len); - if (ret) - dev_err(dev, "%s: failed to read register %#x : %d", - __func__, reg, ret); - - return ret; -} - -static int stpmu1_bind(struct udevice *dev) -{ -#ifndef CONFIG_SPL_BUILD - ofnode regulators_node; - int children; - - regulators_node = dev_read_subnode(dev, "regulators"); - if (!ofnode_valid(regulators_node)) { - dev_dbg(dev, "regulators subnode not found!\n"); - return -ENXIO; - } - dev_dbg(dev, "found regulators subnode\n"); - - children = pmic_bind_children(dev, regulators_node, - stpmu1_children_info); - if (!children) - dev_dbg(dev, "no child found\n"); -#endif /* CONFIG_SPL_BUILD */ - - return 0; -} - -static struct dm_pmic_ops stpmu1_ops = { - .reg_count = stpmu1_reg_count, - .read = stpmu1_read, - .write = stpmu1_write, -}; - -static const struct udevice_id stpmu1_ids[] = { - { .compatible = "st,stpmu1" }, - { } -}; - -U_BOOT_DRIVER(pmic_stpmu1) = { - .name = "stpmu1_pmic", - .id = UCLASS_PMIC, - .of_match = stpmu1_ids, - .bind = stpmu1_bind, - .ops = &stpmu1_ops, -}; diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 3ed0dd2..72dfc48 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -244,11 +244,17 @@ config DM_REGULATOR_TPS65910 regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements the get/set api for value and enable. -config DM_REGULATOR_STPMU1 - bool "Enable driver for STPMU1 regulators" - depends on DM_REGULATOR && PMIC_STPMU1 +config DM_REGULATOR_STPMIC1 + bool "Enable driver for STPMIC1 regulators" + depends on DM_REGULATOR && PMIC_STPMIC1 ---help--- - Enable support for the regulator functions of the STPMU1 PMIC. The + Enable support for the regulator functions of the STPMIC1 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 SPL_DM_REGULATOR_STPMIC1 + bool "Enable driver for STPMIC1 regulators in SPL" + depends on SPL_DM_REGULATOR && PMIC_STPMIC1 + help + Enable support for the regulator functions of the STPMIC1 PMIC in SPL. diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index f617ce7..8c1506c 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -24,4 +24,4 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP873X) += lp873x_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o -obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMU1) += stpmu1.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o diff --git a/drivers/power/regulator/pbias_regulator.c b/drivers/power/regulator/pbias_regulator.c index 4ed3c94..88dc9f2 100644 --- a/drivers/power/regulator/pbias_regulator.c +++ b/drivers/power/regulator/pbias_regulator.c @@ -238,7 +238,7 @@ static int pbias_regulator_set_value(struct udevice *dev, int uV) if (rc) return rc; - if (uV == 3000000) + if (uV == 3300000) reg |= p->vmode; else if (uV == 1800000) reg &= ~p->vmode; diff --git a/drivers/power/regulator/stpmic1.c b/drivers/power/regulator/stpmic1.c new file mode 100644 index 0000000..50ef2a2 --- /dev/null +++ b/drivers/power/regulator/stpmic1.c @@ -0,0 +1,672 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Author: Christophe Kerello <christophe.kerello@st.com> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <power/pmic.h> +#include <power/regulator.h> +#include <power/stpmic1.h> + +struct stpmic1_range { + int min_uv; + int min_sel; + int max_sel; + int step; +}; + +struct stpmic1_output { + const struct stpmic1_range *ranges; + int nbranges; +}; + +#define STPMIC1_MODE(_id, _val, _name) { \ + .id = _id, \ + .register_value = _val, \ + .name = _name, \ +} + +#define STPMIC1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \ + .min_uv = _min_uv, \ + .min_sel = _min_sel, \ + .max_sel = _max_sel, \ + .step = _step, \ +} + +#define STPMIC1_OUTPUT(_ranges, _nbranges) { \ + .ranges = _ranges, \ + .nbranges = _nbranges, \ +} + +static int stpmic1_output_find_uv(int sel, + const struct stpmic1_output *output) +{ + const struct stpmic1_range *range; + int i; + + for (i = 0, range = output->ranges; + i < output->nbranges; i++, range++) { + if (sel >= range->min_sel && sel <= range->max_sel) + return range->min_uv + + (sel - range->min_sel) * range->step; + } + + return -EINVAL; +} + +static int stpmic1_output_find_sel(int uv, + const struct stpmic1_output *output) +{ + const struct stpmic1_range *range; + int i; + + for (i = 0, range = output->ranges; + i < output->nbranges; i++, range++) { + if (uv == range->min_uv && !range->step) + return range->min_sel; + + if (uv >= range->min_uv && + uv <= range->min_uv + + (range->max_sel - range->min_sel) * range->step) + return range->min_sel + + (uv - range->min_uv) / range->step; + } + + return -EINVAL; +} + +/* + * BUCK regulators + */ + +static const struct stpmic1_range buck1_ranges[] = { + STPMIC1_RANGE(725000, 0, 4, 0), + STPMIC1_RANGE(725000, 5, 36, 25000), + STPMIC1_RANGE(1500000, 37, 63, 0), +}; + +static const struct stpmic1_range buck2_ranges[] = { + STPMIC1_RANGE(1000000, 0, 17, 0), + STPMIC1_RANGE(1050000, 18, 19, 0), + STPMIC1_RANGE(1100000, 20, 21, 0), + STPMIC1_RANGE(1150000, 22, 23, 0), + STPMIC1_RANGE(1200000, 24, 25, 0), + STPMIC1_RANGE(1250000, 26, 27, 0), + STPMIC1_RANGE(1300000, 28, 29, 0), + STPMIC1_RANGE(1350000, 30, 31, 0), + STPMIC1_RANGE(1400000, 32, 33, 0), + STPMIC1_RANGE(1450000, 34, 35, 0), + STPMIC1_RANGE(1500000, 36, 63, 0), +}; + +static const struct stpmic1_range buck3_ranges[] = { + STPMIC1_RANGE(1000000, 0, 19, 0), + STPMIC1_RANGE(1100000, 20, 23, 0), + STPMIC1_RANGE(1200000, 24, 27, 0), + STPMIC1_RANGE(1300000, 28, 31, 0), + STPMIC1_RANGE(1400000, 32, 35, 0), + STPMIC1_RANGE(1500000, 36, 55, 100000), + STPMIC1_RANGE(3400000, 56, 63, 0), +}; + +static const struct stpmic1_range buck4_ranges[] = { + STPMIC1_RANGE(600000, 0, 27, 25000), + STPMIC1_RANGE(1300000, 28, 29, 0), + STPMIC1_RANGE(1350000, 30, 31, 0), + STPMIC1_RANGE(1400000, 32, 33, 0), + STPMIC1_RANGE(1450000, 34, 35, 0), + STPMIC1_RANGE(1500000, 36, 60, 100000), + STPMIC1_RANGE(3900000, 61, 63, 0), +}; + +/* BUCK: 1,2,3,4 - voltage ranges */ +static const struct stpmic1_output buck_voltage_range[] = { + STPMIC1_OUTPUT(buck1_ranges, ARRAY_SIZE(buck1_ranges)), + STPMIC1_OUTPUT(buck2_ranges, ARRAY_SIZE(buck2_ranges)), + STPMIC1_OUTPUT(buck3_ranges, ARRAY_SIZE(buck3_ranges)), + STPMIC1_OUTPUT(buck4_ranges, ARRAY_SIZE(buck4_ranges)), +}; + +/* BUCK modes */ +static const struct dm_regulator_mode buck_modes[] = { + STPMIC1_MODE(STPMIC1_PREG_MODE_HP, STPMIC1_PREG_MODE_HP, "HP"), + STPMIC1_MODE(STPMIC1_PREG_MODE_LP, STPMIC1_PREG_MODE_LP, "LP"), +}; + +static int stpmic1_buck_get_uv(struct udevice *dev, int buck) +{ + int sel; + + sel = pmic_reg_read(dev, STPMIC1_BUCKX_MAIN_CR(buck)); + if (sel < 0) + return sel; + + sel &= STPMIC1_BUCK_VOUT_MASK; + sel >>= STPMIC1_BUCK_VOUT_SHIFT; + + return stpmic1_output_find_uv(sel, &buck_voltage_range[buck]); +} + +static int stpmic1_buck_get_value(struct udevice *dev) +{ + return stpmic1_buck_get_uv(dev->parent, dev->driver_data - 1); +} + +static int stpmic1_buck_set_value(struct udevice *dev, int uv) +{ + int sel, buck = dev->driver_data - 1; + + sel = stpmic1_output_find_sel(uv, &buck_voltage_range[buck]); + if (sel < 0) + return sel; + + return pmic_clrsetbits(dev->parent, + STPMIC1_BUCKX_MAIN_CR(buck), + STPMIC1_BUCK_VOUT_MASK, + sel << STPMIC1_BUCK_VOUT_SHIFT); +} + +static int stpmic1_buck_get_enable(struct udevice *dev) +{ + int ret; + + ret = pmic_reg_read(dev->parent, + STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1)); + if (ret < 0) + return false; + + return ret & STPMIC1_BUCK_ENA ? true : false; +} + +static int stpmic1_buck_set_enable(struct udevice *dev, bool enable) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS : + STPMIC1_DEFAULT_STOP_DELAY_MS; + int ret, uv; + + /* if regulator is already in the wanted state, nothing to do */ + if (stpmic1_buck_get_enable(dev) == enable) + return 0; + + if (enable) { + uc_pdata = dev_get_uclass_platdata(dev); + uv = stpmic1_buck_get_value(dev); + if (uv < uc_pdata->min_uV || uv > uc_pdata->max_uV) + stpmic1_buck_set_value(dev, uc_pdata->min_uV); + } + + ret = pmic_clrsetbits(dev->parent, + STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1), + STPMIC1_BUCK_ENA, enable ? STPMIC1_BUCK_ENA : 0); + mdelay(delay); + + return ret; +} + +static int stpmic1_buck_get_mode(struct udevice *dev) +{ + int ret; + + ret = pmic_reg_read(dev->parent, + STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1)); + if (ret < 0) + return ret; + + return ret & STPMIC1_BUCK_PREG_MODE ? STPMIC1_PREG_MODE_LP : + STPMIC1_PREG_MODE_HP; +} + +static int stpmic1_buck_set_mode(struct udevice *dev, int mode) +{ + return pmic_clrsetbits(dev->parent, + STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1), + STPMIC1_BUCK_PREG_MODE, + mode ? STPMIC1_BUCK_PREG_MODE : 0); +} + +static int stpmic1_buck_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_BUCK) + return -EINVAL; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_BUCK; + uc_pdata->mode = (struct dm_regulator_mode *)buck_modes; + uc_pdata->mode_count = ARRAY_SIZE(buck_modes); + + return 0; +} + +static const struct dm_regulator_ops stpmic1_buck_ops = { + .get_value = stpmic1_buck_get_value, + .set_value = stpmic1_buck_set_value, + .get_enable = stpmic1_buck_get_enable, + .set_enable = stpmic1_buck_set_enable, + .get_mode = stpmic1_buck_get_mode, + .set_mode = stpmic1_buck_set_mode, +}; + +U_BOOT_DRIVER(stpmic1_buck) = { + .name = "stpmic1_buck", + .id = UCLASS_REGULATOR, + .ops = &stpmic1_buck_ops, + .probe = stpmic1_buck_probe, +}; + +/* + * LDO regulators + */ + +static const struct stpmic1_range ldo12_ranges[] = { + STPMIC1_RANGE(1700000, 0, 7, 0), + STPMIC1_RANGE(1700000, 8, 24, 100000), + STPMIC1_RANGE(3300000, 25, 31, 0), +}; + +static const struct stpmic1_range ldo3_ranges[] = { + STPMIC1_RANGE(1700000, 0, 7, 0), + STPMIC1_RANGE(1700000, 8, 24, 100000), + STPMIC1_RANGE(3300000, 25, 30, 0), + /* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */ +}; + +static const struct stpmic1_range ldo5_ranges[] = { + STPMIC1_RANGE(1700000, 0, 7, 0), + STPMIC1_RANGE(1700000, 8, 30, 100000), + STPMIC1_RANGE(3900000, 31, 31, 0), +}; + +static const struct stpmic1_range ldo6_ranges[] = { + STPMIC1_RANGE(900000, 0, 24, 100000), + STPMIC1_RANGE(3300000, 25, 31, 0), +}; + +/* LDO: 1,2,3,4,5,6 - voltage ranges */ +static const struct stpmic1_output ldo_voltage_range[] = { + STPMIC1_OUTPUT(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)), + STPMIC1_OUTPUT(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)), + STPMIC1_OUTPUT(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)), + STPMIC1_OUTPUT(NULL, 0), + STPMIC1_OUTPUT(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)), + STPMIC1_OUTPUT(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)), +}; + +/* LDO modes */ +static const struct dm_regulator_mode ldo_modes[] = { + STPMIC1_MODE(STPMIC1_LDO_MODE_NORMAL, + STPMIC1_LDO_MODE_NORMAL, "NORMAL"), + STPMIC1_MODE(STPMIC1_LDO_MODE_BYPASS, + STPMIC1_LDO_MODE_BYPASS, "BYPASS"), + STPMIC1_MODE(STPMIC1_LDO_MODE_SINK_SOURCE, + STPMIC1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"), +}; + +static int stpmic1_ldo_get_value(struct udevice *dev) +{ + int sel, ldo = dev->driver_data - 1; + + sel = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo)); + if (sel < 0) + return sel; + + /* ldo4 => 3,3V */ + if (ldo == STPMIC1_LDO4) + return STPMIC1_LDO4_UV; + + sel &= STPMIC1_LDO12356_VOUT_MASK; + sel >>= STPMIC1_LDO12356_VOUT_SHIFT; + + /* ldo3, sel = 31 => BUCK2/2 */ + if (ldo == STPMIC1_LDO3 && sel == STPMIC1_LDO3_DDR_SEL) + return stpmic1_buck_get_uv(dev->parent, STPMIC1_BUCK2) / 2; + + return stpmic1_output_find_uv(sel, &ldo_voltage_range[ldo]); +} + +static int stpmic1_ldo_set_value(struct udevice *dev, int uv) +{ + int sel, ldo = dev->driver_data - 1; + + /* ldo4 => not possible */ + if (ldo == STPMIC1_LDO4) + return -EINVAL; + + sel = stpmic1_output_find_sel(uv, &ldo_voltage_range[ldo]); + if (sel < 0) + return sel; + + return pmic_clrsetbits(dev->parent, + STPMIC1_LDOX_MAIN_CR(ldo), + STPMIC1_LDO12356_VOUT_MASK, + sel << STPMIC1_LDO12356_VOUT_SHIFT); +} + +static int stpmic1_ldo_get_enable(struct udevice *dev) +{ + int ret; + + ret = pmic_reg_read(dev->parent, + STPMIC1_LDOX_MAIN_CR(dev->driver_data - 1)); + if (ret < 0) + return false; + + return ret & STPMIC1_LDO_ENA ? true : false; +} + +static int stpmic1_ldo_set_enable(struct udevice *dev, bool enable) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS : + STPMIC1_DEFAULT_STOP_DELAY_MS; + int ret, uv; + + /* if regulator is already in the wanted state, nothing to do */ + if (stpmic1_ldo_get_enable(dev) == enable) + return 0; + + if (enable) { + uc_pdata = dev_get_uclass_platdata(dev); + uv = stpmic1_ldo_get_value(dev); + if (uv < uc_pdata->min_uV || uv > uc_pdata->max_uV) + stpmic1_ldo_set_value(dev, uc_pdata->min_uV); + } + + ret = pmic_clrsetbits(dev->parent, + STPMIC1_LDOX_MAIN_CR(dev->driver_data - 1), + STPMIC1_LDO_ENA, enable ? STPMIC1_LDO_ENA : 0); + mdelay(delay); + + return ret; +} + +static int stpmic1_ldo_get_mode(struct udevice *dev) +{ + int ret, ldo = dev->driver_data - 1; + + if (ldo != STPMIC1_LDO3) + return -EINVAL; + + ret = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo)); + if (ret < 0) + return ret; + + if (ret & STPMIC1_LDO3_MODE) + return STPMIC1_LDO_MODE_BYPASS; + + ret &= STPMIC1_LDO12356_VOUT_MASK; + ret >>= STPMIC1_LDO12356_VOUT_SHIFT; + + return ret == STPMIC1_LDO3_DDR_SEL ? STPMIC1_LDO_MODE_SINK_SOURCE : + STPMIC1_LDO_MODE_NORMAL; +} + +static int stpmic1_ldo_set_mode(struct udevice *dev, int mode) +{ + int ret, ldo = dev->driver_data - 1; + + if (ldo != STPMIC1_LDO3) + return -EINVAL; + + ret = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo)); + if (ret < 0) + return ret; + + switch (mode) { + case STPMIC1_LDO_MODE_SINK_SOURCE: + ret &= ~STPMIC1_LDO12356_VOUT_MASK; + ret |= STPMIC1_LDO3_DDR_SEL << STPMIC1_LDO12356_VOUT_SHIFT; + case STPMIC1_LDO_MODE_NORMAL: + ret &= ~STPMIC1_LDO3_MODE; + break; + case STPMIC1_LDO_MODE_BYPASS: + ret |= STPMIC1_LDO3_MODE; + break; + } + + return pmic_reg_write(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo), ret); +} + +static int stpmic1_ldo_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_LDO) + return -EINVAL; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_LDO; + if (dev->driver_data - 1 == STPMIC1_LDO3) { + uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes; + uc_pdata->mode_count = ARRAY_SIZE(ldo_modes); + } else { + uc_pdata->mode_count = 0; + } + + return 0; +} + +static const struct dm_regulator_ops stpmic1_ldo_ops = { + .get_value = stpmic1_ldo_get_value, + .set_value = stpmic1_ldo_set_value, + .get_enable = stpmic1_ldo_get_enable, + .set_enable = stpmic1_ldo_set_enable, + .get_mode = stpmic1_ldo_get_mode, + .set_mode = stpmic1_ldo_set_mode, +}; + +U_BOOT_DRIVER(stpmic1_ldo) = { + .name = "stpmic1_ldo", + .id = UCLASS_REGULATOR, + .ops = &stpmic1_ldo_ops, + .probe = stpmic1_ldo_probe, +}; + +/* + * VREF DDR regulator + */ + +static int stpmic1_vref_ddr_get_value(struct udevice *dev) +{ + /* BUCK2/2 */ + return stpmic1_buck_get_uv(dev->parent, STPMIC1_BUCK2) / 2; +} + +static int stpmic1_vref_ddr_get_enable(struct udevice *dev) +{ + int ret; + + ret = pmic_reg_read(dev->parent, STPMIC1_REFDDR_MAIN_CR); + if (ret < 0) + return false; + + return ret & STPMIC1_VREF_ENA ? true : false; +} + +static int stpmic1_vref_ddr_set_enable(struct udevice *dev, bool enable) +{ + int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS : + STPMIC1_DEFAULT_STOP_DELAY_MS; + int ret; + + /* if regulator is already in the wanted state, nothing to do */ + if (stpmic1_vref_ddr_get_enable(dev) == enable) + return 0; + + ret = pmic_clrsetbits(dev->parent, STPMIC1_REFDDR_MAIN_CR, + STPMIC1_VREF_ENA, enable ? STPMIC1_VREF_ENA : 0); + mdelay(delay); + + return ret; +} + +static int stpmic1_vref_ddr_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_FIXED; + uc_pdata->mode_count = 0; + + return 0; +} + +static const struct dm_regulator_ops stpmic1_vref_ddr_ops = { + .get_value = stpmic1_vref_ddr_get_value, + .get_enable = stpmic1_vref_ddr_get_enable, + .set_enable = stpmic1_vref_ddr_set_enable, +}; + +U_BOOT_DRIVER(stpmic1_vref_ddr) = { + .name = "stpmic1_vref_ddr", + .id = UCLASS_REGULATOR, + .ops = &stpmic1_vref_ddr_ops, + .probe = stpmic1_vref_ddr_probe, +}; + +/* + * BOOST regulator + */ + +static int stpmic1_boost_get_enable(struct udevice *dev) +{ + int ret; + + ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR); + if (ret < 0) + return false; + + return ret & STPMIC1_BST_ON ? true : false; +} + +static int stpmic1_boost_set_enable(struct udevice *dev, bool enable) +{ + int ret; + + ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR); + if (ret < 0) + return ret; + + if (!enable && ret & STPMIC1_PWR_SW_ON) + return -EINVAL; + + /* if regulator is already in the wanted state, nothing to do */ + if (!!(ret & STPMIC1_BST_ON) == enable) + return 0; + + ret = pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR, + STPMIC1_BST_ON, + enable ? STPMIC1_BST_ON : 0); + if (enable) + mdelay(STPMIC1_USB_BOOST_START_UP_DELAY_MS); + + return ret; +} + +static int stpmic1_boost_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_FIXED; + uc_pdata->mode_count = 0; + + return 0; +} + +static const struct dm_regulator_ops stpmic1_boost_ops = { + .get_enable = stpmic1_boost_get_enable, + .set_enable = stpmic1_boost_set_enable, +}; + +U_BOOT_DRIVER(stpmic1_boost) = { + .name = "stpmic1_boost", + .id = UCLASS_REGULATOR, + .ops = &stpmic1_boost_ops, + .probe = stpmic1_boost_probe, +}; + +/* + * USB power switch + */ + +static int stpmic1_pwr_sw_get_enable(struct udevice *dev) +{ + uint mask = 1 << dev->driver_data; + int ret; + + ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR); + if (ret < 0) + return false; + + return ret & mask ? true : false; +} + +static int stpmic1_pwr_sw_set_enable(struct udevice *dev, bool enable) +{ + uint mask = 1 << dev->driver_data; + int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS : + STPMIC1_DEFAULT_STOP_DELAY_MS; + int ret; + + ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR); + if (ret < 0) + return ret; + + /* if regulator is already in the wanted state, nothing to do */ + if (!!(ret & mask) == enable) + return 0; + + /* Boost management */ + if (enable && !(ret & STPMIC1_BST_ON)) { + pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR, + STPMIC1_BST_ON, STPMIC1_BST_ON); + mdelay(STPMIC1_USB_BOOST_START_UP_DELAY_MS); + } else if (!enable && ret & STPMIC1_BST_ON && + (ret & STPMIC1_PWR_SW_ON) != STPMIC1_PWR_SW_ON) { + pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR, + STPMIC1_BST_ON, 0); + } + + ret = pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR, + mask, enable ? mask : 0); + mdelay(delay); + + return ret; +} + +static int stpmic1_pwr_sw_probe(struct udevice *dev) +{ + struct dm_regulator_uclass_platdata *uc_pdata; + + if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_PWR_SW) + return -EINVAL; + + uc_pdata = dev_get_uclass_platdata(dev); + + uc_pdata->type = REGULATOR_TYPE_FIXED; + uc_pdata->mode_count = 0; + + return 0; +} + +static const struct dm_regulator_ops stpmic1_pwr_sw_ops = { + .get_enable = stpmic1_pwr_sw_get_enable, + .set_enable = stpmic1_pwr_sw_set_enable, +}; + +U_BOOT_DRIVER(stpmic1_pwr_sw) = { + .name = "stpmic1_pwr_sw", + .id = UCLASS_REGULATOR, + .ops = &stpmic1_pwr_sw_ops, + .probe = stpmic1_pwr_sw_probe, +}; diff --git a/drivers/power/regulator/stpmu1.c b/drivers/power/regulator/stpmu1.c deleted file mode 100644 index 6eb2420..0000000 --- a/drivers/power/regulator/stpmu1.c +++ /dev/null @@ -1,671 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause -/* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - * Author: Christophe Kerello <christophe.kerello@st.com> - */ - -#include <common.h> -#include <dm.h> -#include <errno.h> -#include <power/pmic.h> -#include <power/regulator.h> -#include <power/stpmu1.h> - -struct stpmu1_range { - int min_uv; - int min_sel; - int max_sel; - int step; -}; - -struct stpmu1_output_range { - const struct stpmu1_range *ranges; - int nbranges; -}; - -#define STPMU1_MODE(_id, _val, _name) { \ - .id = _id, \ - .register_value = _val, \ - .name = _name, \ -} - -#define STPMU1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \ - .min_uv = _min_uv, \ - .min_sel = _min_sel, \ - .max_sel = _max_sel, \ - .step = _step, \ -} - -#define STPMU1_OUTPUT_RANGE(_ranges, _nbranges) { \ - .ranges = _ranges, \ - .nbranges = _nbranges, \ -} - -static int stpmu1_output_find_uv(int sel, - const struct stpmu1_output_range *output_range) -{ - const struct stpmu1_range *range; - int i; - - for (i = 0, range = output_range->ranges; - i < output_range->nbranges; i++, range++) { - if (sel >= range->min_sel && sel <= range->max_sel) - return range->min_uv + - (sel - range->min_sel) * range->step; - } - - return -EINVAL; -} - -static int stpmu1_output_find_sel(int uv, - const struct stpmu1_output_range *output_range) -{ - const struct stpmu1_range *range; - int i; - - for (i = 0, range = output_range->ranges; - i < output_range->nbranges; i++, range++) { - if (uv == range->min_uv && !range->step) - return range->min_sel; - - if (uv >= range->min_uv && - uv <= range->min_uv + - (range->max_sel - range->min_sel) * range->step) - return range->min_sel + - (uv - range->min_uv) / range->step; - } - - return -EINVAL; -} - -/* - * BUCK regulators - */ - -static const struct stpmu1_range buck1_ranges[] = { - STPMU1_RANGE(600000, 0, 30, 25000), - STPMU1_RANGE(1350000, 31, 63, 0), -}; - -static const struct stpmu1_range buck2_ranges[] = { - STPMU1_RANGE(1000000, 0, 17, 0), - STPMU1_RANGE(1050000, 18, 19, 0), - STPMU1_RANGE(1100000, 20, 21, 0), - STPMU1_RANGE(1150000, 22, 23, 0), - STPMU1_RANGE(1200000, 24, 25, 0), - STPMU1_RANGE(1250000, 26, 27, 0), - STPMU1_RANGE(1300000, 28, 29, 0), - STPMU1_RANGE(1350000, 30, 31, 0), - STPMU1_RANGE(1400000, 32, 33, 0), - STPMU1_RANGE(1450000, 34, 35, 0), - STPMU1_RANGE(1500000, 36, 63, 0), -}; - -static const struct stpmu1_range buck3_ranges[] = { - STPMU1_RANGE(1000000, 0, 19, 0), - STPMU1_RANGE(1100000, 20, 23, 0), - STPMU1_RANGE(1200000, 24, 27, 0), - STPMU1_RANGE(1300000, 28, 31, 0), - STPMU1_RANGE(1400000, 32, 35, 0), - STPMU1_RANGE(1500000, 36, 55, 100000), - STPMU1_RANGE(3400000, 56, 63, 0), -}; - -static const struct stpmu1_range buck4_ranges[] = { - STPMU1_RANGE(600000, 0, 27, 25000), - STPMU1_RANGE(1300000, 28, 29, 0), - STPMU1_RANGE(1350000, 30, 31, 0), - STPMU1_RANGE(1400000, 32, 33, 0), - STPMU1_RANGE(1450000, 34, 35, 0), - STPMU1_RANGE(1500000, 36, 60, 100000), - STPMU1_RANGE(3900000, 61, 63, 0), -}; - -/* BUCK: 1,2,3,4 - voltage ranges */ -static const struct stpmu1_output_range buck_voltage_range[] = { - STPMU1_OUTPUT_RANGE(buck1_ranges, ARRAY_SIZE(buck1_ranges)), - STPMU1_OUTPUT_RANGE(buck2_ranges, ARRAY_SIZE(buck2_ranges)), - STPMU1_OUTPUT_RANGE(buck3_ranges, ARRAY_SIZE(buck3_ranges)), - STPMU1_OUTPUT_RANGE(buck4_ranges, ARRAY_SIZE(buck4_ranges)), -}; - -/* BUCK modes */ -static const struct dm_regulator_mode buck_modes[] = { - STPMU1_MODE(STPMU1_BUCK_MODE_HP, STPMU1_BUCK_MODE_HP, "HP"), - STPMU1_MODE(STPMU1_BUCK_MODE_LP, STPMU1_BUCK_MODE_LP, "LP"), -}; - -static int stpmu1_buck_get_uv(struct udevice *dev, int buck) -{ - int sel; - - sel = pmic_reg_read(dev, STPMU1_BUCKX_CTRL_REG(buck)); - if (sel < 0) - return sel; - - sel &= STPMU1_BUCK_OUTPUT_MASK; - sel >>= STPMU1_BUCK_OUTPUT_SHIFT; - - return stpmu1_output_find_uv(sel, &buck_voltage_range[buck]); -} - -static int stpmu1_buck_get_value(struct udevice *dev) -{ - return stpmu1_buck_get_uv(dev->parent, dev->driver_data - 1); -} - -static int stpmu1_buck_set_value(struct udevice *dev, int uv) -{ - int sel, buck = dev->driver_data - 1; - - sel = stpmu1_output_find_sel(uv, &buck_voltage_range[buck]); - if (sel < 0) - return sel; - - return pmic_clrsetbits(dev->parent, - STPMU1_BUCKX_CTRL_REG(buck), - STPMU1_BUCK_OUTPUT_MASK, - sel << STPMU1_BUCK_OUTPUT_SHIFT); -} - -static int stpmu1_buck_get_enable(struct udevice *dev) -{ - int ret; - - ret = pmic_reg_read(dev->parent, - STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1)); - if (ret < 0) - return false; - - return ret & STPMU1_BUCK_EN ? true : false; -} - -static int stpmu1_buck_set_enable(struct udevice *dev, bool enable) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS : - STPMU1_DEFAULT_STOP_DELAY_MS; - int ret, uv; - - /* if regulator is already in the wanted state, nothing to do */ - if (stpmu1_buck_get_enable(dev) == enable) - return 0; - - if (enable) { - uc_pdata = dev_get_uclass_platdata(dev); - uv = stpmu1_buck_get_value(dev); - if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV)) - stpmu1_buck_set_value(dev, uc_pdata->min_uV); - } - - ret = pmic_clrsetbits(dev->parent, - STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1), - STPMU1_BUCK_EN, enable ? STPMU1_BUCK_EN : 0); - mdelay(delay); - - return ret; -} - -static int stpmu1_buck_get_mode(struct udevice *dev) -{ - int ret; - - ret = pmic_reg_read(dev->parent, - STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1)); - if (ret < 0) - return ret; - - return ret & STPMU1_BUCK_MODE ? STPMU1_BUCK_MODE_LP : - STPMU1_BUCK_MODE_HP; -} - -static int stpmu1_buck_set_mode(struct udevice *dev, int mode) -{ - return pmic_clrsetbits(dev->parent, - STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1), - STPMU1_BUCK_MODE, - mode ? STPMU1_BUCK_MODE : 0); -} - -static int stpmu1_buck_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - if (!dev->driver_data || dev->driver_data > STPMU1_MAX_BUCK) - return -EINVAL; - - uc_pdata = dev_get_uclass_platdata(dev); - - uc_pdata->type = REGULATOR_TYPE_BUCK; - uc_pdata->mode = (struct dm_regulator_mode *)buck_modes; - uc_pdata->mode_count = ARRAY_SIZE(buck_modes); - - return 0; -} - -static const struct dm_regulator_ops stpmu1_buck_ops = { - .get_value = stpmu1_buck_get_value, - .set_value = stpmu1_buck_set_value, - .get_enable = stpmu1_buck_get_enable, - .set_enable = stpmu1_buck_set_enable, - .get_mode = stpmu1_buck_get_mode, - .set_mode = stpmu1_buck_set_mode, -}; - -U_BOOT_DRIVER(stpmu1_buck) = { - .name = "stpmu1_buck", - .id = UCLASS_REGULATOR, - .ops = &stpmu1_buck_ops, - .probe = stpmu1_buck_probe, -}; - -/* - * LDO regulators - */ - -static const struct stpmu1_range ldo12_ranges[] = { - STPMU1_RANGE(1700000, 0, 7, 0), - STPMU1_RANGE(1700000, 8, 24, 100000), - STPMU1_RANGE(3300000, 25, 31, 0), -}; - -static const struct stpmu1_range ldo3_ranges[] = { - STPMU1_RANGE(1700000, 0, 7, 0), - STPMU1_RANGE(1700000, 8, 24, 100000), - STPMU1_RANGE(3300000, 25, 30, 0), - /* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */ -}; - -static const struct stpmu1_range ldo5_ranges[] = { - STPMU1_RANGE(1700000, 0, 7, 0), - STPMU1_RANGE(1700000, 8, 30, 100000), - STPMU1_RANGE(3900000, 31, 31, 0), -}; - -static const struct stpmu1_range ldo6_ranges[] = { - STPMU1_RANGE(900000, 0, 24, 100000), - STPMU1_RANGE(3300000, 25, 31, 0), -}; - -/* LDO: 1,2,3,4,5,6 - voltage ranges */ -static const struct stpmu1_output_range ldo_voltage_range[] = { - STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)), - STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)), - STPMU1_OUTPUT_RANGE(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)), - STPMU1_OUTPUT_RANGE(NULL, 0), - STPMU1_OUTPUT_RANGE(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)), - STPMU1_OUTPUT_RANGE(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)), -}; - -/* LDO modes */ -static const struct dm_regulator_mode ldo_modes[] = { - STPMU1_MODE(STPMU1_LDO_MODE_NORMAL, - STPMU1_LDO_MODE_NORMAL, "NORMAL"), - STPMU1_MODE(STPMU1_LDO_MODE_BYPASS, - STPMU1_LDO_MODE_BYPASS, "BYPASS"), - STPMU1_MODE(STPMU1_LDO_MODE_SINK_SOURCE, - STPMU1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"), -}; - -static int stpmu1_ldo_get_value(struct udevice *dev) -{ - int sel, ldo = dev->driver_data - 1; - - sel = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo)); - if (sel < 0) - return sel; - - /* ldo4 => 3,3V */ - if (ldo == STPMU1_LDO4) - return STPMU1_LDO4_UV; - - sel &= STPMU1_LDO12356_OUTPUT_MASK; - sel >>= STPMU1_LDO12356_OUTPUT_SHIFT; - - /* ldo3, sel = 31 => BUCK2/2 */ - if (ldo == STPMU1_LDO3 && sel == STPMU1_LDO3_DDR_SEL) - return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2; - - return stpmu1_output_find_uv(sel, &ldo_voltage_range[ldo]); -} - -static int stpmu1_ldo_set_value(struct udevice *dev, int uv) -{ - int sel, ldo = dev->driver_data - 1; - - /* ldo4 => not possible */ - if (ldo == STPMU1_LDO4) - return -EINVAL; - - sel = stpmu1_output_find_sel(uv, &ldo_voltage_range[ldo]); - if (sel < 0) - return sel; - - return pmic_clrsetbits(dev->parent, - STPMU1_LDOX_CTRL_REG(ldo), - STPMU1_LDO12356_OUTPUT_MASK, - sel << STPMU1_LDO12356_OUTPUT_SHIFT); -} - -static int stpmu1_ldo_get_enable(struct udevice *dev) -{ - int ret; - - ret = pmic_reg_read(dev->parent, - STPMU1_LDOX_CTRL_REG(dev->driver_data - 1)); - if (ret < 0) - return false; - - return ret & STPMU1_LDO_EN ? true : false; -} - -static int stpmu1_ldo_set_enable(struct udevice *dev, bool enable) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS : - STPMU1_DEFAULT_STOP_DELAY_MS; - int ret, uv; - - /* if regulator is already in the wanted state, nothing to do */ - if (stpmu1_ldo_get_enable(dev) == enable) - return 0; - - if (enable) { - uc_pdata = dev_get_uclass_platdata(dev); - uv = stpmu1_ldo_get_value(dev); - if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV)) - stpmu1_ldo_set_value(dev, uc_pdata->min_uV); - } - - ret = pmic_clrsetbits(dev->parent, - STPMU1_LDOX_CTRL_REG(dev->driver_data - 1), - STPMU1_LDO_EN, enable ? STPMU1_LDO_EN : 0); - mdelay(delay); - - return ret; -} - -static int stpmu1_ldo_get_mode(struct udevice *dev) -{ - int ret, ldo = dev->driver_data - 1; - - if (ldo != STPMU1_LDO3) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo)); - if (ret < 0) - return ret; - - if (ret & STPMU1_LDO3_MODE) - return STPMU1_LDO_MODE_BYPASS; - - ret &= STPMU1_LDO12356_OUTPUT_MASK; - ret >>= STPMU1_LDO12356_OUTPUT_SHIFT; - - return ret == STPMU1_LDO3_DDR_SEL ? STPMU1_LDO_MODE_SINK_SOURCE : - STPMU1_LDO_MODE_NORMAL; -} - -static int stpmu1_ldo_set_mode(struct udevice *dev, int mode) -{ - int ret, ldo = dev->driver_data - 1; - - if (ldo != STPMU1_LDO3) - return -EINVAL; - - ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo)); - if (ret < 0) - return ret; - - switch (mode) { - case STPMU1_LDO_MODE_SINK_SOURCE: - ret &= ~STPMU1_LDO12356_OUTPUT_MASK; - ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT; - case STPMU1_LDO_MODE_NORMAL: - ret &= ~STPMU1_LDO3_MODE; - break; - case STPMU1_LDO_MODE_BYPASS: - ret |= STPMU1_LDO3_MODE; - break; - } - - return pmic_reg_write(dev->parent, STPMU1_LDOX_CTRL_REG(ldo), ret); -} - -static int stpmu1_ldo_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - if (!dev->driver_data || dev->driver_data > STPMU1_MAX_LDO) - return -EINVAL; - - uc_pdata = dev_get_uclass_platdata(dev); - - uc_pdata->type = REGULATOR_TYPE_LDO; - if (dev->driver_data - 1 == STPMU1_LDO3) { - uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes; - uc_pdata->mode_count = ARRAY_SIZE(ldo_modes); - } else { - uc_pdata->mode_count = 0; - } - - return 0; -} - -static const struct dm_regulator_ops stpmu1_ldo_ops = { - .get_value = stpmu1_ldo_get_value, - .set_value = stpmu1_ldo_set_value, - .get_enable = stpmu1_ldo_get_enable, - .set_enable = stpmu1_ldo_set_enable, - .get_mode = stpmu1_ldo_get_mode, - .set_mode = stpmu1_ldo_set_mode, -}; - -U_BOOT_DRIVER(stpmu1_ldo) = { - .name = "stpmu1_ldo", - .id = UCLASS_REGULATOR, - .ops = &stpmu1_ldo_ops, - .probe = stpmu1_ldo_probe, -}; - -/* - * VREF DDR regulator - */ - -static int stpmu1_vref_ddr_get_value(struct udevice *dev) -{ - /* BUCK2/2 */ - return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2; -} - -static int stpmu1_vref_ddr_get_enable(struct udevice *dev) -{ - int ret; - - ret = pmic_reg_read(dev->parent, STPMU1_VREF_CTRL_REG); - if (ret < 0) - return false; - - return ret & STPMU1_VREF_EN ? true : false; -} - -static int stpmu1_vref_ddr_set_enable(struct udevice *dev, bool enable) -{ - int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS : - STPMU1_DEFAULT_STOP_DELAY_MS; - int ret; - - /* if regulator is already in the wanted state, nothing to do */ - if (stpmu1_vref_ddr_get_enable(dev) == enable) - return 0; - - ret = pmic_clrsetbits(dev->parent, STPMU1_VREF_CTRL_REG, - STPMU1_VREF_EN, enable ? STPMU1_VREF_EN : 0); - mdelay(delay); - - return ret; -} - -static int stpmu1_vref_ddr_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - uc_pdata = dev_get_uclass_platdata(dev); - - uc_pdata->type = REGULATOR_TYPE_FIXED; - uc_pdata->mode_count = 0; - - return 0; -} - -static const struct dm_regulator_ops stpmu1_vref_ddr_ops = { - .get_value = stpmu1_vref_ddr_get_value, - .get_enable = stpmu1_vref_ddr_get_enable, - .set_enable = stpmu1_vref_ddr_set_enable, -}; - -U_BOOT_DRIVER(stpmu1_vref_ddr) = { - .name = "stpmu1_vref_ddr", - .id = UCLASS_REGULATOR, - .ops = &stpmu1_vref_ddr_ops, - .probe = stpmu1_vref_ddr_probe, -}; - -/* - * BOOST regulator - */ - -static int stpmu1_boost_get_enable(struct udevice *dev) -{ - int ret; - - ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); - if (ret < 0) - return false; - - return ret & STPMU1_USB_BOOST_EN ? true : false; -} - -static int stpmu1_boost_set_enable(struct udevice *dev, bool enable) -{ - int ret; - - ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); - if (ret < 0) - return ret; - - if (!enable && ret & STPMU1_USB_PWR_SW_EN) - return -EINVAL; - - /* if regulator is already in the wanted state, nothing to do */ - if (!!(ret & STPMU1_USB_BOOST_EN) == enable) - return 0; - - ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, - STPMU1_USB_BOOST_EN, - enable ? STPMU1_USB_BOOST_EN : 0); - if (enable) - mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS); - - return ret; -} - -static int stpmu1_boost_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - uc_pdata = dev_get_uclass_platdata(dev); - - uc_pdata->type = REGULATOR_TYPE_FIXED; - uc_pdata->mode_count = 0; - - return 0; -} - -static const struct dm_regulator_ops stpmu1_boost_ops = { - .get_enable = stpmu1_boost_get_enable, - .set_enable = stpmu1_boost_set_enable, -}; - -U_BOOT_DRIVER(stpmu1_boost) = { - .name = "stpmu1_boost", - .id = UCLASS_REGULATOR, - .ops = &stpmu1_boost_ops, - .probe = stpmu1_boost_probe, -}; - -/* - * USB power switch - */ - -static int stpmu1_pwr_sw_get_enable(struct udevice *dev) -{ - uint mask = 1 << dev->driver_data; - int ret; - - ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); - if (ret < 0) - return false; - - return ret & mask ? true : false; -} - -static int stpmu1_pwr_sw_set_enable(struct udevice *dev, bool enable) -{ - uint mask = 1 << dev->driver_data; - int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS : - STPMU1_DEFAULT_STOP_DELAY_MS; - int ret; - - ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG); - if (ret < 0) - return ret; - - /* if regulator is already in the wanted state, nothing to do */ - if (!!(ret & mask) == enable) - return 0; - - /* Boost management */ - if (enable && !(ret & STPMU1_USB_BOOST_EN)) { - pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, - STPMU1_USB_BOOST_EN, STPMU1_USB_BOOST_EN); - mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS); - } else if (!enable && ret & STPMU1_USB_BOOST_EN && - (ret & STPMU1_USB_PWR_SW_EN) != STPMU1_USB_PWR_SW_EN) { - pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, - STPMU1_USB_BOOST_EN, 0); - } - - ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG, - mask, enable ? mask : 0); - mdelay(delay); - - return ret; -} - -static int stpmu1_pwr_sw_probe(struct udevice *dev) -{ - struct dm_regulator_uclass_platdata *uc_pdata; - - if (!dev->driver_data || dev->driver_data > STPMU1_MAX_PWR_SW) - return -EINVAL; - - uc_pdata = dev_get_uclass_platdata(dev); - - uc_pdata->type = REGULATOR_TYPE_FIXED; - uc_pdata->mode_count = 0; - - return 0; -} - -static const struct dm_regulator_ops stpmu1_pwr_sw_ops = { - .get_enable = stpmu1_pwr_sw_get_enable, - .set_enable = stpmu1_pwr_sw_set_enable, -}; - -U_BOOT_DRIVER(stpmu1_pwr_sw) = { - .name = "stpmu1_pwr_sw", - .id = UCLASS_REGULATOR, - .ops = &stpmu1_pwr_sw_ops, - .probe = stpmu1_pwr_sw_probe, -}; diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c index bd497a3..e45a3b2 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ram.c +++ b/drivers/ram/stm32mp1/stm32mp1_ram.c @@ -157,7 +157,8 @@ static int stm32mp1_ddr_probe(struct udevice *dev) priv->info.base = STM32_DDR_BASE; -#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) +#if !defined(CONFIG_STM32MP1_TRUSTED) && \ + (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) priv->info.size = 0; return stm32mp1_ddr_setup(dev); #else diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig new file mode 100644 index 0000000..7b4e4d6 --- /dev/null +++ b/drivers/soc/Kconfig @@ -0,0 +1,5 @@ +menu "SOC (System On Chip) specific Drivers" + +source "drivers/soc/ti/Kconfig" + +endmenu diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 42037f9..ce253b7 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -2,4 +2,4 @@ # # Makefile for the U-Boot SOC specific device drivers. -obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ +obj-$(CONFIG_SOC_TI) += ti/ diff --git a/drivers/soc/keystone/Makefile b/drivers/soc/keystone/Makefile deleted file mode 100644 index dfebb14..0000000 --- a/drivers/soc/keystone/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ - -obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig new file mode 100644 index 0000000..e4f8834 --- /dev/null +++ b/drivers/soc/ti/Kconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0+ + +menuconfig SOC_TI + bool "TI SOC drivers support" + +if SOC_TI + +config TI_K3_NAVSS_RINGACC + bool "K3 Ring accelerator Sub System" + depends on ARCH_K3 + select MISC + help + Say y here to support the K3 AM65x Ring accelerator module. + The Ring Accelerator (RINGACC or RA) provides hardware acceleration + to enable straightforward passing of work between a producer + and a consumer. There is one RINGACC module per NAVSS on TI AM65x SoCs + If unsure, say N. + +config TI_KEYSTONE_SERDES + bool "Keystone SerDes driver for ethernet" + depends on ARCH_KEYSTONE + help + SerDes driver for Keystone SoC used for ethernet support on TI + K2 platforms. + +endif # SOC_TI diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile new file mode 100644 index 0000000..4ec04ee --- /dev/null +++ b/drivers/soc/ti/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_TI_K3_NAVSS_RINGACC) += k3-navss-ringacc.o +obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o diff --git a/drivers/soc/ti/k3-navss-ringacc.c b/drivers/soc/ti/k3-navss-ringacc.c new file mode 100644 index 0000000..fcb84f7 --- /dev/null +++ b/drivers/soc/ti/k3-navss-ringacc.c @@ -0,0 +1,1057 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * TI K3 AM65x NAVSS Ring accelerator Manager (RA) subsystem driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + */ + +#include <common.h> +#include <asm/io.h> +#include <malloc.h> +#include <asm/dma-mapping.h> +#include <asm/bitops.h> +#include <dm.h> +#include <dm/read.h> +#include <dm/uclass.h> +#include <linux/compat.h> +#include <linux/soc/ti/k3-navss-ringacc.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +#define set_bit(bit, bitmap) __set_bit(bit, bitmap) +#define clear_bit(bit, bitmap) __clear_bit(bit, bitmap) +#define dma_free_coherent(dev, size, cpu_addr, dma_handle) \ + dma_free_coherent(cpu_addr) +#define dma_zalloc_coherent(dev, size, dma_handle, flag) \ +({ \ + void *ring_mem_virt; \ + ring_mem_virt = dma_alloc_coherent((size), \ + (unsigned long *)(dma_handle)); \ + if (ring_mem_virt) \ + memset(ring_mem_virt, 0, (size)); \ + ring_mem_virt; \ +}) + +static LIST_HEAD(k3_nav_ringacc_list); + +static void ringacc_writel(u32 v, void __iomem *reg) +{ + pr_debug("WRITEL(32): v(%08X)-->reg(%p)\n", v, reg); + writel(v, reg); +} + +static u32 ringacc_readl(void __iomem *reg) +{ + u32 v; + + v = readl(reg); + pr_debug("READL(32): v(%08X)<--reg(%p)\n", v, reg); + return v; +} + +#define KNAV_RINGACC_CFG_RING_SIZE_ELCNT_MASK GENMASK(19, 0) + +/** + * struct k3_nav_ring_rt_regs - The RA Control/Status Registers region + */ +struct k3_nav_ring_rt_regs { + u32 resv_16[4]; + u32 db; /* RT Ring N Doorbell Register */ + u32 resv_4[1]; + u32 occ; /* RT Ring N Occupancy Register */ + u32 indx; /* RT Ring N Current Index Register */ + u32 hwocc; /* RT Ring N Hardware Occupancy Register */ + u32 hwindx; /* RT Ring N Current Index Register */ +}; + +#define KNAV_RINGACC_RT_REGS_STEP 0x1000 + +/** + * struct k3_nav_ring_fifo_regs - The Ring Accelerator Queues Registers region + */ +struct k3_nav_ring_fifo_regs { + u32 head_data[128]; /* Ring Head Entry Data Registers */ + u32 tail_data[128]; /* Ring Tail Entry Data Registers */ + u32 peek_head_data[128]; /* Ring Peek Head Entry Data Regs */ + u32 peek_tail_data[128]; /* Ring Peek Tail Entry Data Regs */ +}; + +/** + * struct k3_ringacc_proxy_gcfg_regs - RA Proxy Global Config MMIO Region + */ +struct k3_ringacc_proxy_gcfg_regs { + u32 revision; /* Revision Register */ + u32 config; /* Config Register */ +}; + +#define K3_RINGACC_PROXY_CFG_THREADS_MASK GENMASK(15, 0) + +/** + * struct k3_ringacc_proxy_target_regs - RA Proxy Datapath MMIO Region + */ +struct k3_ringacc_proxy_target_regs { + u32 control; /* Proxy Control Register */ + u32 status; /* Proxy Status Register */ + u8 resv_512[504]; + u32 data[128]; /* Proxy Data Register */ +}; + +#define K3_RINGACC_PROXY_TARGET_STEP 0x1000 +#define K3_RINGACC_PROXY_NOT_USED (-1) + +enum k3_ringacc_proxy_access_mode { + PROXY_ACCESS_MODE_HEAD = 0, + PROXY_ACCESS_MODE_TAIL = 1, + PROXY_ACCESS_MODE_PEEK_HEAD = 2, + PROXY_ACCESS_MODE_PEEK_TAIL = 3, +}; + +#define KNAV_RINGACC_FIFO_WINDOW_SIZE_BYTES (512U) +#define KNAV_RINGACC_FIFO_REGS_STEP 0x1000 +#define KNAV_RINGACC_MAX_DB_RING_CNT (127U) + +/** + * struct k3_nav_ring_ops - Ring operations + */ +struct k3_nav_ring_ops { + int (*push_tail)(struct k3_nav_ring *ring, void *elm); + int (*push_head)(struct k3_nav_ring *ring, void *elm); + int (*pop_tail)(struct k3_nav_ring *ring, void *elm); + int (*pop_head)(struct k3_nav_ring *ring, void *elm); +}; + +/** + * struct k3_nav_ring - RA Ring descriptor + * + * @rt - Ring control/status registers + * @fifos - Ring queues registers + * @proxy - Ring Proxy Datapath registers + * @ring_mem_dma - Ring buffer dma address + * @ring_mem_virt - Ring buffer virt address + * @ops - Ring operations + * @size - Ring size in elements + * @elm_size - Size of the ring element + * @mode - Ring mode + * @flags - flags + * @free - Number of free elements + * @occ - Ring occupancy + * @windex - Write index (only for @K3_NAV_RINGACC_RING_MODE_RING) + * @rindex - Read index (only for @K3_NAV_RINGACC_RING_MODE_RING) + * @ring_id - Ring Id + * @parent - Pointer on struct @k3_nav_ringacc + * @use_count - Use count for shared rings + * @proxy_id - RA Ring Proxy Id (only if @K3_NAV_RINGACC_RING_USE_PROXY) + */ +struct k3_nav_ring { + struct k3_nav_ring_rt_regs __iomem *rt; + struct k3_nav_ring_fifo_regs __iomem *fifos; + struct k3_ringacc_proxy_target_regs __iomem *proxy; + dma_addr_t ring_mem_dma; + void *ring_mem_virt; + struct k3_nav_ring_ops *ops; + u32 size; + enum k3_nav_ring_size elm_size; + enum k3_nav_ring_mode mode; + u32 flags; +#define KNAV_RING_FLAG_BUSY BIT(1) +#define K3_NAV_RING_FLAG_SHARED BIT(2) + u32 free; + u32 occ; + u32 windex; + u32 rindex; + u32 ring_id; + struct k3_nav_ringacc *parent; + u32 use_count; + int proxy_id; +}; + +/** + * struct k3_nav_ringacc - Rings accelerator descriptor + * + * @dev - pointer on RA device + * @proxy_gcfg - RA proxy global config registers + * @proxy_target_base - RA proxy datapath region + * @num_rings - number of ring in RA + * @rm_gp_range - general purpose rings range from tisci + * @dma_ring_reset_quirk - DMA reset w/a enable + * @num_proxies - number of RA proxies + * @rings - array of rings descriptors (struct @k3_nav_ring) + * @list - list of RAs in the system + * @tisci - pointer ti-sci handle + * @tisci_ring_ops - ti-sci rings ops + * @tisci_dev_id - ti-sci device id + */ +struct k3_nav_ringacc { + struct udevice *dev; + struct k3_ringacc_proxy_gcfg_regs __iomem *proxy_gcfg; + void __iomem *proxy_target_base; + u32 num_rings; /* number of rings in Ringacc module */ + unsigned long *rings_inuse; + struct ti_sci_resource *rm_gp_range; + bool dma_ring_reset_quirk; + u32 num_proxies; + unsigned long *proxy_inuse; + + struct k3_nav_ring *rings; + struct list_head list; + + const struct ti_sci_handle *tisci; + const struct ti_sci_rm_ringacc_ops *tisci_ring_ops; + u32 tisci_dev_id; +}; + +static long k3_nav_ringacc_ring_get_fifo_pos(struct k3_nav_ring *ring) +{ + return KNAV_RINGACC_FIFO_WINDOW_SIZE_BYTES - + (4 << ring->elm_size); +} + +static void *k3_nav_ringacc_get_elm_addr(struct k3_nav_ring *ring, u32 idx) +{ + return (idx * (4 << ring->elm_size) + ring->ring_mem_virt); +} + +static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem); +static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem); + +static struct k3_nav_ring_ops k3_nav_mode_ring_ops = { + .push_tail = k3_nav_ringacc_ring_push_mem, + .pop_head = k3_nav_ringacc_ring_pop_mem, +}; + +static int k3_nav_ringacc_ring_push_io(struct k3_nav_ring *ring, void *elem); +static int k3_nav_ringacc_ring_pop_io(struct k3_nav_ring *ring, void *elem); +static int k3_nav_ringacc_ring_push_head_io(struct k3_nav_ring *ring, + void *elem); +static int k3_nav_ringacc_ring_pop_tail_io(struct k3_nav_ring *ring, + void *elem); + +static struct k3_nav_ring_ops k3_nav_mode_msg_ops = { + .push_tail = k3_nav_ringacc_ring_push_io, + .push_head = k3_nav_ringacc_ring_push_head_io, + .pop_tail = k3_nav_ringacc_ring_pop_tail_io, + .pop_head = k3_nav_ringacc_ring_pop_io, +}; + +static int k3_ringacc_ring_push_head_proxy(struct k3_nav_ring *ring, + void *elem); +static int k3_ringacc_ring_push_tail_proxy(struct k3_nav_ring *ring, + void *elem); +static int k3_ringacc_ring_pop_head_proxy(struct k3_nav_ring *ring, void *elem); +static int k3_ringacc_ring_pop_tail_proxy(struct k3_nav_ring *ring, void *elem); + +static struct k3_nav_ring_ops k3_nav_mode_proxy_ops = { + .push_tail = k3_ringacc_ring_push_tail_proxy, + .push_head = k3_ringacc_ring_push_head_proxy, + .pop_tail = k3_ringacc_ring_pop_tail_proxy, + .pop_head = k3_ringacc_ring_pop_head_proxy, +}; + +struct udevice *k3_nav_ringacc_get_dev(struct k3_nav_ringacc *ringacc) +{ + return ringacc->dev; +} + +struct k3_nav_ring *k3_nav_ringacc_request_ring(struct k3_nav_ringacc *ringacc, + int id, u32 flags) +{ + int proxy_id = K3_RINGACC_PROXY_NOT_USED; + + if (id == K3_NAV_RINGACC_RING_ID_ANY) { + /* Request for any general purpose ring */ + struct ti_sci_resource_desc *gp_rings = + &ringacc->rm_gp_range->desc[0]; + unsigned long size; + + size = gp_rings->start + gp_rings->num; + id = find_next_zero_bit(ringacc->rings_inuse, + size, gp_rings->start); + if (id == size) + goto error; + } else if (id < 0) { + goto error; + } + + if (test_bit(id, ringacc->rings_inuse) && + !(ringacc->rings[id].flags & K3_NAV_RING_FLAG_SHARED)) + goto error; + else if (ringacc->rings[id].flags & K3_NAV_RING_FLAG_SHARED) + goto out; + + if (flags & K3_NAV_RINGACC_RING_USE_PROXY) { + proxy_id = find_next_zero_bit(ringacc->proxy_inuse, + ringacc->num_proxies, 0); + if (proxy_id == ringacc->num_proxies) + goto error; + } + + if (!try_module_get(ringacc->dev->driver->owner)) + goto error; + + if (proxy_id != K3_RINGACC_PROXY_NOT_USED) { + set_bit(proxy_id, ringacc->proxy_inuse); + ringacc->rings[id].proxy_id = proxy_id; + pr_debug("Giving ring#%d proxy#%d\n", + id, proxy_id); + } else { + pr_debug("Giving ring#%d\n", id); + } + + set_bit(id, ringacc->rings_inuse); +out: + ringacc->rings[id].use_count++; + return &ringacc->rings[id]; + +error: + return NULL; +} + +static void k3_ringacc_ring_reset_sci(struct k3_nav_ring *ring) +{ + struct k3_nav_ringacc *ringacc = ring->parent; + int ret; + + ret = ringacc->tisci_ring_ops->config( + ringacc->tisci, + TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID, + ringacc->tisci_dev_id, + ring->ring_id, + 0, + 0, + ring->size, + 0, + 0, + 0); + if (ret) + dev_err(ringacc->dev, "TISCI reset ring fail (%d) ring_idx %d\n", + ret, ring->ring_id); +} + +void k3_nav_ringacc_ring_reset(struct k3_nav_ring *ring) +{ + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return; + + ring->occ = 0; + ring->free = 0; + ring->rindex = 0; + ring->windex = 0; + + k3_ringacc_ring_reset_sci(ring); +} + +static void k3_ringacc_ring_reconfig_qmode_sci(struct k3_nav_ring *ring, + enum k3_nav_ring_mode mode) +{ + struct k3_nav_ringacc *ringacc = ring->parent; + int ret; + + ret = ringacc->tisci_ring_ops->config( + ringacc->tisci, + TI_SCI_MSG_VALUE_RM_RING_MODE_VALID, + ringacc->tisci_dev_id, + ring->ring_id, + 0, + 0, + 0, + mode, + 0, + 0); + if (ret) + dev_err(ringacc->dev, "TISCI reconf qmode fail (%d) ring_idx %d\n", + ret, ring->ring_id); +} + +void k3_nav_ringacc_ring_reset_dma(struct k3_nav_ring *ring, u32 occ) +{ + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return; + + if (!ring->parent->dma_ring_reset_quirk) + return; + + if (!occ) + occ = ringacc_readl(&ring->rt->occ); + + if (occ) { + u32 db_ring_cnt, db_ring_cnt_cur; + + pr_debug("%s %u occ: %u\n", __func__, + ring->ring_id, occ); + /* 2. Reset the ring */ + k3_ringacc_ring_reset_sci(ring); + + /* + * 3. Setup the ring in ring/doorbell mode + * (if not already in this mode) + */ + if (ring->mode != K3_NAV_RINGACC_RING_MODE_RING) + k3_ringacc_ring_reconfig_qmode_sci( + ring, K3_NAV_RINGACC_RING_MODE_RING); + /* + * 4. Ring the doorbell 2**22 – ringOcc times. + * This will wrap the internal UDMAP ring state occupancy + * counter (which is 21-bits wide) to 0. + */ + db_ring_cnt = (1U << 22) - occ; + + while (db_ring_cnt != 0) { + /* + * Ring the doorbell with the maximum count each + * iteration if possible to minimize the total + * of writes + */ + if (db_ring_cnt > KNAV_RINGACC_MAX_DB_RING_CNT) + db_ring_cnt_cur = KNAV_RINGACC_MAX_DB_RING_CNT; + else + db_ring_cnt_cur = db_ring_cnt; + + writel(db_ring_cnt_cur, &ring->rt->db); + db_ring_cnt -= db_ring_cnt_cur; + } + + /* 5. Restore the original ring mode (if not ring mode) */ + if (ring->mode != K3_NAV_RINGACC_RING_MODE_RING) + k3_ringacc_ring_reconfig_qmode_sci(ring, ring->mode); + } + + /* 2. Reset the ring */ + k3_nav_ringacc_ring_reset(ring); +} + +static void k3_ringacc_ring_free_sci(struct k3_nav_ring *ring) +{ + struct k3_nav_ringacc *ringacc = ring->parent; + int ret; + + ret = ringacc->tisci_ring_ops->config( + ringacc->tisci, + TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER, + ringacc->tisci_dev_id, + ring->ring_id, + 0, + 0, + 0, + 0, + 0, + 0); + if (ret) + dev_err(ringacc->dev, "TISCI ring free fail (%d) ring_idx %d\n", + ret, ring->ring_id); +} + +int k3_nav_ringacc_ring_free(struct k3_nav_ring *ring) +{ + struct k3_nav_ringacc *ringacc; + + if (!ring) + return -EINVAL; + + ringacc = ring->parent; + + pr_debug("%s flags: 0x%08x\n", __func__, ring->flags); + + if (!test_bit(ring->ring_id, ringacc->rings_inuse)) + return -EINVAL; + + if (--ring->use_count) + goto out; + + if (!(ring->flags & KNAV_RING_FLAG_BUSY)) + goto no_init; + + k3_ringacc_ring_free_sci(ring); + + dma_free_coherent(ringacc->dev, + ring->size * (4 << ring->elm_size), + ring->ring_mem_virt, ring->ring_mem_dma); + ring->flags &= ~KNAV_RING_FLAG_BUSY; + ring->ops = NULL; + if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED) { + clear_bit(ring->proxy_id, ringacc->proxy_inuse); + ring->proxy = NULL; + ring->proxy_id = K3_RINGACC_PROXY_NOT_USED; + } + +no_init: + clear_bit(ring->ring_id, ringacc->rings_inuse); + + module_put(ringacc->dev->driver->owner); + +out: + return 0; +} + +u32 k3_nav_ringacc_get_ring_id(struct k3_nav_ring *ring) +{ + if (!ring) + return -EINVAL; + + return ring->ring_id; +} + +static int k3_nav_ringacc_ring_cfg_sci(struct k3_nav_ring *ring) +{ + struct k3_nav_ringacc *ringacc = ring->parent; + u32 ring_idx; + int ret; + + if (!ringacc->tisci) + return -EINVAL; + + ring_idx = ring->ring_id; + ret = ringacc->tisci_ring_ops->config( + ringacc->tisci, + TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER, + ringacc->tisci_dev_id, + ring_idx, + lower_32_bits(ring->ring_mem_dma), + upper_32_bits(ring->ring_mem_dma), + ring->size, + ring->mode, + ring->elm_size, + 0); + if (ret) + dev_err(ringacc->dev, "TISCI config ring fail (%d) ring_idx %d\n", + ret, ring_idx); + + return ret; +} + +int k3_nav_ringacc_ring_cfg(struct k3_nav_ring *ring, + struct k3_nav_ring_cfg *cfg) +{ + struct k3_nav_ringacc *ringacc = ring->parent; + int ret = 0; + + if (!ring || !cfg) + return -EINVAL; + if (cfg->elm_size > K3_NAV_RINGACC_RING_ELSIZE_256 || + cfg->mode > K3_NAV_RINGACC_RING_MODE_QM || + cfg->size & ~KNAV_RINGACC_CFG_RING_SIZE_ELCNT_MASK || + !test_bit(ring->ring_id, ringacc->rings_inuse)) + return -EINVAL; + + if (ring->use_count != 1) + return 0; + + ring->size = cfg->size; + ring->elm_size = cfg->elm_size; + ring->mode = cfg->mode; + ring->occ = 0; + ring->free = 0; + ring->rindex = 0; + ring->windex = 0; + + if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED) + ring->proxy = ringacc->proxy_target_base + + ring->proxy_id * K3_RINGACC_PROXY_TARGET_STEP; + + switch (ring->mode) { + case K3_NAV_RINGACC_RING_MODE_RING: + ring->ops = &k3_nav_mode_ring_ops; + break; + case K3_NAV_RINGACC_RING_MODE_QM: + /* + * In Queue mode elm_size can be 8 only and each operation + * uses 2 element slots + */ + if (cfg->elm_size != K3_NAV_RINGACC_RING_ELSIZE_8 || + cfg->size % 2) + goto err_free_proxy; + case K3_NAV_RINGACC_RING_MODE_MESSAGE: + if (ring->proxy) + ring->ops = &k3_nav_mode_proxy_ops; + else + ring->ops = &k3_nav_mode_msg_ops; + break; + default: + ring->ops = NULL; + ret = -EINVAL; + goto err_free_proxy; + }; + + ring->ring_mem_virt = + dma_zalloc_coherent(ringacc->dev, + ring->size * (4 << ring->elm_size), + &ring->ring_mem_dma, GFP_KERNEL); + if (!ring->ring_mem_virt) { + dev_err(ringacc->dev, "Failed to alloc ring mem\n"); + ret = -ENOMEM; + goto err_free_ops; + } + + ret = k3_nav_ringacc_ring_cfg_sci(ring); + + if (ret) + goto err_free_mem; + + ring->flags |= KNAV_RING_FLAG_BUSY; + ring->flags |= (cfg->flags & K3_NAV_RINGACC_RING_SHARED) ? + K3_NAV_RING_FLAG_SHARED : 0; + + return 0; + +err_free_mem: + dma_free_coherent(ringacc->dev, + ring->size * (4 << ring->elm_size), + ring->ring_mem_virt, + ring->ring_mem_dma); +err_free_ops: + ring->ops = NULL; +err_free_proxy: + ring->proxy = NULL; + return ret; +} + +u32 k3_nav_ringacc_ring_get_size(struct k3_nav_ring *ring) +{ + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + return ring->size; +} + +u32 k3_nav_ringacc_ring_get_free(struct k3_nav_ring *ring) +{ + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + if (!ring->free) + ring->free = ring->size - ringacc_readl(&ring->rt->occ); + + return ring->free; +} + +u32 k3_nav_ringacc_ring_get_occ(struct k3_nav_ring *ring) +{ + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + return ringacc_readl(&ring->rt->occ); +} + +u32 k3_nav_ringacc_ring_is_full(struct k3_nav_ring *ring) +{ + return !k3_nav_ringacc_ring_get_free(ring); +} + +enum k3_ringacc_access_mode { + K3_RINGACC_ACCESS_MODE_PUSH_HEAD, + K3_RINGACC_ACCESS_MODE_POP_HEAD, + K3_RINGACC_ACCESS_MODE_PUSH_TAIL, + K3_RINGACC_ACCESS_MODE_POP_TAIL, + K3_RINGACC_ACCESS_MODE_PEEK_HEAD, + K3_RINGACC_ACCESS_MODE_PEEK_TAIL, +}; + +static int k3_ringacc_ring_cfg_proxy(struct k3_nav_ring *ring, + enum k3_ringacc_proxy_access_mode mode) +{ + u32 val; + + val = ring->ring_id; + val |= mode << 16; + val |= ring->elm_size << 24; + ringacc_writel(val, &ring->proxy->control); + return 0; +} + +static int k3_nav_ringacc_ring_access_proxy( + struct k3_nav_ring *ring, void *elem, + enum k3_ringacc_access_mode access_mode) +{ + void __iomem *ptr; + + ptr = (void __iomem *)&ring->proxy->data; + + switch (access_mode) { + case K3_RINGACC_ACCESS_MODE_PUSH_HEAD: + case K3_RINGACC_ACCESS_MODE_POP_HEAD: + k3_ringacc_ring_cfg_proxy(ring, PROXY_ACCESS_MODE_HEAD); + break; + case K3_RINGACC_ACCESS_MODE_PUSH_TAIL: + case K3_RINGACC_ACCESS_MODE_POP_TAIL: + k3_ringacc_ring_cfg_proxy(ring, PROXY_ACCESS_MODE_TAIL); + break; + default: + return -EINVAL; + } + + ptr += k3_nav_ringacc_ring_get_fifo_pos(ring); + + switch (access_mode) { + case K3_RINGACC_ACCESS_MODE_POP_HEAD: + case K3_RINGACC_ACCESS_MODE_POP_TAIL: + pr_debug("proxy:memcpy_fromio(x): --> ptr(%p), mode:%d\n", + ptr, access_mode); + memcpy_fromio(elem, ptr, (4 << ring->elm_size)); + ring->occ--; + break; + case K3_RINGACC_ACCESS_MODE_PUSH_TAIL: + case K3_RINGACC_ACCESS_MODE_PUSH_HEAD: + pr_debug("proxy:memcpy_toio(x): --> ptr(%p), mode:%d\n", + ptr, access_mode); + memcpy_toio(ptr, elem, (4 << ring->elm_size)); + ring->free--; + break; + default: + return -EINVAL; + } + + pr_debug("proxy: free%d occ%d\n", + ring->free, ring->occ); + return 0; +} + +static int k3_ringacc_ring_push_head_proxy(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_proxy( + ring, elem, K3_RINGACC_ACCESS_MODE_PUSH_HEAD); +} + +static int k3_ringacc_ring_push_tail_proxy(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_proxy( + ring, elem, K3_RINGACC_ACCESS_MODE_PUSH_TAIL); +} + +static int k3_ringacc_ring_pop_head_proxy(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_proxy( + ring, elem, K3_RINGACC_ACCESS_MODE_POP_HEAD); +} + +static int k3_ringacc_ring_pop_tail_proxy(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_proxy( + ring, elem, K3_RINGACC_ACCESS_MODE_POP_HEAD); +} + +static int k3_nav_ringacc_ring_access_io( + struct k3_nav_ring *ring, void *elem, + enum k3_ringacc_access_mode access_mode) +{ + void __iomem *ptr; + + switch (access_mode) { + case K3_RINGACC_ACCESS_MODE_PUSH_HEAD: + case K3_RINGACC_ACCESS_MODE_POP_HEAD: + ptr = (void __iomem *)&ring->fifos->head_data; + break; + case K3_RINGACC_ACCESS_MODE_PUSH_TAIL: + case K3_RINGACC_ACCESS_MODE_POP_TAIL: + ptr = (void __iomem *)&ring->fifos->tail_data; + break; + default: + return -EINVAL; + } + + ptr += k3_nav_ringacc_ring_get_fifo_pos(ring); + + switch (access_mode) { + case K3_RINGACC_ACCESS_MODE_POP_HEAD: + case K3_RINGACC_ACCESS_MODE_POP_TAIL: + pr_debug("memcpy_fromio(x): --> ptr(%p), mode:%d\n", + ptr, access_mode); + memcpy_fromio(elem, ptr, (4 << ring->elm_size)); + ring->occ--; + break; + case K3_RINGACC_ACCESS_MODE_PUSH_TAIL: + case K3_RINGACC_ACCESS_MODE_PUSH_HEAD: + pr_debug("memcpy_toio(x): --> ptr(%p), mode:%d\n", + ptr, access_mode); + memcpy_toio(ptr, elem, (4 << ring->elm_size)); + ring->free--; + break; + default: + return -EINVAL; + } + + pr_debug("free%d index%d occ%d index%d\n", + ring->free, ring->windex, ring->occ, ring->rindex); + return 0; +} + +static int k3_nav_ringacc_ring_push_head_io(struct k3_nav_ring *ring, + void *elem) +{ + return k3_nav_ringacc_ring_access_io( + ring, elem, K3_RINGACC_ACCESS_MODE_PUSH_HEAD); +} + +static int k3_nav_ringacc_ring_push_io(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_io( + ring, elem, K3_RINGACC_ACCESS_MODE_PUSH_TAIL); +} + +static int k3_nav_ringacc_ring_pop_io(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_io( + ring, elem, K3_RINGACC_ACCESS_MODE_POP_HEAD); +} + +static int k3_nav_ringacc_ring_pop_tail_io(struct k3_nav_ring *ring, void *elem) +{ + return k3_nav_ringacc_ring_access_io( + ring, elem, K3_RINGACC_ACCESS_MODE_POP_HEAD); +} + +static int k3_nav_ringacc_ring_push_mem(struct k3_nav_ring *ring, void *elem) +{ + void *elem_ptr; + + elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->windex); + + memcpy(elem_ptr, elem, (4 << ring->elm_size)); + + ring->windex = (ring->windex + 1) % ring->size; + ring->free--; + ringacc_writel(1, &ring->rt->db); + + pr_debug("ring_push_mem: free%d index%d\n", + ring->free, ring->windex); + + return 0; +} + +static int k3_nav_ringacc_ring_pop_mem(struct k3_nav_ring *ring, void *elem) +{ + void *elem_ptr; + + elem_ptr = k3_nav_ringacc_get_elm_addr(ring, ring->rindex); + + memcpy(elem, elem_ptr, (4 << ring->elm_size)); + + ring->rindex = (ring->rindex + 1) % ring->size; + ring->occ--; + ringacc_writel(-1, &ring->rt->db); + + pr_debug("ring_pop_mem: occ%d index%d pos_ptr%p\n", + ring->occ, ring->rindex, elem_ptr); + return 0; +} + +int k3_nav_ringacc_ring_push(struct k3_nav_ring *ring, void *elem) +{ + int ret = -EOPNOTSUPP; + + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + pr_debug("ring_push%d: free%d index%d\n", + ring->ring_id, ring->free, ring->windex); + + if (k3_nav_ringacc_ring_is_full(ring)) + return -ENOMEM; + + if (ring->ops && ring->ops->push_tail) + ret = ring->ops->push_tail(ring, elem); + + return ret; +} + +int k3_nav_ringacc_ring_push_head(struct k3_nav_ring *ring, void *elem) +{ + int ret = -EOPNOTSUPP; + + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + pr_debug("ring_push_head: free%d index%d\n", + ring->free, ring->windex); + + if (k3_nav_ringacc_ring_is_full(ring)) + return -ENOMEM; + + if (ring->ops && ring->ops->push_head) + ret = ring->ops->push_head(ring, elem); + + return ret; +} + +int k3_nav_ringacc_ring_pop(struct k3_nav_ring *ring, void *elem) +{ + int ret = -EOPNOTSUPP; + + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + if (!ring->occ) + ring->occ = k3_nav_ringacc_ring_get_occ(ring); + + pr_debug("ring_pop%d: occ%d index%d\n", + ring->ring_id, ring->occ, ring->rindex); + + if (!ring->occ) + return -ENODATA; + + if (ring->ops && ring->ops->pop_head) + ret = ring->ops->pop_head(ring, elem); + + return ret; +} + +int k3_nav_ringacc_ring_pop_tail(struct k3_nav_ring *ring, void *elem) +{ + int ret = -EOPNOTSUPP; + + if (!ring || !(ring->flags & KNAV_RING_FLAG_BUSY)) + return -EINVAL; + + if (!ring->occ) + ring->occ = k3_nav_ringacc_ring_get_occ(ring); + + pr_debug("ring_pop_tail: occ%d index%d\n", + ring->occ, ring->rindex); + + if (!ring->occ) + return -ENODATA; + + if (ring->ops && ring->ops->pop_tail) + ret = ring->ops->pop_tail(ring, elem); + + return ret; +} + +static int k3_nav_ringacc_probe_dt(struct k3_nav_ringacc *ringacc) +{ + struct udevice *dev = ringacc->dev; + struct udevice *tisci_dev = NULL; + int ret; + + ringacc->num_rings = dev_read_u32_default(dev, "ti,num-rings", 0); + if (!ringacc->num_rings) { + dev_err(dev, "ti,num-rings read failure %d\n", ret); + return -EINVAL; + } + + ringacc->dma_ring_reset_quirk = + dev_read_bool(dev, "ti,dma-ring-reset-quirk"); + + ret = uclass_get_device_by_name(UCLASS_FIRMWARE, "dmsc", &tisci_dev); + if (ret) { + pr_debug("TISCI RA RM get failed (%d)\n", ret); + ringacc->tisci = NULL; + return -ENODEV; + } + ringacc->tisci = (struct ti_sci_handle *) + (ti_sci_get_handle_from_sysfw(tisci_dev)); + + ret = dev_read_u32_default(dev, "ti,sci", 0); + if (!ret) { + dev_err(dev, "TISCI RA RM disabled\n"); + ringacc->tisci = NULL; + return ret; + } + + ret = dev_read_u32(dev, "ti,sci-dev-id", &ringacc->tisci_dev_id); + if (ret) { + dev_err(dev, "ti,sci-dev-id read failure %d\n", ret); + ringacc->tisci = NULL; + return ret; + } + + ringacc->rm_gp_range = devm_ti_sci_get_of_resource( + ringacc->tisci, dev, + ringacc->tisci_dev_id, + "ti,sci-rm-range-gp-rings"); + if (IS_ERR(ringacc->rm_gp_range)) + ret = PTR_ERR(ringacc->rm_gp_range); + + return 0; +} + +static int k3_nav_ringacc_probe(struct udevice *dev) +{ + struct k3_nav_ringacc *ringacc; + void __iomem *base_fifo, *base_rt; + int ret, i; + + ringacc = dev_get_priv(dev); + if (!ringacc) + return -ENOMEM; + + ringacc->dev = dev; + + ret = k3_nav_ringacc_probe_dt(ringacc); + if (ret) + return ret; + + base_rt = (uint32_t *)devfdt_get_addr_name(dev, "rt"); + pr_debug("rt %p\n", base_rt); + if (IS_ERR(base_rt)) + return PTR_ERR(base_rt); + + base_fifo = (uint32_t *)devfdt_get_addr_name(dev, "fifos"); + pr_debug("fifos %p\n", base_fifo); + if (IS_ERR(base_fifo)) + return PTR_ERR(base_fifo); + + ringacc->proxy_gcfg = (struct k3_ringacc_proxy_gcfg_regs __iomem *) + devfdt_get_addr_name(dev, "proxy_gcfg"); + if (IS_ERR(ringacc->proxy_gcfg)) + return PTR_ERR(ringacc->proxy_gcfg); + ringacc->proxy_target_base = + (struct k3_ringacc_proxy_gcfg_regs __iomem *) + devfdt_get_addr_name(dev, "proxy_target"); + if (IS_ERR(ringacc->proxy_target_base)) + return PTR_ERR(ringacc->proxy_target_base); + + ringacc->num_proxies = ringacc_readl(&ringacc->proxy_gcfg->config) & + K3_RINGACC_PROXY_CFG_THREADS_MASK; + + ringacc->rings = devm_kzalloc(dev, + sizeof(*ringacc->rings) * + ringacc->num_rings, + GFP_KERNEL); + ringacc->rings_inuse = devm_kcalloc(dev, + BITS_TO_LONGS(ringacc->num_rings), + sizeof(unsigned long), GFP_KERNEL); + ringacc->proxy_inuse = devm_kcalloc(dev, + BITS_TO_LONGS(ringacc->num_proxies), + sizeof(unsigned long), GFP_KERNEL); + + if (!ringacc->rings || !ringacc->rings_inuse || !ringacc->proxy_inuse) + return -ENOMEM; + + for (i = 0; i < ringacc->num_rings; i++) { + ringacc->rings[i].rt = base_rt + + KNAV_RINGACC_RT_REGS_STEP * i; + ringacc->rings[i].fifos = base_fifo + + KNAV_RINGACC_FIFO_REGS_STEP * i; + ringacc->rings[i].parent = ringacc; + ringacc->rings[i].ring_id = i; + ringacc->rings[i].proxy_id = K3_RINGACC_PROXY_NOT_USED; + } + dev_set_drvdata(dev, ringacc); + + ringacc->tisci_ring_ops = &ringacc->tisci->ops.rm_ring_ops; + + list_add_tail(&ringacc->list, &k3_nav_ringacc_list); + + dev_info(dev, "Ring Accelerator probed rings:%u, gp-rings[%u,%u] sci-dev-id:%u\n", + ringacc->num_rings, + ringacc->rm_gp_range->desc[0].start, + ringacc->rm_gp_range->desc[0].num, + ringacc->tisci_dev_id); + dev_info(dev, "dma-ring-reset-quirk: %s\n", + ringacc->dma_ring_reset_quirk ? "enabled" : "disabled"); + dev_info(dev, "RA Proxy rev. %08x, num_proxies:%u\n", + ringacc_readl(&ringacc->proxy_gcfg->revision), + ringacc->num_proxies); + return 0; +} + +static const struct udevice_id knav_ringacc_ids[] = { + { .compatible = "ti,am654-navss-ringacc" }, + {}, +}; + +U_BOOT_DRIVER(k3_navss_ringacc) = { + .name = "k3-navss-ringacc", + .id = UCLASS_MISC, + .of_match = knav_ringacc_ids, + .probe = k3_nav_ringacc_probe, + .priv_auto_alloc_size = sizeof(struct k3_nav_ringacc), +}; diff --git a/drivers/soc/keystone/keystone_serdes.c b/drivers/soc/ti/keystone_serdes.c index 7907e6f..7907e6f 100644 --- a/drivers/soc/keystone/keystone_serdes.c +++ b/drivers/soc/ti/keystone_serdes.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 098372e..a700f24 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -222,8 +222,7 @@ config SPI_SUNXI config STM32_QSPI bool "STM32F7 QSPI driver" - depends on STM32F7 - imply SPI_FLASH_BAR + depends on STM32F7 || ARCH_STM32MP help Enable the STM32F7 Quad-SPI (QSPI) driver. This driver can be used to access the SPI NOR flash chips on platforms embedding diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c index 8b60d7c..bb1067f 100644 --- a/drivers/spi/stm32_qspi.c +++ b/drivers/spi/stm32_qspi.c @@ -9,15 +9,11 @@ #include <common.h> #include <clk.h> -#include <dm.h> -#include <errno.h> -#include <malloc.h> #include <reset.h> -#include <spi.h> -#include <spi_flash.h> -#include <asm/io.h> -#include <asm/arch/stm32.h> +#include <spi-mem.h> +#include <linux/iopoll.h> #include <linux/ioport.h> +#include <linux/sizes.h> struct stm32_qspi_regs { u32 cr; /* 0x00 */ @@ -45,8 +41,7 @@ struct stm32_qspi_regs { #define STM32_QSPI_CR_SSHIFT BIT(4) #define STM32_QSPI_CR_DFM BIT(6) #define STM32_QSPI_CR_FSEL BIT(7) -#define STM32_QSPI_CR_FTHRES_MASK GENMASK(4, 0) -#define STM32_QSPI_CR_FTHRES_SHIFT (8) +#define STM32_QSPI_CR_FTHRES_SHIFT 8 #define STM32_QSPI_CR_TEIE BIT(16) #define STM32_QSPI_CR_TCIE BIT(17) #define STM32_QSPI_CR_FTIE BIT(18) @@ -55,16 +50,16 @@ struct stm32_qspi_regs { #define STM32_QSPI_CR_APMS BIT(22) #define STM32_QSPI_CR_PMM BIT(23) #define STM32_QSPI_CR_PRESCALER_MASK GENMASK(7, 0) -#define STM32_QSPI_CR_PRESCALER_SHIFT (24) +#define STM32_QSPI_CR_PRESCALER_SHIFT 24 /* * QUADSPI device configuration register */ #define STM32_QSPI_DCR_CKMODE BIT(0) #define STM32_QSPI_DCR_CSHT_MASK GENMASK(2, 0) -#define STM32_QSPI_DCR_CSHT_SHIFT (8) +#define STM32_QSPI_DCR_CSHT_SHIFT 8 #define STM32_QSPI_DCR_FSIZE_MASK GENMASK(4, 0) -#define STM32_QSPI_DCR_FSIZE_SHIFT (16) +#define STM32_QSPI_DCR_FSIZE_SHIFT 16 /* * QUADSPI status register @@ -75,8 +70,6 @@ struct stm32_qspi_regs { #define STM32_QSPI_SR_SMF BIT(3) #define STM32_QSPI_SR_TOF BIT(4) #define STM32_QSPI_SR_BUSY BIT(5) -#define STM32_QSPI_SR_FLEVEL_MASK GENMASK(5, 0) -#define STM32_QSPI_SR_FLEVEL_SHIFT (8) /* * QUADSPI flag clear register @@ -92,388 +85,276 @@ struct stm32_qspi_regs { #define STM32_QSPI_CCR_DDRM BIT(31) #define STM32_QSPI_CCR_DHHC BIT(30) #define STM32_QSPI_CCR_SIOO BIT(28) -#define STM32_QSPI_CCR_FMODE_SHIFT (26) -#define STM32_QSPI_CCR_DMODE_SHIFT (24) -#define STM32_QSPI_CCR_DCYC_SHIFT (18) -#define STM32_QSPI_CCR_DCYC_MASK GENMASK(4, 0) -#define STM32_QSPI_CCR_ABSIZE_SHIFT (16) -#define STM32_QSPI_CCR_ABMODE_SHIFT (14) -#define STM32_QSPI_CCR_ADSIZE_SHIFT (12) -#define STM32_QSPI_CCR_ADMODE_SHIFT (10) -#define STM32_QSPI_CCR_IMODE_SHIFT (8) -#define STM32_QSPI_CCR_INSTRUCTION_MASK GENMASK(7, 0) - -enum STM32_QSPI_CCR_IMODE { - STM32_QSPI_CCR_IMODE_NONE = 0, - STM32_QSPI_CCR_IMODE_ONE_LINE = 1, - STM32_QSPI_CCR_IMODE_TWO_LINE = 2, - STM32_QSPI_CCR_IMODE_FOUR_LINE = 3, -}; - -enum STM32_QSPI_CCR_ADMODE { - STM32_QSPI_CCR_ADMODE_NONE = 0, - STM32_QSPI_CCR_ADMODE_ONE_LINE = 1, - STM32_QSPI_CCR_ADMODE_TWO_LINE = 2, - STM32_QSPI_CCR_ADMODE_FOUR_LINE = 3, -}; - -enum STM32_QSPI_CCR_ADSIZE { - STM32_QSPI_CCR_ADSIZE_8BIT = 0, - STM32_QSPI_CCR_ADSIZE_16BIT = 1, - STM32_QSPI_CCR_ADSIZE_24BIT = 2, - STM32_QSPI_CCR_ADSIZE_32BIT = 3, -}; - -enum STM32_QSPI_CCR_ABMODE { - STM32_QSPI_CCR_ABMODE_NONE = 0, - STM32_QSPI_CCR_ABMODE_ONE_LINE = 1, - STM32_QSPI_CCR_ABMODE_TWO_LINE = 2, - STM32_QSPI_CCR_ABMODE_FOUR_LINE = 3, -}; - -enum STM32_QSPI_CCR_ABSIZE { - STM32_QSPI_CCR_ABSIZE_8BIT = 0, - STM32_QSPI_CCR_ABSIZE_16BIT = 1, - STM32_QSPI_CCR_ABSIZE_24BIT = 2, - STM32_QSPI_CCR_ABSIZE_32BIT = 3, -}; - -enum STM32_QSPI_CCR_DMODE { - STM32_QSPI_CCR_DMODE_NONE = 0, - STM32_QSPI_CCR_DMODE_ONE_LINE = 1, - STM32_QSPI_CCR_DMODE_TWO_LINE = 2, - STM32_QSPI_CCR_DMODE_FOUR_LINE = 3, -}; - -enum STM32_QSPI_CCR_FMODE { - STM32_QSPI_CCR_IND_WRITE = 0, - STM32_QSPI_CCR_IND_READ = 1, - STM32_QSPI_CCR_AUTO_POLL = 2, - STM32_QSPI_CCR_MEM_MAP = 3, -}; - -/* default SCK frequency, unit: HZ */ -#define STM32_QSPI_DEFAULT_SCK_FREQ 108000000 - -#define STM32_MAX_NORCHIP 2 - -struct stm32_qspi_platdata { - u32 base; - u32 memory_map; - u32 max_hz; +#define STM32_QSPI_CCR_FMODE_SHIFT 26 +#define STM32_QSPI_CCR_DMODE_SHIFT 24 +#define STM32_QSPI_CCR_DCYC_SHIFT 18 +#define STM32_QSPI_CCR_ABSIZE_SHIFT 16 +#define STM32_QSPI_CCR_ABMODE_SHIFT 14 +#define STM32_QSPI_CCR_ADSIZE_SHIFT 12 +#define STM32_QSPI_CCR_ADMODE_SHIFT 10 +#define STM32_QSPI_CCR_IMODE_SHIFT 8 + +#define STM32_QSPI_CCR_IND_WRITE 0 +#define STM32_QSPI_CCR_IND_READ 1 +#define STM32_QSPI_CCR_MEM_MAP 3 + +#define STM32_QSPI_MAX_MMAP_SZ SZ_256M +#define STM32_QSPI_MAX_CHIP 2 + +#define STM32_QSPI_FIFO_TIMEOUT_US 30000 +#define STM32_QSPI_CMD_TIMEOUT_US 1000000 +#define STM32_BUSY_TIMEOUT_US 100000 +#define STM32_ABT_TIMEOUT_US 100000 + +struct stm32_qspi_flash { + u32 cr; + u32 dcr; + bool initialized; }; struct stm32_qspi_priv { struct stm32_qspi_regs *regs; + struct stm32_qspi_flash flash[STM32_QSPI_MAX_CHIP]; + void __iomem *mm_base; + resource_size_t mm_size; ulong clock_rate; - u32 max_hz; - u32 mode; - - u32 command; - u32 address; - u32 dummycycles; -#define CMD_HAS_ADR BIT(24) -#define CMD_HAS_DUMMY BIT(25) -#define CMD_HAS_DATA BIT(26) + int cs_used; }; -static void _stm32_qspi_disable(struct stm32_qspi_priv *priv) +static int _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv) { - clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); -} + u32 sr; + int ret; -static void _stm32_qspi_enable(struct stm32_qspi_priv *priv) -{ - setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); -} + ret = readl_poll_timeout(&priv->regs->sr, sr, + !(sr & STM32_QSPI_SR_BUSY), + STM32_BUSY_TIMEOUT_US); + if (ret) + pr_err("busy timeout (stat:%#x)\n", sr); -static void _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv) -{ - while (readl(&priv->regs->sr) & STM32_QSPI_SR_BUSY) - ; + return ret; } -static void _stm32_qspi_wait_for_complete(struct stm32_qspi_priv *priv) +static int _stm32_qspi_wait_cmd(struct stm32_qspi_priv *priv, + const struct spi_mem_op *op) { - while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_TCF)) - ; -} + u32 sr; + int ret; -static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv) -{ - while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_FTF)) - ; -} + if (!op->data.nbytes) + return _stm32_qspi_wait_for_not_busy(priv); -static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size) -{ - u32 fsize = fls(size) - 1; + ret = readl_poll_timeout(&priv->regs->sr, sr, + sr & STM32_QSPI_SR_TCF, + STM32_QSPI_CMD_TIMEOUT_US); + if (ret) { + pr_err("cmd timeout (stat:%#x)\n", sr); + } else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) { + pr_err("transfer error (stat:%#x)\n", sr); + ret = -EIO; + } - clrsetbits_le32(&priv->regs->dcr, - STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT, - fsize << STM32_QSPI_DCR_FSIZE_SHIFT); + /* clear flags */ + writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr); + + return ret; } -static void _stm32_qspi_set_cs(struct stm32_qspi_priv *priv, unsigned int cs) +static void _stm32_qspi_read_fifo(u8 *val, void __iomem *addr) { - clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL, - cs ? STM32_QSPI_CR_FSEL : 0); + *val = readb(addr); } -static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv, u8 fmode) +static void _stm32_qspi_write_fifo(u8 *val, void __iomem *addr) { - unsigned int ccr_reg = 0; - u8 imode, admode, dmode; - u32 mode = priv->mode; - u32 cmd = (priv->command & STM32_QSPI_CCR_INSTRUCTION_MASK); - - imode = STM32_QSPI_CCR_IMODE_ONE_LINE; - admode = STM32_QSPI_CCR_ADMODE_ONE_LINE; - dmode = STM32_QSPI_CCR_DMODE_ONE_LINE; - - if ((priv->command & CMD_HAS_ADR) && (priv->command & CMD_HAS_DATA)) { - if (fmode == STM32_QSPI_CCR_IND_WRITE) { - if (mode & SPI_TX_QUAD) - dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE; - else if (mode & SPI_TX_DUAL) - dmode = STM32_QSPI_CCR_DMODE_TWO_LINE; - } else if ((fmode == STM32_QSPI_CCR_MEM_MAP) || - (fmode == STM32_QSPI_CCR_IND_READ)) { - if (mode & SPI_RX_QUAD) - dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE; - else if (mode & SPI_RX_DUAL) - dmode = STM32_QSPI_CCR_DMODE_TWO_LINE; - } - } - - if (priv->command & CMD_HAS_DATA) - ccr_reg |= (dmode << STM32_QSPI_CCR_DMODE_SHIFT); - - if (priv->command & CMD_HAS_DUMMY) - ccr_reg |= ((priv->dummycycles & STM32_QSPI_CCR_DCYC_MASK) - << STM32_QSPI_CCR_DCYC_SHIFT); - - if (priv->command & CMD_HAS_ADR) { - ccr_reg |= (STM32_QSPI_CCR_ADSIZE_24BIT - << STM32_QSPI_CCR_ADSIZE_SHIFT); - ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT); - } - - ccr_reg |= (fmode << STM32_QSPI_CCR_FMODE_SHIFT); - ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT); - ccr_reg |= cmd; - - return ccr_reg; + writeb(*val, addr); } -static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv, - struct spi_flash *flash) +static int _stm32_qspi_poll(struct stm32_qspi_priv *priv, + const struct spi_mem_op *op) { - unsigned int ccr_reg; + void (*fifo)(u8 *val, void __iomem *addr); + u32 len = op->data.nbytes, sr; + u8 *buf; + int ret; - priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA - | CMD_HAS_DUMMY; - priv->dummycycles = flash->read_dummy; + if (op->data.dir == SPI_MEM_DATA_IN) { + fifo = _stm32_qspi_read_fifo; + buf = op->data.buf.in; - ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP); + } else { + fifo = _stm32_qspi_write_fifo; + buf = (u8 *)op->data.buf.out; + } - _stm32_qspi_wait_for_not_busy(priv); + while (len--) { + ret = readl_poll_timeout(&priv->regs->sr, sr, + sr & STM32_QSPI_SR_FTF, + STM32_QSPI_FIFO_TIMEOUT_US); + if (ret) { + pr_err("fifo timeout (len:%d stat:%#x)\n", len, sr); + return ret; + } - writel(ccr_reg, &priv->regs->ccr); + fifo(buf++, &priv->regs->dr); + } - priv->dummycycles = 0; + return 0; } -static void _stm32_qspi_disable_mmap(struct stm32_qspi_priv *priv) +static int stm32_qspi_mm(struct stm32_qspi_priv *priv, + const struct spi_mem_op *op) { - setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT); -} + memcpy_fromio(op->data.buf.in, priv->mm_base + op->addr.val, + op->data.nbytes); -static void _stm32_qspi_set_xfer_length(struct stm32_qspi_priv *priv, - u32 length) -{ - writel(length - 1, &priv->regs->dlr); + return 0; } -static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg) +static int _stm32_qspi_tx(struct stm32_qspi_priv *priv, + const struct spi_mem_op *op, + u8 mode) { - writel(cr_reg, &priv->regs->ccr); + if (!op->data.nbytes) + return 0; + + if (mode == STM32_QSPI_CCR_MEM_MAP) + return stm32_qspi_mm(priv, op); - if (priv->command & CMD_HAS_ADR) - writel(priv->address, &priv->regs->ar); + return _stm32_qspi_poll(priv, op); } -static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv, - struct spi_flash *flash, unsigned int bitlen, - const u8 *dout, u8 *din, unsigned long flags) +static int _stm32_qspi_get_mode(u8 buswidth) { - unsigned int words = bitlen / 8; - u32 ccr_reg; - int i; + if (buswidth == 4) + return 3; - if (flags & SPI_XFER_MMAP) { - _stm32_qspi_enable_mmap(priv, flash); - return 0; - } else if (flags & SPI_XFER_MMAP_END) { - _stm32_qspi_disable_mmap(priv); - return 0; - } - - if (bitlen == 0) - return -1; + return buswidth; +} - if (bitlen % 8) { - debug("spi_xfer: Non byte aligned SPI transfer\n"); - return -1; - } +static int stm32_qspi_exec_op(struct spi_slave *slave, + const struct spi_mem_op *op) +{ + struct stm32_qspi_priv *priv = dev_get_priv(slave->dev->parent); + u32 cr, ccr, addr_max; + u8 mode = STM32_QSPI_CCR_IND_WRITE; + int timeout, ret; + + debug("%s: cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n", + __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, + op->addr.val, op->data.nbytes); + + ret = _stm32_qspi_wait_for_not_busy(priv); + if (ret) + return ret; - if (dout && din) { - debug("spi_xfer: QSPI cannot have data in and data out set\n"); - return -1; - } + addr_max = op->addr.val + op->data.nbytes + 1; - if (!dout && (flags & SPI_XFER_BEGIN)) { - debug("spi_xfer: QSPI transfer must begin with command\n"); - return -1; + if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) { + if (addr_max < priv->mm_size && op->addr.buswidth) + mode = STM32_QSPI_CCR_MEM_MAP; + else + mode = STM32_QSPI_CCR_IND_READ; } - if (dout) { - if (flags & SPI_XFER_BEGIN) { - /* data is command */ - priv->command = dout[0] | CMD_HAS_DATA; - if (words >= 4) { - /* address is here too */ - priv->address = (dout[1] << 16) | - (dout[2] << 8) | dout[3]; - priv->command |= CMD_HAS_ADR; - } - - if (words > 4) { - /* rest is dummy bytes */ - priv->dummycycles = (words - 4) * 8; - priv->command |= CMD_HAS_DUMMY; - } - - if (flags & SPI_XFER_END) { - /* command without data */ - priv->command &= ~(CMD_HAS_DATA); - } - } - - if (flags & SPI_XFER_END) { - ccr_reg = _stm32_qspi_gen_ccr(priv, - STM32_QSPI_CCR_IND_WRITE); - - _stm32_qspi_wait_for_not_busy(priv); - - if (priv->command & CMD_HAS_DATA) - _stm32_qspi_set_xfer_length(priv, words); - - _stm32_qspi_start_xfer(priv, ccr_reg); - - debug("%s: write: ccr:0x%08x adr:0x%08x\n", - __func__, priv->regs->ccr, priv->regs->ar); - - if (priv->command & CMD_HAS_DATA) { - _stm32_qspi_wait_for_ftf(priv); - - debug("%s: words:%d data:", __func__, words); + if (op->data.nbytes) + writel(op->data.nbytes - 1, &priv->regs->dlr); - i = 0; - while (words > i) { - writeb(dout[i], &priv->regs->dr); - debug("%02x ", dout[i]); - i++; - } - debug("\n"); + ccr = (mode << STM32_QSPI_CCR_FMODE_SHIFT); + ccr |= op->cmd.opcode; + ccr |= (_stm32_qspi_get_mode(op->cmd.buswidth) + << STM32_QSPI_CCR_IMODE_SHIFT); - _stm32_qspi_wait_for_complete(priv); - } else { - _stm32_qspi_wait_for_not_busy(priv); - } - } - } else if (din) { - ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_IND_READ); + if (op->addr.nbytes) { + ccr |= ((op->addr.nbytes - 1) << STM32_QSPI_CCR_ADSIZE_SHIFT); + ccr |= (_stm32_qspi_get_mode(op->addr.buswidth) + << STM32_QSPI_CCR_ADMODE_SHIFT); + } - _stm32_qspi_wait_for_not_busy(priv); + if (op->dummy.buswidth && op->dummy.nbytes) + ccr |= (op->dummy.nbytes * 8 / op->dummy.buswidth + << STM32_QSPI_CCR_DCYC_SHIFT); - _stm32_qspi_set_xfer_length(priv, words); + if (op->data.nbytes) + ccr |= (_stm32_qspi_get_mode(op->data.buswidth) + << STM32_QSPI_CCR_DMODE_SHIFT); - _stm32_qspi_start_xfer(priv, ccr_reg); + writel(ccr, &priv->regs->ccr); - debug("%s: read: ccr:0x%08x adr:0x%08x len:%d\n", __func__, - priv->regs->ccr, priv->regs->ar, priv->regs->dlr); + if (op->addr.nbytes && mode != STM32_QSPI_CCR_MEM_MAP) + writel(op->addr.val, &priv->regs->ar); - debug("%s: data:", __func__); + ret = _stm32_qspi_tx(priv, op, mode); + /* + * Abort in: + * -error case + * -read memory map: prefetching must be stopped if we read the last + * byte of device (device size - fifo size). like device size is not + * knows, the prefetching is always stop. + */ + if (ret || mode == STM32_QSPI_CCR_MEM_MAP) + goto abort; - i = 0; - while (words > i) { - din[i] = readb(&priv->regs->dr); - debug("%02x ", din[i]); - i++; - } - debug("\n"); - } + /* Wait end of tx in indirect mode */ + ret = _stm32_qspi_wait_cmd(priv, op); + if (ret) + goto abort; return 0; -} - -static int stm32_qspi_ofdata_to_platdata(struct udevice *bus) -{ - struct resource res_regs, res_mem; - struct stm32_qspi_platdata *plat = bus->platdata; - int ret; - ret = dev_read_resource_byname(bus, "qspi", &res_regs); - if (ret) { - debug("Error: can't get regs base addresses(ret = %d)!\n", ret); - return -ENOMEM; - } - ret = dev_read_resource_byname(bus, "qspi_mm", &res_mem); - if (ret) { - debug("Error: can't get mmap base address(ret = %d)!\n", ret); - return -ENOMEM; - } +abort: + setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT); - plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency", - STM32_QSPI_DEFAULT_SCK_FREQ); + /* Wait clear of abort bit by hw */ + timeout = readl_poll_timeout(&priv->regs->cr, cr, + !(cr & STM32_QSPI_CR_ABORT), + STM32_ABT_TIMEOUT_US); - plat->base = res_regs.start; - plat->memory_map = res_mem.start; + writel(STM32_QSPI_FCR_CTCF, &priv->regs->fcr); - debug("%s: regs=<0x%x> mapped=<0x%x>, max-frequency=%d\n", - __func__, - plat->base, - plat->memory_map, - plat->max_hz - ); + if (ret || timeout) + pr_err("%s ret:%d abort timeout:%d\n", __func__, ret, timeout); - return 0; + return ret; } static int stm32_qspi_probe(struct udevice *bus) { - struct stm32_qspi_platdata *plat = dev_get_platdata(bus); struct stm32_qspi_priv *priv = dev_get_priv(bus); - struct dm_spi_bus *dm_spi_bus; + struct resource res; struct clk clk; struct reset_ctl reset_ctl; int ret; - dm_spi_bus = bus->uclass_priv; + ret = dev_read_resource_byname(bus, "qspi", &res); + if (ret) { + dev_err(bus, "can't get regs base addresses(ret = %d)!\n", ret); + return ret; + } - dm_spi_bus->max_hz = plat->max_hz; + priv->regs = (struct stm32_qspi_regs *)res.start; - priv->regs = (struct stm32_qspi_regs *)(uintptr_t)plat->base; + ret = dev_read_resource_byname(bus, "qspi_mm", &res); + if (ret) { + dev_err(bus, "can't get mmap base address(ret = %d)!\n", ret); + return ret; + } - priv->max_hz = plat->max_hz; + priv->mm_base = (void __iomem *)res.start; + + priv->mm_size = resource_size(&res); + if (priv->mm_size > STM32_QSPI_MAX_MMAP_SZ) + return -EINVAL; + + debug("%s: regs=<0x%p> mapped=<0x%p> mapped_size=<0x%lx>\n", + __func__, priv->regs, priv->mm_base, priv->mm_size); ret = clk_get_by_index(bus, 0, &clk); if (ret < 0) return ret; ret = clk_enable(&clk); - if (ret) { dev_err(bus, "failed to enable clock\n"); return ret; @@ -499,78 +380,68 @@ static int stm32_qspi_probe(struct udevice *bus) reset_deassert(&reset_ctl); } + priv->cs_used = -1; + setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT); - return 0; -} + /* Set dcr fsize to max address */ + setbits_le32(&priv->regs->dcr, + STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT); -static int stm32_qspi_remove(struct udevice *bus) -{ return 0; } static int stm32_qspi_claim_bus(struct udevice *dev) { - struct stm32_qspi_priv *priv; - struct udevice *bus; - struct spi_flash *flash; - struct dm_spi_slave_platdata *slave_plat; + struct stm32_qspi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); - bus = dev->parent; - priv = dev_get_priv(bus); - flash = dev_get_uclass_priv(dev); - slave_plat = dev_get_parent_platdata(dev); - - if (slave_plat->cs >= STM32_MAX_NORCHIP) + if (slave_plat->cs >= STM32_QSPI_MAX_CHIP) return -ENODEV; - _stm32_qspi_set_cs(priv, slave_plat->cs); - - _stm32_qspi_set_flash_size(priv, flash->size); + if (priv->cs_used != slave_plat->cs) { + struct stm32_qspi_flash *flash = &priv->flash[slave_plat->cs]; - _stm32_qspi_enable(priv); + priv->cs_used = slave_plat->cs; - return 0; -} + if (flash->initialized) { + /* Set the configuration: speed + cs */ + writel(flash->cr, &priv->regs->cr); + writel(flash->dcr, &priv->regs->dcr); + } else { + /* Set chip select */ + clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL, + priv->cs_used ? STM32_QSPI_CR_FSEL : 0); -static int stm32_qspi_release_bus(struct udevice *dev) -{ - struct stm32_qspi_priv *priv; - struct udevice *bus; + /* Save the configuration: speed + cs */ + flash->cr = readl(&priv->regs->cr); + flash->dcr = readl(&priv->regs->dcr); - bus = dev->parent; - priv = dev_get_priv(bus); + flash->initialized = true; + } + } - _stm32_qspi_disable(priv); + setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); return 0; } -static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) +static int stm32_qspi_release_bus(struct udevice *dev) { - struct stm32_qspi_priv *priv; - struct udevice *bus; - struct spi_flash *flash; + struct stm32_qspi_priv *priv = dev_get_priv(dev->parent); - bus = dev->parent; - priv = dev_get_priv(bus); - flash = dev_get_uclass_priv(dev); + clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN); - return _stm32_qspi_xfer(priv, flash, bitlen, (const u8 *)dout, - (u8 *)din, flags); + return 0; } static int stm32_qspi_set_speed(struct udevice *bus, uint speed) { - struct stm32_qspi_platdata *plat = bus->platdata; struct stm32_qspi_priv *priv = dev_get_priv(bus); u32 qspi_clk = priv->clock_rate; u32 prescaler = 255; u32 csht; - - if (speed > plat->max_hz) - speed = plat->max_hz; + int ret; if (speed > 0) { prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1; @@ -583,7 +454,9 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed) csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000); csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK; - _stm32_qspi_wait_for_not_busy(priv); + ret = _stm32_qspi_wait_for_not_busy(priv); + if (ret) + return ret; clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_PRESCALER_MASK << @@ -603,8 +476,11 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed) static int stm32_qspi_set_mode(struct udevice *bus, uint mode) { struct stm32_qspi_priv *priv = dev_get_priv(bus); + int ret; - _stm32_qspi_wait_for_not_busy(priv); + ret = _stm32_qspi_wait_for_not_busy(priv); + if (ret) + return ret; if ((mode & SPI_CPHA) && (mode & SPI_CPOL)) setbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE); @@ -616,20 +492,6 @@ static int stm32_qspi_set_mode(struct udevice *bus, uint mode) if (mode & SPI_CS_HIGH) return -ENODEV; - if (mode & SPI_RX_QUAD) - priv->mode |= SPI_RX_QUAD; - else if (mode & SPI_RX_DUAL) - priv->mode |= SPI_RX_DUAL; - else - priv->mode &= ~(SPI_RX_QUAD | SPI_RX_DUAL); - - if (mode & SPI_TX_QUAD) - priv->mode |= SPI_TX_QUAD; - else if (mode & SPI_TX_DUAL) - priv->mode |= SPI_TX_DUAL; - else - priv->mode &= ~(SPI_TX_QUAD | SPI_TX_DUAL); - debug("%s: regs=%p, mode=%d rx: ", __func__, priv->regs, mode); if (mode & SPI_RX_QUAD) @@ -649,12 +511,16 @@ static int stm32_qspi_set_mode(struct udevice *bus, uint mode) return 0; } +static const struct spi_controller_mem_ops stm32_qspi_mem_ops = { + .exec_op = stm32_qspi_exec_op, +}; + static const struct dm_spi_ops stm32_qspi_ops = { .claim_bus = stm32_qspi_claim_bus, .release_bus = stm32_qspi_release_bus, - .xfer = stm32_qspi_xfer, .set_speed = stm32_qspi_set_speed, .set_mode = stm32_qspi_set_mode, + .mem_ops = &stm32_qspi_mem_ops, }; static const struct udevice_id stm32_qspi_ids[] = { @@ -664,13 +530,10 @@ static const struct udevice_id stm32_qspi_ids[] = { }; U_BOOT_DRIVER(stm32_qspi) = { - .name = "stm32_qspi", - .id = UCLASS_SPI, + .name = "stm32_qspi", + .id = UCLASS_SPI, .of_match = stm32_qspi_ids, - .ops = &stm32_qspi_ops, - .ofdata_to_platdata = stm32_qspi_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct stm32_qspi_platdata), + .ops = &stm32_qspi_ops, .priv_auto_alloc_size = sizeof(struct stm32_qspi_priv), - .probe = stm32_qspi_probe, - .remove = stm32_qspi_remove, + .probe = stm32_qspi_probe, }; diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c index 3450640..3fb39b9 100644 --- a/drivers/sysreset/sysreset_syscon.c +++ b/drivers/sysreset/sysreset_syscon.c @@ -36,20 +36,9 @@ static struct sysreset_ops syscon_reboot_ops = { int syscon_reboot_probe(struct udevice *dev) { struct syscon_reboot_priv *priv = dev_get_priv(dev); - int err; - u32 phandle; - ofnode node; - err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle); - if (err) - return err; - - node = ofnode_get_by_phandle(phandle); - if (!ofnode_valid(node)) - return -EINVAL; - - priv->regmap = syscon_node_to_regmap(node); - if (!priv->regmap) { + priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap"); + if (IS_ERR(priv->regmap)) { pr_err("unable to find regmap\n"); return -ENODEV; } diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 34e78be..9d7f503 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -97,6 +97,7 @@ config WDT_BCM6345 config WDT_ORION bool "Orion watchdog timer support" depends on WDT + select CLK help Select this to enable Orion watchdog timer, which can be found on some Marvell Armada chips. diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index a0df02d..885821d 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -14,7 +14,9 @@ #include <common.h> #include <dm.h> +#include <clk.h> #include <wdt.h> +#include <linux/kernel.h> #include <asm/io.h> #include <asm/arch/cpu.h> #include <asm/arch/soc.h> @@ -27,6 +29,8 @@ struct orion_wdt_priv { void __iomem *rstout; void __iomem *rstout_mask; u32 timeout; + unsigned long clk_rate; + struct clk clk; }; #define RSTOUT_ENABLE_BIT BIT(8) @@ -44,17 +48,18 @@ static int orion_wdt_reset(struct udevice *dev) struct orion_wdt_priv *priv = dev_get_priv(dev); /* Reload watchdog duration */ - writel(priv->timeout, priv->reg + priv->wdt_counter_offset); + writel(priv->clk_rate * priv->timeout, + priv->reg + priv->wdt_counter_offset); return 0; } -static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +static int orion_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { struct orion_wdt_priv *priv = dev_get_priv(dev); u32 reg; - priv->timeout = (u32) timeout; + priv->timeout = DIV_ROUND_UP(timeout_ms, 1000); /* Enable the fixed watchdog clock input */ reg = readl(priv->reg + TIMER_CTRL); @@ -62,7 +67,8 @@ static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags) writel(reg, priv->reg + TIMER_CTRL); /* Set watchdog duration */ - writel(priv->timeout, priv->reg + priv->wdt_counter_offset); + writel(priv->clk_rate * priv->timeout, + priv->reg + priv->wdt_counter_offset); /* Clear the watchdog expiration bit */ reg = readl(priv->reg + TIMER_A370_STATUS); @@ -114,9 +120,7 @@ static inline bool save_reg_from_ofdata(struct udevice *dev, int index, fdt_addr_t addr; fdt_size_t off; - addr = fdtdec_get_addr_size_auto_noparent( - gd->fdt_blob, dev_of_offset(dev), "reg", index, &off, true); - + addr = devfdt_get_addr_size_index(dev, index, &off); if (addr == FDT_ADDR_T_NONE) return false; @@ -149,9 +153,18 @@ err: static int orion_wdt_probe(struct udevice *dev) { + struct orion_wdt_priv *priv = dev_get_priv(dev); + int ret; + debug("%s: Probing wdt%u\n", __func__, dev->seq); orion_wdt_stop(dev); + ret = clk_get_by_name(dev, "fixed", &priv->clk); + if (!ret) + priv->clk_rate = clk_get_rate(&priv->clk); + else + priv->clk_rate = 25000000; + return 0; } diff --git a/dts/Kconfig b/dts/Kconfig index a5f30c8..c9ab66c 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -291,10 +291,10 @@ config SPL_MULTI_DTB_FIT_USER_DEF_ADDR config OF_SPL_REMOVE_PROPS string "List of device tree properties to drop for SPL" depends on SPL_OF_CONTROL - default "interrupt-parent" if SPL_PINCTRL && SPL_CLK - default "clocks clock-names interrupt-parent" if SPL_PINCTRL - default "pinctrl-0 pinctrl-names interrupt-parent" if SPL_CLK - default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent" + default "interrupt-parent interrupts" if SPL_PINCTRL && SPL_CLK + default "clocks clock-names interrupt-parent interrupts" if SPL_PINCTRL + default "pinctrl-0 pinctrl-names interrupt-parent interrupts" if SPL_CLK + default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent interrupts" help Since SPL normally runs in a reduced memory space, the device tree is cut down to only what is needed to load and start U-Boot. Only @@ -26,7 +26,7 @@ #if defined(CONFIG_CMD_SAVEENV) && defined(CONFIG_CMD_NAND) && \ !defined(CONFIG_SPL_BUILD) #define CMD_SAVEENV -#elif defined(CONFIG_ENV_OFFSET_REDUND) +#elif defined(CONFIG_ENV_OFFSET_REDUND) && !defined(CONFIG_SPL_BUILD) #error CONFIG_ENV_OFFSET_REDUND must have CONFIG_CMD_SAVEENV & CONFIG_CMD_NAND #endif diff --git a/include/configs/am335x_guardian.h b/include/configs/am335x_guardian.h new file mode 100644 index 0000000..8bde198 --- /dev/null +++ b/include/configs/am335x_guardian.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * am335x_guardian_.h + * + * Copyright (C) 2018 Robert Bosch Power Tools GmbH + * Copyright (C) 2018 sjoerd Simons <sjoerd.simons@collabora.co.uk> + * + */ + +#ifndef __CONFIG_AM335X_GUARDIAN_H +#define __CONFIG_AM335X_GUARDIAN_H + +#include <configs/ti_am335x_common.h> + +#ifndef CONFIG_SPL_BUILD +#define CONFIG_TIMESTAMP +#endif + +/* Clock Defines */ +#define V_OSCK 24000000 /* Clock output from T2 */ +#define V_SCLK (V_OSCK) + +#ifndef CONFIG_SPL_BUILD + +#define MEM_LAYOUT_ENV_SETTINGS \ + "scriptaddr=0x80000000\0" \ + "pxefile_addr_r=0x80100000\0" \ + "kernel_addr_r=0x82000000\0" \ + "fdt_addr_r=0x88000000\0" \ + "ramdisk_addr_r=0x88080000\0" \ + +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ + func(UBIFS, ubifs, 0) \ + func(PXE, pxe, na) \ + func(DHCP, dhcp, na) + +#define AM335XX_BOARD_FDTFILE "fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" + +#include <config_distro_bootcmd.h> + +#define CONFIG_EXTRA_ENV_SETTINGS \ + AM335XX_BOARD_FDTFILE \ + MEM_LAYOUT_ENV_SETTINGS \ + BOOTENV \ + "bootlimit=3\0" \ + "altbootcmd=" \ + "setenv boot_config \"extlinux-rollback.conf\"; " \ + "run distro_bootcmd\0" + +#endif /* CONFIG_SPL_BUILD */ + +/* NS16550 Configuration */ +#define CONFIG_SYS_NS16550_COM1 0x44e09000 /* UART0 */ +#define CONFIG_SYS_NS16550_COM2 0x48022000 /* UART1 */ +#define CONFIG_SYS_NS16550_COM3 0x48024000 /* UART2 */ +#define CONFIG_SYS_NS16550_COM4 0x481a6000 /* UART3 */ +#define CONFIG_SYS_NS16550_COM5 0x481a8000 /* UART4 */ +#define CONFIG_SYS_NS16550_COM6 0x481aa000 /* UART5 */ + +/* PMIC support */ +#define CONFIG_POWER_TPS65217 + +/* Bootcount using the RTC block */ +#define CONFIG_SYS_BOOTCOUNT_LE + +#ifdef CONFIG_NAND +#define CONFIG_ENV_OFFSET 0x300000 +#define CONFIG_ENV_OFFSET_REDUND 0x340000 +#define CONFIG_ENV_SIZE 0x040000 + +#define CONFIG_SYS_NAND_5_ADDR_CYCLE +#define CONFIG_SYS_NAND_PAGE_COUNT (CONFIG_SYS_NAND_BLOCK_SIZE / \ + CONFIG_SYS_NAND_PAGE_SIZE) +#define CONFIG_SYS_NAND_PAGE_SIZE 4096 +#define CONFIG_SYS_NAND_OOBSIZE 256 +#define CONFIG_SYS_NAND_BLOCK_SIZE (256 * 1024) + +#define CONFIG_SYS_NAND_ECCPOS { 2, 3, 4, 5, 6, 7, 8, 9, \ + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, \ + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, \ + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, \ + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, \ + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \ + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, \ + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, \ + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, \ + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, \ + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, \ + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, \ + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, \ + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, \ + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, \ + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, \ + 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, \ + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, \ + 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, \ + 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, \ + } +#define CONFIG_SYS_NAND_ECCSIZE 512 +#define CONFIG_SYS_NAND_ECCBYTES 26 +#define CONFIG_SYS_NAND_ONFI_DETECTION +#define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_BCH16_CODE_HW +#define MTDIDS_DEFAULT "nand0=nand.0" + +#define CONFIG_SYS_NAND_BAD_BLOCK_POS NAND_LARGE_BADBLOCK_POS + +#endif /* CONFIG_NAND */ + +#endif /* ! __CONFIG_AM335X_GUARDIAN_H */ diff --git a/include/configs/ap152.h b/include/configs/ap152.h new file mode 100644 index 0000000..c948a44 --- /dev/null +++ b/include/configs/ap152.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com> + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_SYS_HZ 1000 +#define CONFIG_SYS_MHZ 375 +#define CONFIG_SYS_MIPS_TIMER_FREQ (CONFIG_SYS_MHZ * 1000000) + +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE + +#define CONFIG_SYS_MALLOC_LEN 0x40000 +#define CONFIG_SYS_BOOTPARAMS_LEN 0x20000 + +#define CONFIG_SYS_SDRAM_BASE 0x80000000 +#define CONFIG_SYS_LOAD_ADDR 0x81000000 + +#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000 +#define CONFIG_SYS_INIT_RAM_SIZE 0x2000 +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1) + +/* + * Serial Port + */ +#define CONFIG_SYS_NS16550_CLK 25000000 +#define CONFIG_SYS_BAUDRATE_TABLE \ + {9600, 19200, 38400, 57600, 115200} + +#define CONFIG_BOOTCOMMAND "sf probe;" \ + "mtdparts default;" \ + "bootm 0x9f060000" + +#define CONFIG_ENV_SPI_MAX_HZ 25000000 +#define CONFIG_ENV_OFFSET 0x40000 +#define CONFIG_ENV_SECT_SIZE 0x10000 +#define CONFIG_ENV_SIZE 0x10000 + +/* Miscellaneous configurable options */ + +/* + * Diagnostics + */ +#define CONFIG_SYS_MEMTEST_START 0x80100000 +#define CONFIG_SYS_MEMTEST_END 0x83f00000 + +#endif /* __CONFIG_H */ diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h index c51cf28..9f8d3cc 100644 --- a/include/configs/clearfog.h +++ b/include/configs/clearfog.h @@ -21,8 +21,6 @@ * Commands configuration */ -/* SPI NOR flash default params, used by sf commands */ - /* * SDIO/MMC Card Configuration */ diff --git a/include/configs/da850evm.h b/include/configs/da850evm.h index 583f994..94848f5 100644 --- a/include/configs/da850evm.h +++ b/include/configs/da850evm.h @@ -48,7 +48,8 @@ #define PHYS_SDRAM_1 DAVINCI_DDR_EMIF_DATA_BASE /* DDR Start */ #define PHYS_SDRAM_1_SIZE (64 << 20) /* SDRAM size 64MB */ #define CONFIG_MAX_RAM_BANK_SIZE (512 << 20) /* max size from SPRS586*/ - +#define CONFIG_SPL_BSS_START_ADDR DAVINCI_DDR_EMIF_DATA_BASE +#define CONFIG_SPL_BSS_MAX_SIZE 0x1080000 /* memtest start addr */ #define CONFIG_SYS_MEMTEST_START (PHYS_SDRAM_1 + 0x2000000) diff --git a/include/configs/db-88f6720.h b/include/configs/db-88f6720.h index 55968c2..63194d5 100644 --- a/include/configs/db-88f6720.h +++ b/include/configs/db-88f6720.h @@ -32,8 +32,6 @@ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -/* SPI NOR flash default params, used by sf commands */ - /* Environment in SPI NOR flash */ #define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ diff --git a/include/configs/db-88f6820-amc.h b/include/configs/db-88f6820-amc.h index f1bdc2d..2fdc845 100644 --- a/include/configs/db-88f6820-amc.h +++ b/include/configs/db-88f6820-amc.h @@ -16,8 +16,6 @@ * Commands configuration */ -/* SPI NOR flash default params, used by sf commands */ - /* USB/EHCI configuration */ #define CONFIG_EHCI_IS_TDI diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index d378052..ec2405b 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -24,12 +24,6 @@ #define CONFIG_SYS_I2C_SPEED 100000 /* - * SPI Flash configuration for the environemnt access - */ - -/* SPI NOR flash default params, used by sf commands */ - -/* * SDIO/MMC Card Configuration */ #define CONFIG_SYS_MMC_BASE MVEBU_SDIO_BASE diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h index b78dbcb..1f9d24b 100644 --- a/include/configs/db-mv784mp-gp.h +++ b/include/configs/db-mv784mp-gp.h @@ -29,8 +29,6 @@ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -/* SPI NOR flash default params, used by sf commands */ - /* Environment in SPI NOR flash */ #define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ diff --git a/include/configs/db-xc3-24g4xg.h b/include/configs/db-xc3-24g4xg.h new file mode 100644 index 0000000..0f75ad7 --- /dev/null +++ b/include/configs/db-xc3-24g4xg.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2014 Stefan Roese <sr@denx.de> + */ + +#ifndef _CONFIG_DB_XC3_24G4G_H +#define _CONFIG_DB_XC3_24G4G_H + +/* + * High Level Configuration Options (easy to change) + */ + +#define CONFIG_SYS_KWD_CONFIG $(CONFIG_BOARDDIR)/kwbimage.cfg +#define CONFIG_SYS_TCLK 200000000 /* 200MHz */ + +/* USB/EHCI configuration */ +#define CONFIG_EHCI_IS_TDI + +/* Environment in SPI NOR flash */ +#define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */ +#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ +#define CONFIG_ENV_SECT_SIZE (256 << 10) /* 256KiB sectors */ + +/* NAND */ +#define CONFIG_SYS_NAND_USE_FLASH_BBT +#define CONFIG_SYS_NAND_ONFI_DETECTION + +/* Keep device tree and initrd in lower memory so the kernel can access them */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "fdt_high=0x10000000\0" \ + "initrd_high=0x10000000\0" + +/* + * mv-common.h should be defined after CMD configs since it used them + * to enable certain macros + */ +#include "mv-common.h" +#undef CONFIG_SYS_MAXARGS +#define CONFIG_SYS_MAXARGS 96 + +#endif /* _CONFIG_DB_XC3_24G4G_H */ diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 10eac20..7441f4a 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -133,7 +133,7 @@ 50, 51, 52, 53, 54, 55, 56, 57, } #define CONFIG_SYS_NAND_ECCSIZE 512 #define CONFIG_SYS_NAND_ECCBYTES 14 -#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x000c0000 +#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x00140000 /* NAND: SPL related configs */ /* NAND: SPL falcon mode configs */ #ifdef CONFIG_SPL_OS_BOOT diff --git a/include/configs/ds414.h b/include/configs/ds414.h index 275a2b4..192c055 100644 --- a/include/configs/ds414.h +++ b/include/configs/ds414.h @@ -28,8 +28,6 @@ #define CONFIG_SYS_I2C_SLAVE 0x0 #define CONFIG_SYS_I2C_SPEED 100000 -/* SPI NOR flash default params, used by sf commands */ - /* Environment in SPI NOR flash */ #define CONFIG_ENV_OFFSET 0x7E0000 /* RedBoot config partition in DTS */ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ diff --git a/include/configs/helios4.h b/include/configs/helios4.h index df4d8bc..b2badab 100644 --- a/include/configs/helios4.h +++ b/include/configs/helios4.h @@ -23,8 +23,6 @@ * Commands configuration */ -/* SPI NOR flash default params, used by sf commands */ - /* * SDIO/MMC Card Configuration */ diff --git a/include/configs/k2e_evm.h b/include/configs/k2e_evm.h index 2c0e4cb..5471274 100644 --- a/include/configs/k2e_evm.h +++ b/include/configs/k2e_evm.h @@ -40,10 +40,6 @@ #include <configs/ti_armv7_keystone2.h> -/* SPL SPI Loader Configuration */ -#define CONFIG_SPL_TEXT_BASE 0x0c100000 - - #define SPI_MTD_PARTS KEYSTONE_SPI0_MTD_PARTS /* NAND Configuration */ diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h index b1aec98..3ec5a5a 100644 --- a/include/configs/k2g_evm.h +++ b/include/configs/k2g_evm.h @@ -72,9 +72,6 @@ "bootm ${fit_loadaddr}#${name_fdt}" #endif -/* SPL SPI Loader Configuration */ -#define CONFIG_SPL_TEXT_BASE 0x0c0a0000 - /* NAND Configuration */ #define CONFIG_SYS_NAND_PAGE_2K diff --git a/include/configs/k2hk_evm.h b/include/configs/k2hk_evm.h index 0b909a1..d4f2e96 100644 --- a/include/configs/k2hk_evm.h +++ b/include/configs/k2hk_evm.h @@ -40,9 +40,6 @@ #include <configs/ti_armv7_keystone2.h> -/* SPL SPI Loader Configuration */ -#define CONFIG_SPL_TEXT_BASE 0x0c200000 - #define SPI_MTD_PARTS KEYSTONE_SPI0_MTD_PARTS /* NAND Configuration */ diff --git a/include/configs/k2l_evm.h b/include/configs/k2l_evm.h index 59e6b09..cfdb36e 100644 --- a/include/configs/k2l_evm.h +++ b/include/configs/k2l_evm.h @@ -40,9 +40,6 @@ #include <configs/ti_armv7_keystone2.h> -/* SPL SPI Loader Configuration */ -#define CONFIG_SPL_TEXT_BASE 0x0c100000 - #define SPI_MTD_PARTS KEYSTONE_SPI0_MTD_PARTS /* NAND Configuration */ diff --git a/include/configs/lsxl.h b/include/configs/lsxl.h index 72e6265..55c4e63 100644 --- a/include/configs/lsxl.h +++ b/include/configs/lsxl.h @@ -76,9 +76,9 @@ "kernel_addr=0x00800000\0" \ "ramdisk_addr=0x01000000\0" \ "fdt_addr=0x00ff0000\0" \ - "bootcmd_legacy=ide reset " \ - "&& load ide ${hdpart} ${kernel_addr} /uImage.buffalo " \ - "&& load ide ${hdpart} ${ramdisk_addr} /initrd.buffalo "\ + "bootcmd_legacy=sata init " \ + "&& load sata ${hdpart} ${kernel_addr} /uImage.buffalo "\ + "&& load sata ${hdpart} ${ramdisk_addr} /initrd.buffalo "\ "&& bootm ${kernel_addr} ${ramdisk_addr}\0" \ "bootcmd_net=bootp ${kernel_addr} vmlinuz " \ "&& tftpboot ${ramdisk_addr} initrd.img " \ @@ -86,11 +86,11 @@ "&& tftpboot ${fdt_addr} " CONFIG_FDTFILE " " \ "&& bootz ${kernel_addr} " \ "${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0" \ - "bootcmd_hdd=ide reset " \ - "&& load ide ${hdpart} ${kernel_addr} /vmlinuz " \ - "&& load ide ${hdpart} ${ramdisk_addr} /initrd.img " \ + "bootcmd_hdd=sata init " \ + "&& load sata ${hdpart} ${kernel_addr} /vmlinuz " \ + "&& load sata ${hdpart} ${ramdisk_addr} /initrd.img " \ "&& setenv ramdisk_len ${filesize} " \ - "&& load ide ${hdpart} ${fdt_addr} /dtb " \ + "&& load sata ${hdpart} ${fdt_addr} /dtb " \ "&& bootz ${kernel_addr} " \ "${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0" \ "bootcmd_usb=usb start " \ @@ -131,13 +131,10 @@ #undef CONFIG_RESET_PHY_R #endif /* CONFIG_CMD_NET */ -#ifdef CONFIG_IDE -#undef CONFIG_SYS_IDE_MAXBUS -#define CONFIG_SYS_IDE_MAXBUS 1 -#undef CONFIG_SYS_IDE_MAXDEVICE -#define CONFIG_SYS_IDE_MAXDEVICE 1 -#define CONFIG_SYS_ATA_IDE0_OFFSET MV_SATA_PORT0_OFFSET +#ifdef CONFIG_SATA +#define CONFIG_SYS_SATA_MAX_DEVICE 1 #define CONFIG_SYS_64BIT_LBA +#define CONFIG_LBA48 #endif #endif /* _CONFIG_LSXL_H */ diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h index f4972b6..b28f3b9 100644 --- a/include/configs/mvebu_armada-8k.h +++ b/include/configs/mvebu_armada-8k.h @@ -49,10 +49,6 @@ /* End of 16M scrubbed by training in bootrom */ #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0xFF0000) -/* - * SPI Flash configuration - */ - #define CONFIG_ENV_OFFSET 0x180000 /* as Marvell U-Boot version */ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ #define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ diff --git a/include/configs/omapl138_lcdk.h b/include/configs/omapl138_lcdk.h index 1786e09..6680c3e 100644 --- a/include/configs/omapl138_lcdk.h +++ b/include/configs/omapl138_lcdk.h @@ -43,6 +43,9 @@ #define PHYS_SDRAM_1_SIZE (128 << 20) /* SDRAM size 128MB */ #define CONFIG_MAX_RAM_BANK_SIZE (512 << 20) /* max size from SPRS586*/ +#define CONFIG_SPL_BSS_START_ADDR DAVINCI_DDR_EMIF_DATA_BASE +#define CONFIG_SPL_BSS_MAX_SIZE 0x1080000 + /* memtest start addr */ #define CONFIG_SYS_MEMTEST_START (PHYS_SDRAM_1 + 0x2000000) diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h index 701298c..737dfd6 100644 --- a/include/configs/stm32mp1.h +++ b/include/configs/stm32mp1.h @@ -10,17 +10,17 @@ #include <linux/sizes.h> #include <asm/arch/stm32.h> -#define CONFIG_PREBOOT - /* * Number of clock ticks in 1 sec */ #define CONFIG_SYS_HZ 1000 +#ifndef CONFIG_STM32MP1_TRUSTED /* PSCI support */ #define CONFIG_ARMV7_PSCI_1_0 #define CONFIG_ARMV7_SECURE_BASE STM32_SYSRAM_BASE #define CONFIG_ARMV7_SECURE_MAX_SIZE STM32_SYSRAM_SIZE +#endif /* * malloc() pool size @@ -53,6 +53,9 @@ #define CONFIG_SETUP_MEMORY_TAGS #define CONFIG_INITRD_TAG +/* Extend size of kernel image for uncompression */ +#define CONFIG_SYS_BOOTM_LEN SZ_32M + /* SPL support */ #ifdef CONFIG_SPL /* BOOTROM load address */ @@ -69,36 +72,65 @@ STM32_SYSRAM_SIZE) #endif /* #ifdef CONFIG_SPL */ +#define CONFIG_SYS_MEMTEST_START STM32_DDR_BASE +#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + SZ_64M) +#define CONFIG_SYS_MEMTEST_SCRATCH (CONFIG_SYS_MEMTEST_END + 4) + /*MMC SD*/ #define CONFIG_SYS_MMC_MAX_DEVICE 3 #define CONFIG_SUPPORT_EMMC_BOOT -#if !defined(CONFIG_SPL) || !defined(CONFIG_SPL_BUILD) +/*****************************************************************************/ +#ifdef CONFIG_DISTRO_DEFAULTS +/*****************************************************************************/ + +#if !defined(CONFIG_SPL_BUILD) #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 1) \ func(MMC, mmc, 0) \ func(MMC, mmc, 2) +/* + * bootcmd for stm32mp1: + * for serial/usb: execute the stm32prog command + * for mmc boot (eMMC, SD card), boot only on the same device + * for nand boot, boot with on ubifs partition on nand + * for nor boot, use the default order + */ +#define CONFIG_PREBOOT -#include <config_distro_bootcmd.h> +#define STM32MP_BOOTCMD "bootcmd_stm32mp=" \ + "echo \"Boot over ${boot_device}${boot_instance}!\";" \ + "if test ${boot_device} = serial || test ${boot_device} = usb;" \ + "then stm32prog ${boot_device} ${boot_instance}; " \ + "else " \ + "if test ${boot_device} = mmc;" \ + "then env set boot_targets \"mmc${boot_instance}\"; fi;" \ + "if test ${boot_device} = nand;" \ + "then env set boot_targets ubifs0; fi;" \ + "run distro_bootcmd;" \ + "fi;\0" -#define STM32MP_PREBOOT \ - "echo \"Boot over ${boot_device}${boot_instance}!\"; " \ - "if test \"${boot_device}\" = \"mmc\"; then " \ - "env set boot_targets \"mmc${boot_instance}\"; "\ - "fi;" +#include <config_distro_bootcmd.h> +/* + * memory layout for 32M uncompressed/compressed kernel, + * 1M fdt, 1M script, 1M pxe and 1M for splashimage + * and the ramdisk at the end. + */ #define CONFIG_EXTRA_ENV_SETTINGS \ - "scriptaddr=0xC0000000\0" \ - "pxefile_addr_r=0xC0000000\0" \ - "kernel_addr_r=0xC1000000\0" \ - "fdt_addr_r=0xC4000000\0" \ - "ramdisk_addr_r=0xC4100000\0" \ + "kernel_addr_r=0xc2000000\0" \ + "fdt_addr_r=0xc4000000\0" \ + "scriptaddr=0xc4100000\0" \ + "pxefile_addr_r=0xc4200000\0" \ + "splashimage=0xc4300000\0" \ + "ramdisk_addr_r=0xc4400000\0" \ "fdt_high=0xffffffff\0" \ "initrd_high=0xffffffff\0" \ - "preboot=" STM32MP_PREBOOT "\0" \ + STM32MP_BOOTCMD \ BOOTENV #endif /* ifndef CONFIG_SPL_BUILD */ +#endif /* ifdef CONFIG_DISTRO_DEFAULTS*/ #endif /* __CONFIG_H */ diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h index 59b2546..cd92835 100644 --- a/include/configs/theadorable.h +++ b/include/configs/theadorable.h @@ -39,8 +39,6 @@ #define CONFIG_EHCI_IS_TDI #define CONFIG_USB_MAX_CONTROLLER_COUNT 3 -/* SPI NOR flash default params, used by sf commands */ - /* Environment in SPI NOR flash */ #define CONFIG_ENV_OFFSET (1 << 20) /* 1MiB in */ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h index fb8c082..eeca085 100644 --- a/include/configs/ti_armv7_keystone2.h +++ b/include/configs/ti_armv7_keystone2.h @@ -22,7 +22,7 @@ /* Memory Configuration */ #define CONFIG_SYS_LPAE_SDRAM_BASE 0x800000000 #define CONFIG_MAX_RAM_BANK_SIZE (2 << 30) /* 2GB */ -#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE - \ +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_ISW_ENTRY_ADDR - \ GENERATED_GBL_DATA_SIZE) #ifdef CONFIG_SYS_MALLOC_F_LEN @@ -32,9 +32,10 @@ #endif /* SPL SPI Loader Configuration */ +#define CONFIG_SPL_TEXT_BASE CONFIG_ISW_ENTRY_ADDR #define CONFIG_SPL_PAD_TO 65536 #define CONFIG_SPL_MAX_SIZE (CONFIG_SPL_PAD_TO - 8) -#define CONFIG_SPL_BSS_START_ADDR (CONFIG_SPL_TEXT_BASE + \ +#define CONFIG_SPL_BSS_START_ADDR (CONFIG_ISW_ENTRY_ADDR + \ CONFIG_SPL_MAX_SIZE) #define CONFIG_SPL_BSS_MAX_SIZE (32 * 1024) #define CONFIG_SYS_SPL_MALLOC_START (CONFIG_SPL_BSS_START_ADDR + \ @@ -132,9 +133,6 @@ #define CONFIG_KSNET_SERDES_SGMII2_BASE KS2_SGMII_SERDES2_BASE #define CONFIG_KSNET_SERDES_LANES_PER_SGMII KS2_LANES_PER_SGMII_SERDES -/* SerDes */ -#define CONFIG_TI_KEYSTONE_SERDES - #define CONFIG_AEMIF_CNTRL_BASE KS2_AEMIF_CNTRL_BASE /* I2C Configuration */ diff --git a/include/configs/ti_omap5_common.h b/include/configs/ti_omap5_common.h index ba57c40..7c08e47 100644 --- a/include/configs/ti_omap5_common.h +++ b/include/configs/ti_omap5_common.h @@ -56,6 +56,7 @@ #include <environment/ti/boot.h> #include <environment/ti/mmc.h> +#include <environment/ti/nand.h> #define CONFIG_EXTRA_ENV_SETTINGS \ DEFAULT_LINUX_BOOT_ENV \ @@ -65,6 +66,7 @@ DEFAULT_FDT_TI_ARGS \ DFUARGS \ NETARGS \ + NANDARGS \ /* * SPL related defines. The Public RAM memory map the ROM defines the @@ -100,7 +102,6 @@ #define CONFIG_SYS_SPL_ARGS_ADDR (CONFIG_SYS_SDRAM_BASE + \ (128 << 20)) - #ifdef CONFIG_SPL_BUILD #undef CONFIG_TIMER #endif diff --git a/include/configs/turris_mox.h b/include/configs/turris_mox.h index 5d5394e..0de40ed 100644 --- a/include/configs/turris_mox.h +++ b/include/configs/turris_mox.h @@ -63,10 +63,6 @@ #define CONFIG_I2C_MV #define CONFIG_SYS_I2C_SLAVE 0x0 -/* - * SPI Flash configuration - */ - /* Environment in SPI NOR flash */ #define CONFIG_ENV_OFFSET 0x180000 /* as Marvell U-Boot version */ #define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h index 038f639..c7805cf 100644 --- a/include/configs/turris_omnia.h +++ b/include/configs/turris_omnia.h @@ -34,9 +34,6 @@ # define CONFIG_WATCHDOG #endif -/* SPI NOR flash default params, used by sf commands */ -#define CONFIG_SPI_FLASH_SPANSION - /* * SDIO/MMC Card Configuration */ diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h index 2840c7b..8c68372 100644 --- a/include/configs/vcoreiii.h +++ b/include/configs/vcoreiii.h @@ -10,7 +10,7 @@ /* Onboard devices */ -#define CONFIG_SYS_MALLOC_LEN 0x100000 +#define CONFIG_SYS_MALLOC_LEN 0x1F0000 #define CONFIG_SYS_LOAD_ADDR 0x00100000 #define CONFIG_SYS_INIT_SP_OFFSET 0x400000 @@ -27,7 +27,7 @@ #if defined(CONFIG_ENV_IS_IN_SPI_FLASH) && !defined(CONFIG_ENV_OFFSET) #define CONFIG_ENV_OFFSET (1024 * 1024) -#define CONFIG_ENV_SIZE (256 * 1024) +#define CONFIG_ENV_SIZE (8 * 1024) #define CONFIG_ENV_SECT_SIZE (256 * 1024) #define CONFIG_SYS_REDUNDAND_ENVIRONMENT diff --git a/include/cpsw.h b/include/cpsw.h index 9f8ce88..96ff254 100644 --- a/include/cpsw.h +++ b/include/cpsw.h @@ -16,6 +16,23 @@ #ifndef _CPSW_H_ #define _CPSW_H_ +/* reg offset */ +#define CPSW_HOST_PORT_OFFSET 0x108 +#define CPSW_SLAVE0_OFFSET 0x208 +#define CPSW_SLAVE1_OFFSET 0x308 +#define CPSW_SLAVE_SIZE 0x100 +#define CPSW_CPDMA_OFFSET 0x800 +#define CPSW_HW_STATS 0x900 +#define CPSW_STATERAM_OFFSET 0xa00 +#define CPSW_CPTS_OFFSET 0xc00 +#define CPSW_ALE_OFFSET 0xd00 +#define CPSW_SLIVER0_OFFSET 0xd80 +#define CPSW_SLIVER1_OFFSET 0xdc0 +#define CPSW_BD_OFFSET 0x2000 +#define CPSW_MDIO_DIV 0xff + +#define AM335X_GMII_SEL_OFFSET 0x630 + struct cpsw_slave_data { u32 slave_reg_ofs; u32 sliver_reg_ofs; @@ -50,10 +67,16 @@ struct cpsw_platform_data { u32 active_slave; bool rmii_clock_external; u8 version; + const char *phy_sel_compat; + u32 syscon_addr; + const char *macid_sel_compat; }; int cpsw_register(struct cpsw_platform_data *data); -int ti_cm_get_macid(struct udevice *dev, int slave, u8 *mac_addr); +int ti_cm_get_macid_addr(struct udevice *dev, int slave, + struct cpsw_platform_data *data); +void ti_cm_get_macid(struct udevice *dev, struct cpsw_platform_data *data, + u8 *mac_addr); int cpsw_get_slave_phy_addr(struct udevice *dev, int slave); #endif /* _CPSW_H_ */ diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h index ff2b82e..63a7d55 100644 --- a/include/dm/pinctrl.h +++ b/include/dm/pinctrl.h @@ -355,18 +355,6 @@ int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph); int pinctrl_decode_pin_config(const void *blob, int node); /** - * pinctrl_decode_pin_config_dm() - decode pin configuration flags - * - * This decodes some of the PIN_CONFIG values into flags, with each value - * being (1 << pin_cfg). This does not support things with values like the - * slew rate. - * - * @pinconfig: Pinconfig udevice - * @return decoded flag value, or -ve on error - */ -int pinctrl_decode_pin_config_dm(struct udevice *dev); - -/** * pinctrl_get_gpio_mux() - get the mux value for a particular GPIO * * This allows the raw mux value for a GPIO to be obtained. It is diff --git a/include/dm/util.h b/include/dm/util.h index 9ff6531..60d3b93 100644 --- a/include/dm/util.h +++ b/include/dm/util.h @@ -40,32 +40,6 @@ static inline void dm_dump_devres(void) #endif /** - * Check if a dt node should be or was bound before relocation. - * - * Devicetree nodes can be marked as needed to be bound - * in the loader stages via special devicetree properties. - * - * Before relocation this function can be used to check if nodes - * are required in either SPL or TPL stages. - * - * After relocation and jumping into the real U-Boot binary - * it is possible to determine if a node was bound in one of - * SPL/TPL stages. - * - * There are 3 settings currently in use - * - - * - u-boot,dm-pre-reloc: legacy and indicates any of TPL or SPL - * Existing platforms only use it to indicate nodes needed in - * SPL. Should probably be replaced by u-boot,dm-spl for - * existing platforms. - * @blob: devicetree - * @offset: node offset - * - * Returns true if node is needed in SPL/TL, false otherwise. - */ -bool dm_fdt_pre_reloc(const void *blob, int offset); - -/** * Check if an of node should be or was bound before relocation. * * Devicetree nodes can be marked as needed to be bound diff --git a/include/dt-bindings/dma/k3-udma.h b/include/dt-bindings/dma/k3-udma.h new file mode 100644 index 0000000..670e123 --- /dev/null +++ b/include/dt-bindings/dma/k3-udma.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + */ + +#ifndef __DT_TI_UDMA_H +#define __DT_TI_UDMA_H + +#define UDMA_TR_MODE 0 +#define UDMA_PKT_MODE 1 + +#define UDMA_DIR_TX 0 +#define UDMA_DIR_RX 1 + +#define PSIL_STATIC_TR_NONE 0 +#define PSIL_STATIC_TR_XY 1 +#define PSIL_STATIC_TR_MCAN 2 + +#define UDMA_PDMA_TR_XY(id) \ + ti,psil-config##id { \ + linux,udma-mode = <UDMA_TR_MODE>; \ + statictr-type = <PSIL_STATIC_TR_XY>; \ + } + +#define UDMA_PDMA_PKT_XY(id) \ + ti,psil-config##id { \ + linux,udma-mode = <UDMA_PKT_MODE>; \ + statictr-type = <PSIL_STATIC_TR_XY>; \ + } + +#endif /* __DT_TI_UDMA_H */ diff --git a/include/dt-bindings/mfd/st,stpmic1.h b/include/dt-bindings/mfd/st,stpmic1.h new file mode 100644 index 0000000..b2d6c83 --- /dev/null +++ b/include/dt-bindings/mfd/st,stpmic1.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Philippe Peurichard <philippe.peurichard@st.com>, + * Pascal Paillet <p.paillet@st.com> for STMicroelectronics. + */ + +#ifndef __DT_BINDINGS_STPMIC1_H__ +#define __DT_BINDINGS_STPMIC1_H__ + +/* IRQ definitions */ +#define IT_PONKEY_F 0 +#define IT_PONKEY_R 1 +#define IT_WAKEUP_F 2 +#define IT_WAKEUP_R 3 +#define IT_VBUS_OTG_F 4 +#define IT_VBUS_OTG_R 5 +#define IT_SWOUT_F 6 +#define IT_SWOUT_R 7 + +#define IT_CURLIM_BUCK1 8 +#define IT_CURLIM_BUCK2 9 +#define IT_CURLIM_BUCK3 10 +#define IT_CURLIM_BUCK4 11 +#define IT_OCP_OTG 12 +#define IT_OCP_SWOUT 13 +#define IT_OCP_BOOST 14 +#define IT_OVP_BOOST 15 + +#define IT_CURLIM_LDO1 16 +#define IT_CURLIM_LDO2 17 +#define IT_CURLIM_LDO3 18 +#define IT_CURLIM_LDO4 19 +#define IT_CURLIM_LDO5 20 +#define IT_CURLIM_LDO6 21 +#define IT_SHORT_SWOTG 22 +#define IT_SHORT_SWOUT 23 + +#define IT_TWARN_F 24 +#define IT_TWARN_R 25 +#define IT_VINLOW_F 26 +#define IT_VINLOW_R 27 +#define IT_SWIN_F 30 +#define IT_SWIN_R 31 + +#endif /* __DT_BINDINGS_STPMIC1_H__ */ diff --git a/include/dt-bindings/mfd/st,stpmu1.h b/include/dt-bindings/mfd/st,stpmu1.h deleted file mode 100644 index 81982eb..0000000 --- a/include/dt-bindings/mfd/st,stpmu1.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of stpmu1 pmic driver - * - * Copyright (C) 2017, STMicroelectronics - All Rights Reserved - * Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics. - * - * License type: GPLv2 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __DT_BINDINGS_STPMU1_H__ -#define __DT_BINDINGS_STPMU1_H__ - -/* IRQ definitions */ -#define IT_PONKEY_F 0 -#define IT_PONKEY_R 1 -#define IT_WAKEUP_F 2 -#define IT_WAKEUP_R 3 -#define IT_VBUS_OTG_F 4 -#define IT_VBUS_OTG_R 5 -#define IT_SWOUT_F 6 -#define IT_SWOUT_R 7 - -#define IT_CURLIM_BUCK1 8 -#define IT_CURLIM_BUCK2 9 -#define IT_CURLIM_BUCK3 10 -#define IT_CURLIM_BUCK4 11 -#define IT_OCP_OTG 12 -#define IT_OCP_SWOUT 13 -#define IT_OCP_BOOST 14 -#define IT_OVP_BOOST 15 - -#define IT_CURLIM_LDO1 16 -#define IT_CURLIM_LDO2 17 -#define IT_CURLIM_LDO3 18 -#define IT_CURLIM_LDO4 19 -#define IT_CURLIM_LDO5 20 -#define IT_CURLIM_LDO6 21 -#define IT_SHORT_SWOTG 22 -#define IT_SHORT_SWOUT 23 - -#define IT_TWARN_F 24 -#define IT_TWARN_R 25 -#define IT_VINLOW_F 26 -#define IT_VINLOW_R 27 -#define IT_SWIN_F 30 -#define IT_SWIN_R 31 - -#endif /* __DT_BINDINGS_STPMU1_H__ */ diff --git a/include/dt-bindings/mscc/jr2_data.h b/include/dt-bindings/mscc/jr2_data.h new file mode 100644 index 0000000..2f06fc5 --- /dev/null +++ b/include/dt-bindings/mscc/jr2_data.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2018 Microsemi Corporation + */ + +#ifndef _JR2_DATA_H_ +#define _JR2_DATA_H_ + +#define SERDES1G(x) (x) +#define SERDES1G_MAX SERDES1G(10) +#define SERDES6G(x) (SERDES1G_MAX + 1 + (x)) +#define SERDES6G_MAX SERDES6G(17) +#define SERDES_MAX (SERDES6G_MAX + 1) + +/* similar with phy_interface_t */ +#define PHY_MODE_SGMII 2 +#define PHY_MODE_QSGMII 4 + +#endif diff --git a/include/environment/ti/nand.h b/include/environment/ti/nand.h new file mode 100644 index 0000000..f838cb3 --- /dev/null +++ b/include/environment/ti/nand.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com + * + * Environment variable definitions for NAND on TI boards. + */ + +#ifdef CONFIG_NAND +#define NANDARGS \ + "mtdids=" CONFIG_MTDIDS_DEFAULT "\0" \ + "mtdparts=" CONFIG_MTDPARTS_DEFAULT "\0" \ + "nandargs=setenv bootargs console=${console} " \ + "${optargs} " \ + "root=${nandroot} " \ + "rootfstype=${nandrootfstype}\0" \ + "nandroot=ubi0:rootfs rw ubi.mtd=NAND.file-system,2048\0" \ + "nandrootfstype=ubifs rootwait=1\0" \ + "nandboot=echo Booting from nand ...; " \ + "run nandargs; " \ + "nand read ${fdtaddr} NAND.u-boot-spl-os; " \ + "nand read ${loadaddr} NAND.kernel; " \ + "bootz ${loadaddr} - ${fdtaddr}\0" +#else +#define NANDARGS "" +#endif + diff --git a/include/fdtdec.h b/include/fdtdec.h index ad00f79..266c582 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -23,15 +23,44 @@ */ typedef phys_addr_t fdt_addr_t; typedef phys_size_t fdt_size_t; + +static inline fdt32_t fdt_addr_unpack(fdt_addr_t addr, fdt32_t *upper) +{ + if (upper) +#ifdef CONFIG_PHYS_64BIT + *upper = addr >> 32; +#else + *upper = 0; +#endif + + return addr; +} + +static inline fdt32_t fdt_size_unpack(fdt_size_t size, fdt32_t *upper) +{ + if (upper) +#ifdef CONFIG_PHYS_64BIT + *upper = size >> 32; +#else + *upper = 0; +#endif + + return size; +} + #ifdef CONFIG_PHYS_64BIT #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) +#define cpu_to_fdt_addr(reg) cpu_to_be64(reg) +#define cpu_to_fdt_size(reg) cpu_to_be64(reg) typedef fdt64_t fdt_val_t; #else #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) +#define cpu_to_fdt_addr(reg) cpu_to_be32(reg) +#define cpu_to_fdt_size(reg) cpu_to_be32(reg) typedef fdt32_t fdt_val_t; #endif @@ -992,6 +1021,146 @@ int fdtdec_setup_memory_banksize_fdt(const void *blob); int fdtdec_setup_memory_banksize(void); /** + * fdtdec_set_phandle() - sets the phandle of a given node + * + * @param blob FDT blob + * @param node offset in the FDT blob of the node whose phandle is to + * be set + * @param phandle phandle to set for the given node + * @return 0 on success or a negative error code on failure + */ +int fdtdec_set_phandle(void *blob, int node, uint32_t phandle); + +/** + * fdtdec_add_reserved_memory() - add or find a reserved-memory node + * + * If a reserved-memory node already exists for the given carveout, a phandle + * for that node will be returned. Otherwise a new node will be created and a + * phandle corresponding to it will be returned. + * + * See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt + * for details on how to use reserved memory regions. + * + * As an example, consider the following code snippet: + * + * struct fdt_memory fb = { + * .start = 0x92cb3000, + * .end = 0x934b2fff, + * }; + * uint32_t phandle; + * + * fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, &phandle); + * + * This results in the following subnode being added to the top-level + * /reserved-memory node: + * + * reserved-memory { + * #address-cells = <0x00000002>; + * #size-cells = <0x00000002>; + * ranges; + * + * framebuffer@92cb3000 { + * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>; + * phandle = <0x0000004d>; + * }; + * }; + * + * If the top-level /reserved-memory node does not exist, it will be created. + * The phandle returned from the function call can be used to reference this + * reserved memory region from other nodes. + * + * See fdtdec_set_carveout() for a more elaborate example. + * + * @param blob FDT blob + * @param basename base name of the node to create + * @param carveout information about the carveout region + * @param phandlep return location for the phandle of the carveout region + * @return 0 on success or a negative error code on failure + */ +int fdtdec_add_reserved_memory(void *blob, const char *basename, + const struct fdt_memory *carveout, + uint32_t *phandlep); + +/** + * fdtdec_get_carveout() - reads a carveout from an FDT + * + * Reads information about a carveout region from an FDT. The carveout is a + * referenced by its phandle that is read from a given property in a given + * node. + * + * @param blob FDT blob + * @param node name of a node + * @param name name of the property in the given node that contains + * the phandle for the carveout + * @param index index of the phandle for which to read the carveout + * @param carveout return location for the carveout information + * @return 0 on success or a negative error code on failure + */ +int fdtdec_get_carveout(const void *blob, const char *node, const char *name, + unsigned int index, struct fdt_memory *carveout); + +/** + * fdtdec_set_carveout() - sets a carveout region for a given node + * + * Sets a carveout region for a given node. If a reserved-memory node already + * exists for the carveout, the phandle for that node will be reused. If no + * such node exists, a new one will be created and a phandle to it stored in + * a specified property of the given node. + * + * As an example, consider the following code snippet: + * + * const char *node = "/host1x@50000000/dc@54240000"; + * struct fdt_memory fb = { + * .start = 0x92cb3000, + * .end = 0x934b2fff, + * }; + * + * fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", &fb); + * + * dc@54200000 is a display controller and was set up by the bootloader to + * scan out the framebuffer specified by "fb". This would cause the following + * reserved memory region to be added: + * + * reserved-memory { + * #address-cells = <0x00000002>; + * #size-cells = <0x00000002>; + * ranges; + * + * framebuffer@92cb3000 { + * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>; + * phandle = <0x0000004d>; + * }; + * }; + * + * A "memory-region" property will also be added to the node referenced by the + * offset parameter. + * + * host1x@50000000 { + * ... + * + * dc@54240000 { + * ... + * memory-region = <0x0000004d>; + * ... + * }; + * + * ... + * }; + * + * @param blob FDT blob + * @param node name of the node to add the carveout to + * @param prop_name name of the property in which to store the phandle of + * the carveout + * @param index index of the phandle to store + * @param name base name of the reserved-memory node to create + * @param carveout information about the carveout to add + * @return 0 on success or a negative error code on failure + */ +int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, + unsigned int index, const char *name, + const struct fdt_memory *carveout); + +/** * Set up the device tree ready for use */ int fdtdec_setup(void); diff --git a/include/i2c.h b/include/i2c.h index ccffc19..a5c760c 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -68,9 +68,11 @@ struct dm_i2c_chip { * I2C bus udevice. * * @speed_hz: Bus speed in hertz (typically 100000) + * @max_transaction_bytes: Maximal size of single I2C transfer */ struct dm_i2c_bus { int speed_hz; + int max_transaction_bytes; }; /* diff --git a/include/linux/soc/ti/cppi5.h b/include/linux/soc/ti/cppi5.h new file mode 100644 index 0000000..34038b3 --- /dev/null +++ b/include/linux/soc/ti/cppi5.h @@ -0,0 +1,995 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * CPPI5 descriptors interface + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + */ + +#ifndef __TI_CPPI5_H__ +#define __TI_CPPI5_H__ + +#include <hexdump.h> +#include <linux/bitops.h> + +/** + * Descriptor header, present in all types of descriptors + */ +struct cppi5_desc_hdr_t { + u32 pkt_info0; /* Packet info word 0 (n/a in Buffer desc) */ + u32 pkt_info1; /* Packet info word 1 (n/a in Buffer desc) */ + u32 pkt_info2; /* Packet info word 2 Buffer reclamation info */ + u32 src_dst_tag; /* Packet info word 3 (n/a in Buffer desc) */ +} __packed; + +/** + * Host-mode packet and buffer descriptor definition + */ +struct cppi5_host_desc_t { + struct cppi5_desc_hdr_t hdr; + u64 next_desc; /* w4/5: Linking word */ + u64 buf_ptr; /* w6/7: Buffer pointer */ + u32 buf_info1; /* w8: Buffer valid data length */ + u32 org_buf_len; /* w9: Original buffer length */ + u64 org_buf_ptr; /* w10/11: Original buffer pointer */ + u32 epib[0]; /* Extended Packet Info Data (optional, 4 words) */ + /* + * Protocol Specific Data (optional, 0-128 bytes in multiples of 4), + * and/or Other Software Data (0-N bytes, optional) + */ +} __packed; + +#define CPPI5_DESC_MIN_ALIGN (16U) + +#define CPPI5_INFO0_HDESC_EPIB_SIZE (16U) +#define CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE (128U) + +#define CPPI5_INFO0_HDESC_TYPE_SHIFT (30U) +#define CPPI5_INFO0_HDESC_TYPE_MASK GENMASK(31, 30) +#define CPPI5_INFO0_DESC_TYPE_VAL_HOST (1U) +#define CPPI5_INFO0_DESC_TYPE_VAL_MONO (2U) +#define CPPI5_INFO0_DESC_TYPE_VAL_TR (3U) +#define CPPI5_INFO0_HDESC_EPIB_PRESENT BIT(29) +/* + * Protocol Specific Words location: + * 0 - located in the descriptor, + * 1 = located in the SOP Buffer immediately prior to the data. + */ +#define CPPI5_INFO0_HDESC_PSINFO_LOCATION BIT(28) +#define CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT (22U) +#define CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK GENMASK(27, 22) +#define CPPI5_INFO0_HDESC_PKTLEN_SHIFT (0) +#define CPPI5_INFO0_HDESC_PKTLEN_MASK GENMASK(21, 0) + +#define CPPI5_INFO1_DESC_PKTERROR_SHIFT (28U) +#define CPPI5_INFO1_DESC_PKTERROR_MASK GENMASK(31, 28) +#define CPPI5_INFO1_HDESC_PSFLGS_SHIFT (24U) +#define CPPI5_INFO1_HDESC_PSFLGS_MASK GENMASK(27, 24) +#define CPPI5_INFO1_DESC_PKTID_SHIFT (14U) +#define CPPI5_INFO1_DESC_PKTID_MASK GENMASK(23, 14) +#define CPPI5_INFO1_DESC_FLOWID_SHIFT (0) +#define CPPI5_INFO1_DESC_FLOWID_MASK GENMASK(13, 0) + +#define CPPI5_INFO2_HDESC_PKTTYPE_SHIFT (27U) +#define CPPI5_INFO2_HDESC_PKTTYPE_MASK GENMASK(31, 27) +/* Return Policy: 0 - Entire packet 1 - Each buffer */ +#define CPPI5_INFO2_HDESC_RETPOLICY BIT(18) +/* + * Early Return: + * 0 = desc pointers should be returned after all reads have been completed + * 1 = desc pointers should be returned immediately upon fetching + * the descriptor and beginning to transfer data. + */ +#define CPPI5_INFO2_HDESC_EARLYRET BIT(17) +/* + * Return Push Policy: + * 0 = Descriptor must be returned to tail of queue + * 1 = Descriptor must be returned to head of queue + */ +#define CPPI5_INFO2_DESC_RETPUSHPOLICY BIT(16) +#define CPPI5_INFO2_DESC_RETQ_SHIFT (0) +#define CPPI5_INFO2_DESC_RETQ_MASK GENMASK(15, 0) + +#define CPPI5_INFO3_DESC_SRCTAG_SHIFT (16U) +#define CPPI5_INFO3_DESC_SRCTAG_MASK GENMASK(31, 16) +#define CPPI5_INFO3_DESC_DSTTAG_SHIFT (0) +#define CPPI5_INFO3_DESC_DSTTAG_MASK GENMASK(15, 0) + +#define CPPI5_BUFINFO1_HDESC_DATA_LEN_SHIFT (0) +#define CPPI5_BUFINFO1_HDESC_DATA_LEN_MASK GENMASK(27, 0) + +#define CPPI5_OBUFINFO0_HDESC_BUF_LEN_SHIFT (0) +#define CPPI5_OBUFINFO0_HDESC_BUF_LEN_MASK GENMASK(27, 0) + +/* + * Host Packet Descriptor Extended Packet Info Block + */ +struct cppi5_desc_epib_t { + u32 timestamp; /* w0: application specific timestamp */ + u32 sw_info0; /* w1: Software Info 0 */ + u32 sw_info1; /* w2: Software Info 1 */ + u32 sw_info2; /* w3: Software Info 2 */ +}; + +/** + * Monolithic-mode packet descriptor + */ +struct cppi5_monolithic_desc_t { + struct cppi5_desc_hdr_t hdr; + u32 epib[0]; /* Extended Packet Info Data (optional, 4 words) */ + /* + * Protocol Specific Data (optional, 0-128 bytes in multiples of 4), + * and/or Other Software Data (0-N bytes, optional) + */ +}; + +#define CPPI5_INFO2_MDESC_DATA_OFFSET_SHIFT (18U) +#define CPPI5_INFO2_MDESC_DATA_OFFSET_MASK GENMASK(26, 18) + +/* + * Reload Enable: + * 0 = Finish the packet and place the descriptor back on the return queue + * 1 = Vector to the Reload Index and resume processing + */ +#define CPPI5_INFO0_TRDESC_RLDCNT_SHIFT (20U) +#define CPPI5_INFO0_TRDESC_RLDCNT_MASK GENMASK(28, 20) +#define CPPI5_INFO0_TRDESC_RLDCNT_MAX (0x1ff) +#define CPPI5_INFO0_TRDESC_RLDCNT_INFINITE CPPI5_INFO0_TRDESC_RLDCNT_MAX +#define CPPI5_INFO0_TRDESC_RLDIDX_SHIFT (14U) +#define CPPI5_INFO0_TRDESC_RLDIDX_MASK GENMASK(19, 14) +#define CPPI5_INFO0_TRDESC_RLDIDX_MAX (0x3f) +#define CPPI5_INFO0_TRDESC_LASTIDX_SHIFT (0) +#define CPPI5_INFO0_TRDESC_LASTIDX_MASK GENMASK(13, 0) + +#define CPPI5_INFO1_TRDESC_RECSIZE_SHIFT (24U) +#define CPPI5_INFO1_TRDESC_RECSIZE_MASK GENMASK(26, 24) +#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_16B (0) +#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_32B (1U) +#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_64B (2U) +#define CPPI5_INFO1_TRDESC_RECSIZE_VAL_128B (3U) + +static inline void cppi5_desc_dump(void *desc, u32 size) +{ + print_hex_dump(KERN_ERR "dump udmap_desc: ", DUMP_PREFIX_NONE, + 32, 4, desc, size, false); +} + +/** + * cppi5_desc_get_type - get descriptor type + * @desc_hdr: packet descriptor/TR header + * + * Returns descriptor type: + * CPPI5_INFO0_DESC_TYPE_VAL_HOST + * CPPI5_INFO0_DESC_TYPE_VAL_MONO + * CPPI5_INFO0_DESC_TYPE_VAL_TR + */ +static inline u32 cppi5_desc_get_type(struct cppi5_desc_hdr_t *desc_hdr) +{ + WARN_ON(!desc_hdr); + + return (desc_hdr->pkt_info0 & CPPI5_INFO0_HDESC_TYPE_MASK) >> + CPPI5_INFO0_HDESC_TYPE_SHIFT; +} + +/** + * cppi5_desc_get_errflags - get Error Flags from Desc + * @desc_hdr: packet/TR descriptor header + * + * Returns Error Flags from Packet/TR Descriptor + */ +static inline u32 cppi5_desc_get_errflags(struct cppi5_desc_hdr_t *desc_hdr) +{ + WARN_ON(!desc_hdr); + + return (desc_hdr->pkt_info1 & CPPI5_INFO1_DESC_PKTERROR_MASK) >> + CPPI5_INFO1_DESC_PKTERROR_SHIFT; +} + +/** + * cppi5_desc_get_pktids - get Packet and Flow ids from Desc + * @desc_hdr: packet/TR descriptor header + * @pkt_id: Packet ID + * @flow_id: Flow ID + * + * Returns Packet and Flow ids from packet/TR descriptor + */ +static inline void cppi5_desc_get_pktids(struct cppi5_desc_hdr_t *desc_hdr, + u32 *pkt_id, u32 *flow_id) +{ + WARN_ON(!desc_hdr); + + *pkt_id = (desc_hdr->pkt_info1 & CPPI5_INFO1_DESC_PKTID_MASK) >> + CPPI5_INFO1_DESC_PKTID_SHIFT; + *flow_id = (desc_hdr->pkt_info1 & CPPI5_INFO1_DESC_FLOWID_MASK) >> + CPPI5_INFO1_DESC_FLOWID_SHIFT; +} + +/** + * cppi5_desc_set_pktids - set Packet and Flow ids in Desc + * @desc_hdr: packet/TR descriptor header + * @pkt_id: Packet ID + * @flow_id: Flow ID + */ +static inline void cppi5_desc_set_pktids(struct cppi5_desc_hdr_t *desc_hdr, + u32 pkt_id, u32 flow_id) +{ + WARN_ON(!desc_hdr); + + desc_hdr->pkt_info1 |= (pkt_id << CPPI5_INFO1_DESC_PKTID_SHIFT) & + CPPI5_INFO1_DESC_PKTID_MASK; + desc_hdr->pkt_info1 |= (flow_id << CPPI5_INFO1_DESC_FLOWID_SHIFT) & + CPPI5_INFO1_DESC_FLOWID_MASK; +} + +/** + * cppi5_desc_set_retpolicy - set Packet Return Policy in Desc + * @desc_hdr: packet/TR descriptor header + * @flags: fags, supported values + * CPPI5_INFO2_HDESC_RETPOLICY + * CPPI5_INFO2_HDESC_EARLYRET + * CPPI5_INFO2_DESC_RETPUSHPOLICY + * @return_ring_id: Packet Return Queue/Ring id, value 0xFFFF reserved + */ +static inline void cppi5_desc_set_retpolicy(struct cppi5_desc_hdr_t *desc_hdr, + u32 flags, u32 return_ring_id) +{ + WARN_ON(!desc_hdr); + + desc_hdr->pkt_info2 |= flags; + desc_hdr->pkt_info2 |= return_ring_id & CPPI5_INFO2_DESC_RETQ_MASK; +} + +/** + * cppi5_desc_get_tags_ids - get Packet Src/Dst Tags from Desc + * @desc_hdr: packet/TR descriptor header + * @src_tag_id: Source Tag + * @dst_tag_id: Dest Tag + * + * Returns Packet Src/Dst Tags from packet/TR descriptor + */ +static inline void cppi5_desc_get_tags_ids(struct cppi5_desc_hdr_t *desc_hdr, + u32 *src_tag_id, u32 *dst_tag_id) +{ + WARN_ON(!desc_hdr); + + if (src_tag_id) + *src_tag_id = (desc_hdr->src_dst_tag & + CPPI5_INFO3_DESC_SRCTAG_MASK) >> + CPPI5_INFO3_DESC_SRCTAG_SHIFT; + if (dst_tag_id) + *dst_tag_id = desc_hdr->src_dst_tag & + CPPI5_INFO3_DESC_DSTTAG_MASK; +} + +/** + * cppi5_desc_set_tags_ids - set Packet Src/Dst Tags in HDesc + * @desc_hdr: packet/TR descriptor header + * @src_tag_id: Source Tag + * @dst_tag_id: Dest Tag + * + * Returns Packet Src/Dst Tags from packet/TR descriptor + */ +static inline void cppi5_desc_set_tags_ids(struct cppi5_desc_hdr_t *desc_hdr, + u32 src_tag_id, u32 dst_tag_id) +{ + WARN_ON(!desc_hdr); + + desc_hdr->src_dst_tag = (src_tag_id << CPPI5_INFO3_DESC_SRCTAG_SHIFT) & + CPPI5_INFO3_DESC_SRCTAG_MASK; + desc_hdr->src_dst_tag |= dst_tag_id & CPPI5_INFO3_DESC_DSTTAG_MASK; +} + +/** + * cppi5_hdesc_calc_size - Calculate Host Packet Descriptor size + * @epib: is EPIB present + * @psdata_size: PSDATA size + * @sw_data_size: SWDATA size + * + * Returns required Host Packet Descriptor size + * 0 - if PSDATA > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE + */ +static inline u32 cppi5_hdesc_calc_size(bool epib, u32 psdata_size, + u32 sw_data_size) +{ + u32 desc_size; + + if (psdata_size > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE) + return 0; + //TODO_GS: align + desc_size = sizeof(struct cppi5_host_desc_t) + psdata_size + + sw_data_size; + + if (epib) + desc_size += CPPI5_INFO0_HDESC_EPIB_SIZE; + + return ALIGN(desc_size, CPPI5_DESC_MIN_ALIGN); +} + +/** + * cppi5_hdesc_init - Init Host Packet Descriptor size + * @desc: Host packet descriptor + * @flags: supported values + * CPPI5_INFO0_HDESC_EPIB_PRESENT + * CPPI5_INFO0_HDESC_PSINFO_LOCATION + * @psdata_size: PSDATA size + * + * Returns required Host Packet Descriptor size + * 0 - if PSDATA > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE + */ +static inline void cppi5_hdesc_init(struct cppi5_host_desc_t *desc, u32 flags, + u32 psdata_size) +{ + WARN_ON(!desc); + WARN_ON(psdata_size > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE); + WARN_ON(flags & ~(CPPI5_INFO0_HDESC_EPIB_PRESENT | + CPPI5_INFO0_HDESC_PSINFO_LOCATION)); + + desc->hdr.pkt_info0 = (CPPI5_INFO0_DESC_TYPE_VAL_HOST << + CPPI5_INFO0_HDESC_TYPE_SHIFT) | (flags); + desc->hdr.pkt_info0 |= ((psdata_size >> 2) << + CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT) & + CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK; + desc->next_desc = 0; +} + +/** + * cppi5_hdesc_update_flags - Replace descriptor flags + * @desc: Host packet descriptor + * @flags: supported values + * CPPI5_INFO0_HDESC_EPIB_PRESENT + * CPPI5_INFO0_HDESC_PSINFO_LOCATION + */ +static inline void cppi5_hdesc_update_flags(struct cppi5_host_desc_t *desc, + u32 flags) +{ + WARN_ON(!desc); + WARN_ON(flags & ~(CPPI5_INFO0_HDESC_EPIB_PRESENT | + CPPI5_INFO0_HDESC_PSINFO_LOCATION)); + + desc->hdr.pkt_info0 &= ~(CPPI5_INFO0_HDESC_EPIB_PRESENT | + CPPI5_INFO0_HDESC_PSINFO_LOCATION); + desc->hdr.pkt_info0 |= flags; +} + +/** + * cppi5_hdesc_update_psdata_size - Replace PSdata size + * @desc: Host packet descriptor + * @psdata_size: PSDATA size + */ +static inline void cppi5_hdesc_update_psdata_size( + struct cppi5_host_desc_t *desc, u32 psdata_size) +{ + WARN_ON(!desc); + WARN_ON(psdata_size > CPPI5_INFO0_HDESC_PSDATA_MAX_SIZE); + + desc->hdr.pkt_info0 &= ~CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK; + desc->hdr.pkt_info0 |= ((psdata_size >> 2) << + CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT) & + CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK; +} + +/** + * cppi5_hdesc_get_psdata_size - get PSdata size in bytes + * @desc: Host packet descriptor + */ +static inline u32 cppi5_hdesc_get_psdata_size(struct cppi5_host_desc_t *desc) +{ + u32 psdata_size = 0; + + WARN_ON(!desc); + + if (!(desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PSINFO_LOCATION)) + psdata_size = (desc->hdr.pkt_info0 & + CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK) >> + CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT; + + return (psdata_size << 2); +} + +/** + * cppi5_hdesc_get_pktlen - get Packet Length from HDesc + * @desc: Host packet descriptor + * + * Returns Packet Length from Host Packet Descriptor + */ +static inline u32 cppi5_hdesc_get_pktlen(struct cppi5_host_desc_t *desc) +{ + WARN_ON(!desc); + + return (desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PKTLEN_MASK); +} + +/** + * cppi5_hdesc_set_pktlen - set Packet Length in HDesc + * @desc: Host packet descriptor + */ +static inline void cppi5_hdesc_set_pktlen(struct cppi5_host_desc_t *desc, + u32 pkt_len) +{ + WARN_ON(!desc); + + desc->hdr.pkt_info0 |= (pkt_len & CPPI5_INFO0_HDESC_PKTLEN_MASK); +} + +/** + * cppi5_hdesc_get_psflags - get Protocol Specific Flags from HDesc + * @desc: Host packet descriptor + * + * Returns Protocol Specific Flags from Host Packet Descriptor + */ +static inline u32 cppi5_hdesc_get_psflags(struct cppi5_host_desc_t *desc) +{ + WARN_ON(!desc); + + return (desc->hdr.pkt_info1 & CPPI5_INFO1_HDESC_PSFLGS_MASK) >> + CPPI5_INFO1_HDESC_PSFLGS_SHIFT; +} + +/** + * cppi5_hdesc_set_psflags - set Protocol Specific Flags in HDesc + * @desc: Host packet descriptor + */ +static inline void cppi5_hdesc_set_psflags(struct cppi5_host_desc_t *desc, + u32 ps_flags) +{ + WARN_ON(!desc); + + desc->hdr.pkt_info1 |= (ps_flags << + CPPI5_INFO1_HDESC_PSFLGS_SHIFT) & + CPPI5_INFO1_HDESC_PSFLGS_MASK; +} + +/** + * cppi5_hdesc_get_errflags - get Packet Type from HDesc + * @desc: Host packet descriptor + */ +static inline u32 cppi5_hdesc_get_pkttype(struct cppi5_host_desc_t *desc) +{ + WARN_ON(!desc); + + return (desc->hdr.pkt_info2 & CPPI5_INFO2_HDESC_PKTTYPE_MASK) >> + CPPI5_INFO2_HDESC_PKTTYPE_SHIFT; +} + +/** + * cppi5_hdesc_get_errflags - set Packet Type in HDesc + * @desc: Host packet descriptor + * @pkt_type: Packet Type + */ +static inline void cppi5_hdesc_set_pkttype(struct cppi5_host_desc_t *desc, + u32 pkt_type) +{ + WARN_ON(!desc); + desc->hdr.pkt_info2 |= + (pkt_type << CPPI5_INFO2_HDESC_PKTTYPE_SHIFT) & + CPPI5_INFO2_HDESC_PKTTYPE_MASK; +} + +/** + * cppi5_hdesc_attach_buf - attach buffer to HDesc + * @desc: Host packet descriptor + * @buf: Buffer physical address + * @buf_data_len: Buffer length + * @obuf: Original Buffer physical address + * @obuf_len: Original Buffer length + * + * Attaches buffer to Host Packet Descriptor + */ +static inline void cppi5_hdesc_attach_buf(struct cppi5_host_desc_t *desc, + dma_addr_t buf, u32 buf_data_len, + dma_addr_t obuf, u32 obuf_len) +{ + WARN_ON(!desc); + WARN_ON(!buf && !obuf); + + desc->buf_ptr = buf; + desc->buf_info1 = buf_data_len & CPPI5_BUFINFO1_HDESC_DATA_LEN_MASK; + desc->org_buf_ptr = obuf; + desc->org_buf_len = obuf_len & CPPI5_OBUFINFO0_HDESC_BUF_LEN_MASK; +} + +static inline void cppi5_hdesc_get_obuf(struct cppi5_host_desc_t *desc, + dma_addr_t *obuf, u32 *obuf_len) +{ + WARN_ON(!desc); + WARN_ON(!obuf); + WARN_ON(!obuf_len); + + *obuf = desc->org_buf_ptr; + *obuf_len = desc->org_buf_len & CPPI5_OBUFINFO0_HDESC_BUF_LEN_MASK; +} + +static inline void cppi5_hdesc_reset_to_original(struct cppi5_host_desc_t *desc) +{ + WARN_ON(!desc); + + desc->buf_ptr = desc->org_buf_ptr; + desc->buf_info1 = desc->org_buf_len; +} + +/** + * cppi5_hdesc_link_hbdesc - link Host Buffer Descriptor to HDesc + * @desc: Host Packet Descriptor + * @buf_desc: Host Buffer Descriptor physical address + * + * add and link Host Buffer Descriptor to HDesc + */ +static inline void cppi5_hdesc_link_hbdesc(struct cppi5_host_desc_t *desc, + dma_addr_t hbuf_desc) +{ + WARN_ON(!desc); + WARN_ON(!hbuf_desc); + + desc->next_desc = hbuf_desc; +} + +static inline dma_addr_t cppi5_hdesc_get_next_hbdesc( + struct cppi5_host_desc_t *desc) +{ + WARN_ON(!desc); + + return (dma_addr_t)desc->next_desc; +} + +static inline void cppi5_hdesc_reset_hbdesc(struct cppi5_host_desc_t *desc) +{ + WARN_ON(!desc); + + desc->hdr = (struct cppi5_desc_hdr_t) { 0 }; + desc->next_desc = 0; +} + +/** + * cppi5_hdesc_epib_present - check if EPIB present + * @desc_hdr: packet descriptor/TR header + * + * Returns true if EPIB present in the packet + */ +static inline bool cppi5_hdesc_epib_present(struct cppi5_desc_hdr_t *desc_hdr) +{ + WARN_ON(!desc_hdr); + return !!(desc_hdr->pkt_info0 & CPPI5_INFO0_HDESC_EPIB_PRESENT); +} + +/** + * cppi5_hdesc_get_psdata - Get pointer on PSDATA + * @desc: Host packet descriptor + * + * Returns pointer on PSDATA in HDesc. + * NULL - if ps_data placed at the start of data buffer. + */ +static inline void *cppi5_hdesc_get_psdata(struct cppi5_host_desc_t *desc) +{ + u32 psdata_size; + void *psdata; + + WARN_ON(!desc); + + if (desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PSINFO_LOCATION) + return NULL; + + psdata_size = (desc->hdr.pkt_info0 & + CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK) >> + CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT; + + if (!psdata_size) + return NULL; + + psdata = &desc->epib; + + if (cppi5_hdesc_epib_present(&desc->hdr)) + psdata += CPPI5_INFO0_HDESC_EPIB_SIZE; + + return psdata; +} + +static inline u32 *cppi5_hdesc_get_psdata32(struct cppi5_host_desc_t *desc) +{ + return (u32 *)cppi5_hdesc_get_psdata(desc); +} + +/** + * cppi5_hdesc_get_swdata - Get pointer on swdata + * @desc: Host packet descriptor + * + * Returns pointer on SWDATA in HDesc. + * NOTE. It's caller responsibility to be sure hdesc actually has swdata. + */ +static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc) +{ + u32 psdata_size = 0; + void *swdata; + + WARN_ON(!desc); + + if (!(desc->hdr.pkt_info0 & CPPI5_INFO0_HDESC_PSINFO_LOCATION)) + psdata_size = (desc->hdr.pkt_info0 & + CPPI5_INFO0_HDESC_PSINFO_SIZE_MASK) >> + CPPI5_INFO0_HDESC_PSINFO_SIZE_SHIFT; + + swdata = &desc->epib; + + if (cppi5_hdesc_epib_present(&desc->hdr)) + swdata += CPPI5_INFO0_HDESC_EPIB_SIZE; + + swdata += (psdata_size << 2); + + return swdata; +} + +/* ================================== TR ================================== */ + +#define CPPI5_TR_TYPE_SHIFT (0U) +#define CPPI5_TR_TYPE_MASK GENMASK(3, 0) +#define CPPI5_TR_STATIC BIT(4) +#define CPPI5_TR_WAIT BIT(5) +#define CPPI5_TR_EVENT_SIZE_SHIFT (6U) +#define CPPI5_TR_EVENT_SIZE_MASK GENMASK(7, 6) +#define CPPI5_TR_TRIGGER0_SHIFT (8U) +#define CPPI5_TR_TRIGGER0_MASK GENMASK(9, 8) +#define CPPI5_TR_TRIGGER0_TYPE_SHIFT (10U) +#define CPPI5_TR_TRIGGER0_TYPE_MASK GENMASK(11, 10) +#define CPPI5_TR_TRIGGER1_SHIFT (12U) +#define CPPI5_TR_TRIGGER1_MASK GENMASK(13, 12) +#define CPPI5_TR_TRIGGER1_TYPE_SHIFT (14U) +#define CPPI5_TR_TRIGGER1_TYPE_MASK GENMASK(15, 14) +#define CPPI5_TR_CMD_ID_SHIFT (16U) +#define CPPI5_TR_CMD_ID_MASK GENMASK(23, 16) +#define CPPI5_TR_CSF_FLAGS_SHIFT (24U) +#define CPPI5_TR_CSF_FLAGS_MASK GENMASK(31, 24) +#define CPPI5_TR_CSF_SA_INDIRECT BIT(0) +#define CPPI5_TR_CSF_DA_INDIRECT BIT(1) +#define CPPI5_TR_CSF_SUPR_EVT BIT(2) +#define CPPI5_TR_CSF_EOL_ADV_SHIFT (4U) +#define CPPI5_TR_CSF_EOL_ADV_MASK GENMASK(6, 4) +#define CPPI5_TR_CSF_EOP BIT(7) + +/* Udmap TR flags Type field specifies the type of TR. */ +enum cppi5_tr_types { + /* type0: One dimensional data move */ + CPPI5_TR_TYPE0 = 0, + /* type1: Two dimensional data move */ + CPPI5_TR_TYPE1, + /* type2: Three dimensional data move */ + CPPI5_TR_TYPE2, + /* type3: Four dimensional data move */ + CPPI5_TR_TYPE3, + /* type4: Four dimensional data move with data formatting */ + CPPI5_TR_TYPE4, + /* type5: Four dimensional Cache Warm */ + CPPI5_TR_TYPE5, + /* type6-7: Reserved */ + /* type8: Four Dimensional Block Move */ + CPPI5_TR_TYPE8 = 8, + /* type9: Four Dimensional Block Move with Repacking */ + CPPI5_TR_TYPE9, + /* type10: Two Dimensional Block Move */ + CPPI5_TR_TYPE10, + /* type11: Two Dimensional Block Move with Repacking */ + CPPI5_TR_TYPE11, + /* type12-14: Reserved */ + /* type15 Four Dimensional Block Move with Repacking and Indirection */ + CPPI5_TR_TYPE15 = 15, + CPPI5_TR_TYPE_MAX +}; + +/* + * Udmap TR Flags EVENT_SIZE field specifies when an event is generated + * for each TR. + */ +enum cppi5_tr_event_size { + /* When TR is complete and all status for the TR has been received */ + CPPI5_TR_EVENT_SIZE_COMPLETION, + /* + * Type 0: when the last data transaction is sent for the TR; + * Type 1-11: when ICNT1 is decremented + */ + CPPI5_TR_EVENT_SIZE_ICNT1_DEC, + /* + * Type 0-1,10-11: when the last data transaction is sent for the TR; + * All other types: when ICNT2 is decremented + */ + CPPI5_TR_EVENT_SIZE_ICNT2_DEC, + /* + * Type 0-2,10-11: when the last data transaction is sent for the TR; + * All other types: when ICNT3 is decremented + */ + CPPI5_TR_EVENT_SIZE_ICNT3_DEC, + CPPI5_TR_EVENT_SIZE_MAX +}; + +/* + * Udmap TR Flags TRIGGERx field specifies the type of trigger used to + * enable the TR to transfer data as specified by TRIGGERx_TYPE field. + */ +enum cppi5_tr_trigger { + CPPI5_TR_TRIGGER_NONE, /* No Trigger */ + CPPI5_TR_TRIGGER_GLOBAL0, /* Global Trigger 0 */ + CPPI5_TR_TRIGGER_GLOBAL1, /* Global Trigger 1 */ + CPPI5_TR_TRIGGER_LOCAL_EVENT, /* Local Event */ + CPPI5_TR_TRIGGER_MAX +}; + +/* + * Udmap TR Flags TRIGGERx_TYPE field specifies the type of data transfer + * that will be enabled by receiving a trigger as specified by TRIGGERx. + */ +enum cppi5_tr_trigger_type { + /* The second inner most loop (ICNT1) will be decremented by 1 */ + CPPI5_TR_TRIGGER_TYPE_ICNT1_DEC, + /* The third inner most loop (ICNT2) will be decremented by 1 */ + CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC, + /* The outer most loop (ICNT3) will be decremented by 1 */ + CPPI5_TR_TRIGGER_TYPE_ICNT3_DEC, + /* The entire TR will be allowed to complete */ + CPPI5_TR_TRIGGER_TYPE_ALL, + CPPI5_TR_TRIGGER_TYPE_MAX +}; + +typedef u32 cppi5_tr_flags_t; + +/* Type 0 (One dimensional data move) TR (16 byte) */ +struct cppi5_tr_type0_t { + cppi5_tr_flags_t flags; + u16 icnt0; + u16 unused; + u64 addr; +} __aligned(16) __packed; + +/* Type 1 (Two dimensional data move) TR (32 byte) */ +struct cppi5_tr_type1_t { + cppi5_tr_flags_t flags; + u16 icnt0; + u16 icnt1; + u64 addr; + s32 dim1; +} __aligned(32) __packed; + +/* Type 2 (Three dimensional data move) TR (32 byte) */ +struct cppi5_tr_type2_t { + cppi5_tr_flags_t flags; + u16 icnt0; + u16 icnt1; + u64 addr; + s32 dim1; + u16 icnt2; + u16 unused; + s32 dim2; +} __aligned(32) __packed; + +/* Type 3 (Four dimensional data move) TR (32 byte) */ +struct cppi5_tr_type3_t { + cppi5_tr_flags_t flags; + u16 icnt0; + u16 icnt1; + u64 addr; + s32 dim1; + u16 icnt2; + u16 icnt3; + s32 dim2; + s32 dim3; +} __aligned(32) __packed; + +/* + * Type 15 (Four Dimensional Block Copy with Repacking and + * Indirection Support) TR (64 byte). + */ +struct cppi5_tr_type15_t { + cppi5_tr_flags_t flags; + u16 icnt0; + u16 icnt1; + u64 addr; + s32 dim1; + u16 icnt2; + u16 icnt3; + s32 dim2; + s32 dim3; + u32 _reserved; + s32 ddim1; + u64 daddr; + s32 ddim2; + s32 ddim3; + u16 dicnt0; + u16 dicnt1; + u16 dicnt2; + u16 dicnt3; +} __aligned(64) __packed; + +struct cppi5_tr_resp_t { + u8 status; + u8 reserved; + u8 cmd_id; + u8 flags; +} __packed; + +#define CPPI5_TR_RESPONSE_STATUS_TYPE_SHIFT (0U) +#define CPPI5_TR_RESPONSE_STATUS_TYPE_MASK GENMASK(3, 0) +#define CPPI5_TR_RESPONSE_STATUS_INFO_SHIFT (4U) +#define CPPI5_TR_RESPONSE_STATUS_INFO_MASK GENMASK(7, 4) +#define CPPI5_TR_RESPONSE_CMDID_SHIFT (16U) +#define CPPI5_TR_RESPONSE_CMDID_MASK GENMASK(23, 16) +#define CPPI5_TR_RESPONSE_CFG_SPECIFIC_SHIFT (24U) +#define CPPI5_TR_RESPONSE_CFG_SPECIFIC_MASK GENMASK(31, 24) + +/* + * Udmap TR Response Status Type field is used to determine + * what type of status is being returned. + */ +enum cppi5_tr_resp_status_type { + CPPI5_TR_RESPONSE_STATUS_COMPLETE, /* None */ + CPPI5_TR_RESPONSE_STATUS_TRANSFER_ERR, /* Transfer Error */ + CPPI5_TR_RESPONSE_STATUS_ABORTED_ERR, /* Aborted Error */ + CPPI5_TR_RESPONSE_STATUS_SUBMISSION_ERR, /* Submission Error */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_ERR, /* Unsup. Feature */ + CPPI5_TR_RESPONSE_STATUS_MAX +}; + +/* + * Udmap TR Response Status field values which corresponds + * CPPI5_TR_RESPONSE_STATUS_SUBMISSION_ERR + */ +enum cppi5_tr_resp_status_submission { + /* ICNT0 was 0 */ + CPPI5_TR_RESPONSE_STATUS_SUBMISSION_ICNT0, + /* Channel FIFO was full when TR received */ + CPPI5_TR_RESPONSE_STATUS_SUBMISSION_FIFO_FULL, + /* Channel is not owned by the submitter */ + CPPI5_TR_RESPONSE_STATUS_SUBMISSION_OWN, + CPPI5_TR_RESPONSE_STATUS_SUBMISSION_MAX +}; + +/* + * Udmap TR Response Status field values which corresponds + * CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_ERR + */ +enum cppi5_tr_resp_status_unsupported { + /* TR Type not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_TR_TYPE, + /* STATIC not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_STATIC, + /* EOL not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_EOL, + /* CONFIGURATION SPECIFIC not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_CFG_SPECIFIC, + /* AMODE not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_AMODE, + /* ELTYPE not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_ELTYPE, + /* DFMT not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_DFMT, + /* SECTR not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_SECTR, + /* AMODE SPECIFIC field not supported */ + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_AMODE_SPECIFIC, + CPPI5_TR_RESPONSE_STATUS_UNSUPPORTED_MAX +}; + +/** + * cppi5_trdesc_calc_size - Calculate TR Descriptor size + * @tr_count: number of TR records + * @tr_size: Nominal size of TR record (max) [16, 32, 64, 128] + * + * Returns required TR Descriptor size + */ +static inline size_t cppi5_trdesc_calc_size(u32 tr_count, u32 tr_size) +{ + /* + * The Size of a TR descriptor is: + * 1 x tr_size : the first 16 bytes is used by the packet info block + + * tr_count x tr_size : Transfer Request Records + + * tr_count x sizeof(struct cppi5_tr_resp_t) : Transfer Response Records + */ + return tr_size * (tr_count + 1) + + sizeof(struct cppi5_tr_resp_t) * tr_count; +} + +/** + * cppi5_trdesc_init - Init TR Descriptor + * @desc: TR Descriptor + * @tr_count: number of TR records + * @tr_size: Nominal size of TR record (max) [16, 32, 64, 128] + * @reload_idx: Absolute index to jump to on the 2nd and following passes + * through the TR packet. + * @reload_count: Number of times to jump from last entry to reload_idx. 0x1ff + * indicates infinite looping. + * + * Init TR Descriptor + */ +static inline void cppi5_trdesc_init(struct cppi5_desc_hdr_t *desc_hdr, + u32 tr_count, u32 tr_size, u32 reload_idx, + u32 reload_count) +{ + WARN_ON(!desc_hdr); + WARN_ON(tr_count & ~CPPI5_INFO0_TRDESC_LASTIDX_MASK); + WARN_ON(reload_idx > CPPI5_INFO0_TRDESC_RLDIDX_MAX); + WARN_ON(reload_count > CPPI5_INFO0_TRDESC_RLDCNT_MAX); + + desc_hdr->pkt_info0 = CPPI5_INFO0_DESC_TYPE_VAL_TR << + CPPI5_INFO0_HDESC_TYPE_SHIFT; + desc_hdr->pkt_info0 |= (reload_count << CPPI5_INFO0_TRDESC_RLDCNT_SHIFT) & + CPPI5_INFO0_TRDESC_RLDCNT_MASK; + desc_hdr->pkt_info0 |= (reload_idx << CPPI5_INFO0_TRDESC_RLDIDX_SHIFT) & + CPPI5_INFO0_TRDESC_RLDIDX_MASK; + desc_hdr->pkt_info0 |= (tr_count - 1) & CPPI5_INFO0_TRDESC_LASTIDX_MASK; + + desc_hdr->pkt_info1 |= ((ffs(tr_size >> 4) - 1) << + CPPI5_INFO1_TRDESC_RECSIZE_SHIFT) & + CPPI5_INFO1_TRDESC_RECSIZE_MASK; +} + +/** + * cppi5_tr_init - Init TR record + * @flags: Pointer to the TR's flags + * @type: TR type + * @static_tr: TR is static + * @wait: Wait for TR completion before allow the next TR to start + * @event_size: output event generation cfg + * @cmd_id: TR identifier (application specifics) + * + * Init TR record + */ +static inline void cppi5_tr_init(cppi5_tr_flags_t *flags, + enum cppi5_tr_types type, bool static_tr, + bool wait, enum cppi5_tr_event_size event_size, + u32 cmd_id) +{ + WARN_ON(!flags); + + *flags = type; + *flags |= (event_size << CPPI5_TR_EVENT_SIZE_SHIFT) & + CPPI5_TR_EVENT_SIZE_MASK; + + *flags |= (cmd_id << CPPI5_TR_CMD_ID_SHIFT) & + CPPI5_TR_CMD_ID_MASK; + + if (static_tr && (type == CPPI5_TR_TYPE8 || type == CPPI5_TR_TYPE9)) + *flags |= CPPI5_TR_STATIC; + + if (wait) + *flags |= CPPI5_TR_WAIT; +} + +/** + * cppi5_tr_set_trigger - Configure trigger0/1 and trigger0/1_type + * @flags: Pointer to the TR's flags + * @trigger0: trigger0 selection + * @trigger0_type: type of data transfer that will be enabled by trigger0 + * @trigger1: trigger1 selection + * @trigger1_type: type of data transfer that will be enabled by trigger1 + * + * Configure the triggers for the TR + */ +static inline void cppi5_tr_set_trigger(cppi5_tr_flags_t *flags, + enum cppi5_tr_trigger trigger0, + enum cppi5_tr_trigger_type trigger0_type, + enum cppi5_tr_trigger trigger1, + enum cppi5_tr_trigger_type trigger1_type) +{ + WARN_ON(!flags); + + *flags |= (trigger0 << CPPI5_TR_TRIGGER0_SHIFT) & + CPPI5_TR_TRIGGER0_MASK; + *flags |= (trigger0_type << CPPI5_TR_TRIGGER0_TYPE_SHIFT) & + CPPI5_TR_TRIGGER0_TYPE_MASK; + + *flags |= (trigger1 << CPPI5_TR_TRIGGER1_SHIFT) & + CPPI5_TR_TRIGGER1_MASK; + *flags |= (trigger1_type << CPPI5_TR_TRIGGER1_TYPE_SHIFT) & + CPPI5_TR_TRIGGER1_TYPE_MASK; +} + +/** + * cppi5_tr_cflag_set - Update the Configuration specific flags + * @flags: Pointer to the TR's flags + * @csf: Configuration specific flags + * + * Set a bit in Configuration Specific Flags section of the TR flags. + */ +static inline void cppi5_tr_csf_set(cppi5_tr_flags_t *flags, u32 csf) +{ + WARN_ON(!flags); + + *flags |= (csf << CPPI5_TR_CSF_FLAGS_SHIFT) & + CPPI5_TR_CSF_FLAGS_MASK; +} + +#endif /* __TI_CPPI5_H__ */ diff --git a/include/linux/soc/ti/k3-navss-ringacc.h b/include/linux/soc/ti/k3-navss-ringacc.h new file mode 100644 index 0000000..487dfe9 --- /dev/null +++ b/include/linux/soc/ti/k3-navss-ringacc.h @@ -0,0 +1,236 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * TI K3 AM65x NAVSS Ring accelerator Manager (RA) subsystem driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + */ + +#ifndef __SOC_TI_K3_NAVSS_RINGACC_API_H_ +#define __SOC_TI_K3_NAVSS_RINGACC_API_H_ + +#include <dm/ofnode.h> + +/** + * enum k3_nav_ring_mode - &struct k3_nav_ring_cfg mode + * + * RA ring operational modes + * + * @K3_NAV_RINGACC_RING_MODE_RING: Exposed Ring mode for SW direct access + * @K3_NAV_RINGACC_RING_MODE_MESSAGE: Messaging mode. Messaging mode requires + * that all accesses to the queue must go through this IP so that all + * accesses to the memory are controlled and ordered. This IP then + * controls the entire state of the queue, and SW has no directly control, + * such as through doorbells and cannot access the storage memory directly. + * This is particularly useful when more than one SW or HW entity can be + * the producer and/or consumer at the same time + * @K3_NAV_RINGACC_RING_MODE_CREDENTIALS: Credentials mode is message mode plus + * stores credentials with each message, requiring the element size to be + * doubled to fit the credentials. Any exposed memory should be protected + * by a firewall from unwanted access + * @K3_NAV_RINGACC_RING_MODE_QM: Queue manager mode. This takes the credentials + * mode and adds packet length per element, along with additional read only + * fields for element count and accumulated queue length. The QM mode only + * operates with an 8 byte element size (any other element size is + * illegal), and like in credentials mode each operation uses 2 element + * slots to store the credentials and length fields + */ +enum k3_nav_ring_mode { + K3_NAV_RINGACC_RING_MODE_RING = 0, + K3_NAV_RINGACC_RING_MODE_MESSAGE, + K3_NAV_RINGACC_RING_MODE_CREDENTIALS, + K3_NAV_RINGACC_RING_MODE_QM, + k3_NAV_RINGACC_RING_MODE_INVALID +}; + +/** + * enum k3_nav_ring_size - &struct k3_nav_ring_cfg elm_size + * + * RA ring element's sizes in bytes. + */ +enum k3_nav_ring_size { + K3_NAV_RINGACC_RING_ELSIZE_4 = 0, + K3_NAV_RINGACC_RING_ELSIZE_8, + K3_NAV_RINGACC_RING_ELSIZE_16, + K3_NAV_RINGACC_RING_ELSIZE_32, + K3_NAV_RINGACC_RING_ELSIZE_64, + K3_NAV_RINGACC_RING_ELSIZE_128, + K3_NAV_RINGACC_RING_ELSIZE_256, + K3_NAV_RINGACC_RING_ELSIZE_INVALID +}; + +struct k3_nav_ringacc; +struct k3_nav_ring; + +/** + * enum k3_nav_ring_cfg - RA ring configuration structure + * + * @size: Ring size, number of elements + * @elm_size: Ring element size + * @mode: Ring operational mode + * @flags: Ring configuration flags. Possible values: + * @K3_NAV_RINGACC_RING_SHARED: when set allows to request the same ring + * few times. It's usable when the same ring is used as Free Host PD ring + * for different flows, for example. + * Note: Locking should be done by consumer if required + */ +struct k3_nav_ring_cfg { + u32 size; + enum k3_nav_ring_size elm_size; + enum k3_nav_ring_mode mode; +#define K3_NAV_RINGACC_RING_SHARED BIT(1) + u32 flags; +}; + +#define K3_NAV_RINGACC_RING_ID_ANY (-1) +#define K3_NAV_RINGACC_RING_USE_PROXY BIT(1) + +/** + * k3_nav_ringacc_request_ring - request ring from ringacc + * @ringacc: pointer on ringacc + * @id: ring id or K3_NAV_RINGACC_RING_ID_ANY for any general purpose ring + * @flags: + * @K3_NAV_RINGACC_RING_USE_PROXY: if set - proxy will be allocated and + * used to access ring memory. Sopported only for rings in + * Message/Credentials/Queue mode. + * + * Returns pointer on the Ring - struct k3_nav_ring + * or NULL in case of failure. + */ +struct k3_nav_ring *k3_nav_ringacc_request_ring(struct k3_nav_ringacc *ringacc, + int id, u32 flags); + +/** + * k3_nav_ringacc_get_dev - get pointer on RA device + * @ringacc: pointer on RA + * + * Returns device pointer + */ +struct udevice *k3_nav_ringacc_get_dev(struct k3_nav_ringacc *ringacc); + +/** + * k3_nav_ringacc_ring_reset - ring reset + * @ring: pointer on Ring + * + * Resets ring internal state ((hw)occ, (hw)idx). + * TODO_GS: ? Ring can be reused without reconfiguration + */ +void k3_nav_ringacc_ring_reset(struct k3_nav_ring *ring); +/** + * k3_nav_ringacc_ring_reset - ring reset for DMA rings + * @ring: pointer on Ring + * + * Resets ring internal state ((hw)occ, (hw)idx). Should be used for rings + * which are read by K3 UDMA, like TX or Free Host PD rings. + */ +void k3_nav_ringacc_ring_reset_dma(struct k3_nav_ring *ring, u32 occ); + +/** + * k3_nav_ringacc_ring_free - ring free + * @ring: pointer on Ring + * + * Resets ring and free all alocated resources. + */ +int k3_nav_ringacc_ring_free(struct k3_nav_ring *ring); + +/** + * k3_nav_ringacc_get_ring_id - Get the Ring ID + * @ring: pointer on ring + * + * Returns the Ring ID + */ +u32 k3_nav_ringacc_get_ring_id(struct k3_nav_ring *ring); + +/** + * k3_nav_ringacc_ring_cfg - ring configure + * @ring: pointer on ring + * @cfg: Ring configuration parameters (see &struct k3_nav_ring_cfg) + * + * Configures ring, including ring memory allocation. + * Returns 0 on success, errno otherwise. + */ +int k3_nav_ringacc_ring_cfg(struct k3_nav_ring *ring, + struct k3_nav_ring_cfg *cfg); + +/** + * k3_nav_ringacc_ring_get_size - get ring size + * @ring: pointer on ring + * + * Returns ring size in number of elements. + */ +u32 k3_nav_ringacc_ring_get_size(struct k3_nav_ring *ring); + +/** + * k3_nav_ringacc_ring_get_free - get free elements + * @ring: pointer on ring + * + * Returns number of free elements in the ring. + */ +u32 k3_nav_ringacc_ring_get_free(struct k3_nav_ring *ring); + +/** + * k3_nav_ringacc_ring_get_occ - get ring occupancy + * @ring: pointer on ring + * + * Returns total number of valid entries on the ring + */ +u32 k3_nav_ringacc_ring_get_occ(struct k3_nav_ring *ring); + +/** + * k3_nav_ringacc_ring_is_full - checks if ring is full + * @ring: pointer on ring + * + * Returns true if the ring is full + */ +u32 k3_nav_ringacc_ring_is_full(struct k3_nav_ring *ring); + +/** + * k3_nav_ringacc_ring_push - push element to the ring tail + * @ring: pointer on ring + * @elem: pointer on ring element buffer + * + * Push one ring element to the ring tail. Size of the ring element is + * determined by ring configuration &struct k3_nav_ring_cfg elm_size. + * + * Returns 0 on success, errno otherwise. + */ +int k3_nav_ringacc_ring_push(struct k3_nav_ring *ring, void *elem); + +/** + * k3_nav_ringacc_ring_pop - pop element from the ring head + * @ring: pointer on ring + * @elem: pointer on ring element buffer + * + * Push one ring element from the ring head. Size of the ring element is + * determined by ring configuration &struct k3_nav_ring_cfg elm_size.. + * + * Returns 0 on success, errno otherwise. + */ +int k3_nav_ringacc_ring_pop(struct k3_nav_ring *ring, void *elem); + +/** + * k3_nav_ringacc_ring_push_head - push element to the ring head + * @ring: pointer on ring + * @elem: pointer on ring element buffer + * + * Push one ring element to the ring head. Size of the ring element is + * determined by ring configuration &struct k3_nav_ring_cfg elm_size. + * + * Returns 0 on success, errno otherwise. + * Not Supported by ring modes: K3_NAV_RINGACC_RING_MODE_RING + */ +int k3_nav_ringacc_ring_push_head(struct k3_nav_ring *ring, void *elem); + +/** + * k3_nav_ringacc_ring_pop_tail - pop element from the ring tail + * @ring: pointer on ring + * @elem: pointer on ring element buffer + * + * Push one ring element from the ring tail. Size of the ring element is + * determined by ring configuration &struct k3_nav_ring_cfg elm_size. + * + * Returns 0 on success, errno otherwise. + * Not Supported by ring modes: K3_NAV_RINGACC_RING_MODE_RING + */ +int k3_nav_ringacc_ring_pop_tail(struct k3_nav_ring *ring, void *elem); + +#endif /* __SOC_TI_K3_NAVSS_RINGACC_API_H_ */ diff --git a/include/linux/soc/ti/ti-udma.h b/include/linux/soc/ti/ti-udma.h new file mode 100644 index 0000000..e9d4226 --- /dev/null +++ b/include/linux/soc/ti/ti-udma.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> + */ + +#ifndef __TI_UDMA_H +#define __TI_UDMA_H + +/** + * struct ti_udma_drv_packet_data - TI UDMA transfer specific data + * + * @pkt_type: Packet Type - specific for each DMA client HW + * @dest_tag: Destination tag The source pointer. + * + * TI UDMA transfer specific data passed as part of DMA transfer to + * the DMA client HW in UDMA descriptors. + */ +struct ti_udma_drv_packet_data { + u32 pkt_type; + u32 dest_tag; +}; + +#endif /* __TI_UDMA_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h index 90d5053..222cf66 100644 --- a/include/linux/soc/ti/ti_sci_protocol.h +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -213,13 +213,42 @@ struct ti_sci_clk_ops { }; /** + * struct ti_sci_rm_core_ops - Resource management core operations + * @get_range: Get a range of resources belonging to ti sci host. + * @get_rage_from_shost: Get a range of resources belonging to + * specified host id. + * - s_host: Host processing entity to which the + * resources are allocated + * + * NOTE: for these functions, all the parameters are consolidated and defined + * as below: + * - handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * - dev_id: TISCI device ID. + * - subtype: Resource assignment subtype that is being requested + * from the given device. + * - range_start: Start index of the resource range + * - range_end: Number of resources in the range + */ +struct ti_sci_rm_core_ops { + int (*get_range)(const struct ti_sci_handle *handle, u32 dev_id, + u8 subtype, u16 *range_start, u16 *range_num); + int (*get_range_from_shost)(const struct ti_sci_handle *handle, + u32 dev_id, u8 subtype, u8 s_host, + u16 *range_start, u16 *range_num); +}; + +/** * struct ti_sci_core_ops - SoC Core Operations * @reboot_device: Reboot the SoC * Returns 0 for successful request(ideally should never return), * else returns corresponding error value. + * @query_msmc: Query the size of available msmc + * Return 0 for successful query else appropriate error value. */ struct ti_sci_core_ops { int (*reboot_device)(const struct ti_sci_handle *handle); + int (*query_msmc)(const struct ti_sci_handle *handle, + u64 *msmc_start, u64 *msmc_end); }; /** @@ -257,6 +286,230 @@ struct ti_sci_proc_ops { u32 *sts_flags); }; +#define TI_SCI_RING_MODE_RING (0) +#define TI_SCI_RING_MODE_MESSAGE (1) +#define TI_SCI_RING_MODE_CREDENTIALS (2) +#define TI_SCI_RING_MODE_QM (3) + +#define TI_SCI_MSG_UNUSED_SECONDARY_HOST TI_SCI_RM_NULL_U8 + +/* RA config.addr_lo parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID BIT(0) +/* RA config.addr_hi parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID BIT(1) + /* RA config.count parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID BIT(2) +/* RA config.mode parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_MODE_VALID BIT(3) +/* RA config.size parameter is valid for RM ring configure TI_SCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID BIT(4) +/* RA config.order_id parameter is valid for RM ring configure TISCI message */ +#define TI_SCI_MSG_VALUE_RM_RING_ORDER_ID_VALID BIT(5) + +#define TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER \ + (TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_MODE_VALID | \ + TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID) + +/** + * struct ti_sci_rm_ringacc_ops - Ring Accelerator Management operations + * @config: configure the SoC Navigator Subsystem Ring Accelerator ring + * @get_config: get the SoC Navigator Subsystem Ring Accelerator ring + * configuration + */ +struct ti_sci_rm_ringacc_ops { + int (*config)(const struct ti_sci_handle *handle, + u32 valid_params, u16 nav_id, u16 index, + u32 addr_lo, u32 addr_hi, u32 count, u8 mode, + u8 size, u8 order_id + ); + int (*get_config)(const struct ti_sci_handle *handle, + u32 nav_id, u32 index, u8 *mode, + u32 *addr_lo, u32 *addr_hi, u32 *count, + u8 *size, u8 *order_id); +}; + +/** + * struct ti_sci_rm_psil_ops - PSI-L thread operations + * @pair: pair PSI-L source thread to a destination thread. + * If the src_thread is mapped to UDMA tchan, the corresponding channel's + * TCHAN_THRD_ID register is updated. + * If the dst_thread is mapped to UDMA rchan, the corresponding channel's + * RCHAN_THRD_ID register is updated. + * @unpair: unpair PSI-L source thread from a destination thread. + * If the src_thread is mapped to UDMA tchan, the corresponding channel's + * TCHAN_THRD_ID register is cleared. + * If the dst_thread is mapped to UDMA rchan, the corresponding channel's + * RCHAN_THRD_ID register is cleared. + */ +struct ti_sci_rm_psil_ops { + int (*pair)(const struct ti_sci_handle *handle, u32 nav_id, + u32 src_thread, u32 dst_thread); + int (*unpair)(const struct ti_sci_handle *handle, u32 nav_id, + u32 src_thread, u32 dst_thread); +}; + +/* UDMAP channel types */ +#define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR 2 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR_SB 3 /* RX only */ +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBRR 10 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBVR 11 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR 12 +#define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBVR 13 + +/* UDMAP channel atypes */ +#define TI_SCI_RM_UDMAP_ATYPE_PHYS 0 +#define TI_SCI_RM_UDMAP_ATYPE_INTERMEDIATE 1 +#define TI_SCI_RM_UDMAP_ATYPE_VIRTUAL 2 + +/* UDMAP channel scheduling priorities */ +#define TI_SCI_RM_UDMAP_SCHED_PRIOR_HIGH 0 +#define TI_SCI_RM_UDMAP_SCHED_PRIOR_MEDHIGH 1 +#define TI_SCI_RM_UDMAP_SCHED_PRIOR_MEDLOW 2 +#define TI_SCI_RM_UDMAP_SCHED_PRIOR_LOW 3 + +#define TI_SCI_RM_UDMAP_RX_FLOW_DESC_HOST 0 +#define TI_SCI_RM_UDMAP_RX_FLOW_DESC_MONO 2 + +/* UDMAP TX/RX channel valid_params common declarations */ +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PAUSE_ON_ERR_VALID BIT(0) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID BIT(1) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID BIT(2) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID BIT(3) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID BIT(4) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PRIORITY_VALID BIT(5) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_QOS_VALID BIT(6) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ORDER_ID_VALID BIT(7) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_SCHED_PRIORITY_VALID BIT(8) + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures a Navigator Subsystem UDMAP transmit channel registers. + * See @ti_sci_msg_rm_udmap_tx_ch_cfg_req + */ +struct ti_sci_msg_rm_udmap_tx_ch_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_EINFO_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_PSWORDS_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_CREDIT_COUNT_VALID BIT(12) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FDEPTH_VALID BIT(13) + u16 nav_id; + u16 index; + u8 tx_pause_on_err; + u8 tx_filt_einfo; + u8 tx_filt_pswords; + u8 tx_atype; + u8 tx_chan_type; + u8 tx_supr_tdpkt; + u16 tx_fetch_size; + u8 tx_credit_count; + u16 txcq_qnum; + u8 tx_priority; + u8 tx_qos; + u8 tx_orderid; + u16 fdepth; + u8 tx_sched_priority; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures a Navigator Subsystem UDMAP receive channel registers. + * See @ti_sci_msg_rm_udmap_rx_ch_cfg_req + */ +struct ti_sci_msg_rm_udmap_rx_ch_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_SHORT_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_LONG_VALID BIT(12) + u16 nav_id; + u16 index; + u16 rx_fetch_size; + u16 rxcq_qnum; + u8 rx_priority; + u8 rx_qos; + u8 rx_orderid; + u8 rx_sched_priority; + u16 flowid_start; + u16 flowid_cnt; + u8 rx_pause_on_err; + u8 rx_atype; + u8 rx_chan_type; + u8 rx_ignore_short; + u8 rx_ignore_long; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive flow + * + * Configures a Navigator Subsystem UDMAP receive flow's registers. + * See @tis_ci_msg_rm_udmap_flow_cfg_req + */ +struct ti_sci_msg_rm_udmap_flow_cfg { + u32 valid_params; +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID BIT(0) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID BIT(1) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID BIT(2) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID BIT(3) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SOP_OFFSET_VALID BIT(4) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID BIT(5) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_VALID BIT(6) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_VALID BIT(7) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_VALID BIT(8) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_VALID BIT(9) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID BIT(10) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID BIT(11) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID BIT(12) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID BIT(13) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID BIT(14) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID BIT(15) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID BIT(16) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID BIT(17) +#define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PS_LOCATION_VALID BIT(18) + u16 nav_id; + u16 flow_index; + u8 rx_einfo_present; + u8 rx_psinfo_present; + u8 rx_error_handling; + u8 rx_desc_type; + u16 rx_sop_offset; + u16 rx_dest_qnum; + u8 rx_src_tag_hi; + u8 rx_src_tag_lo; + u8 rx_dest_tag_hi; + u8 rx_dest_tag_lo; + u8 rx_src_tag_hi_sel; + u8 rx_src_tag_lo_sel; + u8 rx_dest_tag_hi_sel; + u8 rx_dest_tag_lo_sel; + u16 rx_fdq0_sz0_qnum; + u16 rx_fdq1_qnum; + u16 rx_fdq2_qnum; + u16 rx_fdq3_qnum; + u8 rx_ps_location; +}; + +/** + * struct ti_sci_rm_udmap_ops - UDMA Management operations + * @tx_ch_cfg: configure SoC Navigator Subsystem UDMA transmit channel. + * @rx_ch_cfg: configure SoC Navigator Subsystem UDMA receive channel. + * @rx_flow_cfg: configure SoC Navigator Subsystem UDMA receive flow. + */ +struct ti_sci_rm_udmap_ops { + int (*tx_ch_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params); + int (*rx_ch_cfg)(const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params); + int (*rx_flow_cfg)( + const struct ti_sci_handle *handle, + const struct ti_sci_msg_rm_udmap_flow_cfg *params); +}; + /** * struct ti_sci_ops - Function support for TI SCI * @board_ops: Miscellaneous operations @@ -264,6 +517,7 @@ struct ti_sci_proc_ops { * @clk_ops: Clock specific operations * @core_ops: Core specific operations * @proc_ops: Processor specific operations + * @ring_ops: Ring Accelerator Management operations */ struct ti_sci_ops { struct ti_sci_board_ops board_ops; @@ -271,6 +525,10 @@ struct ti_sci_ops { struct ti_sci_clk_ops clk_ops; struct ti_sci_core_ops core_ops; struct ti_sci_proc_ops proc_ops; + struct ti_sci_rm_core_ops rm_core_ops; + struct ti_sci_rm_ringacc_ops rm_ring_ops; + struct ti_sci_rm_psil_ops rm_psil_ops; + struct ti_sci_rm_udmap_ops rm_udmap_ops; }; /** @@ -283,12 +541,42 @@ struct ti_sci_handle { struct ti_sci_version_info version; }; +#define TI_SCI_RESOURCE_NULL 0xffff + +/** + * struct ti_sci_resource_desc - Description of TI SCI resource instance range. + * @start: Start index of the resource. + * @num: Number of resources. + * @res_map: Bitmap to manage the allocation of these resources. + */ +struct ti_sci_resource_desc { + u16 start; + u16 num; + unsigned long *res_map; +}; + +/** + * struct ti_sci_resource - Structure representing a resource assigned + * to a device. + * @sets: Number of sets available from this resource type + * @desc: Array of resource descriptors. + */ +struct ti_sci_resource { + u16 sets; + struct ti_sci_resource_desc *desc; +}; + #if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) const struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *dev); const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev); const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev, const char *property); +u16 ti_sci_get_free_resource(struct ti_sci_resource *res); +void ti_sci_release_resource(struct ti_sci_resource *res, u16 id); +struct ti_sci_resource * +devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, + struct udevice *dev, u32 dev_id, char *of_prop); #else /* CONFIG_TI_SCI_PROTOCOL */ @@ -309,6 +597,22 @@ const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev, { return ERR_PTR(-EINVAL); } + +static inline u16 ti_sci_get_free_resource(struct ti_sci_resource *res) +{ + return TI_SCI_RESOURCE_NULL; +} + +static inline void ti_sci_release_resource(struct ti_sci_resource *res, u16 id) +{ +} + +static inline struct ti_sci_resource * +devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, + struct udevice *dev, u32 dev_id, char *of_prop) +{ + return ERR_PTR(-EINVAL); +} #endif /* CONFIG_TI_SCI_PROTOCOL */ #endif /* __TISCI_PROTOCOL_H */ diff --git a/include/net.h b/include/net.h index dd52ed3..44b3238 100644 --- a/include/net.h +++ b/include/net.h @@ -92,12 +92,14 @@ enum eth_state_t { * @enetaddr: The Ethernet MAC address that is loaded from EEPROM or env * @phy_interface: PHY interface to use - see PHY_INTERFACE_MODE_... * @max_speed: Maximum speed of Ethernet connection supported by MAC + * @priv_pdata: device specific platdata */ struct eth_pdata { phys_addr_t iobase; unsigned char enetaddr[ARP_HLEN]; int phy_interface; int max_speed; + void *priv_pdata; }; enum eth_recv_flags { diff --git a/include/power/stpmic1.h b/include/power/stpmic1.h new file mode 100644 index 0000000..0e6721d --- /dev/null +++ b/include/power/stpmic1.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#ifndef __PMIC_STPMIC1_H_ +#define __PMIC_STPMIC1_H_ + +#define STPMIC1_MAIN_CR 0x10 +#define STPMIC1_BUCKS_MRST_CR 0x18 +#define STPMIC1_LDOS_MRST_CR 0x1a +#define STPMIC1_BUCKX_MAIN_CR(buck) (0x20 + (buck)) +#define STPMIC1_REFDDR_MAIN_CR 0x24 +#define STPMIC1_LDOX_MAIN_CR(ldo) (0x25 + (ldo)) +#define STPMIC1_BST_SW_CR 0x40 +#define STPMIC1_NVM_SR 0xb8 +#define STPMIC1_NVM_CR 0xb9 + +/* Main PMIC Control Register (MAIN_CR) */ +#define STPMIC1_SWOFF BIT(0) +#define STPMIC1_RREQ_EN BIT(1) + +/* BUCKS_MRST_CR */ +#define STPMIC1_MRST_BUCK(buck) BIT(buck) +#define STPMIC1_MRST_BUCK_ALL GENMASK(3, 0) + +/* LDOS_MRST_CR */ +#define STPMIC1_MRST_LDO(ldo) BIT(ldo) +#define STPMIC1_MRST_LDO_ALL GENMASK(6, 0) + +/* BUCKx_MAIN_CR (x=1...4) */ +#define STPMIC1_BUCK_ENA BIT(0) +#define STPMIC1_BUCK_PREG_MODE BIT(1) +#define STPMIC1_BUCK_VOUT_MASK GENMASK(7, 2) +#define STPMIC1_BUCK_VOUT_SHIFT 2 +#define STPMIC1_BUCK_VOUT(sel) (sel << STPMIC1_BUCK_VOUT_SHIFT) + +#define STPMIC1_BUCK2_1200000V STPMIC1_BUCK_VOUT(24) +#define STPMIC1_BUCK2_1350000V STPMIC1_BUCK_VOUT(30) + +#define STPMIC1_BUCK3_1800000V STPMIC1_BUCK_VOUT(39) + +/* REFDDR_MAIN_CR */ +#define STPMIC1_VREF_ENA BIT(0) + +/* LDOX_MAIN_CR */ +#define STPMIC1_LDO_ENA BIT(0) +#define STPMIC1_LDO12356_VOUT_MASK GENMASK(6, 2) +#define STPMIC1_LDO12356_VOUT_SHIFT 2 +#define STPMIC1_LDO_VOUT(sel) (sel << STPMIC1_LDO12356_VOUT_SHIFT) + +#define STPMIC1_LDO3_MODE BIT(7) +#define STPMIC1_LDO3_DDR_SEL 31 +#define STPMIC1_LDO3_1800000 STPMIC1_LDO_VOUT(9) + +#define STPMIC1_LDO4_UV 3300000 + +/* BST_SW_CR */ +#define STPMIC1_BST_ON BIT(0) +#define STPMIC1_VBUSOTG_ON BIT(1) +#define STPMIC1_SWOUT_ON BIT(2) +#define STPMIC1_PWR_SW_ON (STPMIC1_VBUSOTG_ON | STPMIC1_SWOUT_ON) + +/* NVM_SR */ +#define STPMIC1_NVM_BUSY BIT(0) + +/* NVM_CR */ +#define STPMIC1_NVM_CMD_PROGRAM 1 +#define STPMIC1_NVM_CMD_READ 2 + +/* Timeout */ +#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 +#define STPMIC1_DEFAULT_STOP_DELAY_MS 5 +#define STPMIC1_USB_BOOST_START_UP_DELAY_MS 10 + +enum { + STPMIC1_BUCK1, + STPMIC1_BUCK2, + STPMIC1_BUCK3, + STPMIC1_BUCK4, + STPMIC1_MAX_BUCK, +}; + +enum { + STPMIC1_PREG_MODE_HP, + STPMIC1_PREG_MODE_LP, +}; + +enum { + STPMIC1_LDO1, + STPMIC1_LDO2, + STPMIC1_LDO3, + STPMIC1_LDO4, + STPMIC1_LDO5, + STPMIC1_LDO6, + STPMIC1_MAX_LDO, +}; + +enum { + STPMIC1_LDO_MODE_NORMAL, + STPMIC1_LDO_MODE_BYPASS, + STPMIC1_LDO_MODE_SINK_SOURCE, +}; + +enum { + STPMIC1_PWR_SW1, + STPMIC1_PWR_SW2, + STPMIC1_MAX_PWR_SW, +}; + +int stpmic1_shadow_read_byte(u8 addr, u8 *buf); +int stpmic1_shadow_write_byte(u8 addr, u8 *buf); +int stpmic1_nvm_read_byte(u8 addr, u8 *buf); +int stpmic1_nvm_write_byte(u8 addr, u8 *buf); +int stpmic1_nvm_read_all(u8 *buf, int buf_len); +int stpmic1_nvm_write_all(u8 *buf, int buf_len); +#endif diff --git a/include/power/stpmu1.h b/include/power/stpmu1.h deleted file mode 100644 index 5906fbf..0000000 --- a/include/power/stpmu1.h +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ -/* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved - */ - -#ifndef __PMIC_STPMU1_H_ -#define __PMIC_STPMU1_H_ - -#define STPMU1_MASK_RESET_BUCK 0x18 -#define STPMU1_BUCKX_CTRL_REG(buck) (0x20 + (buck)) -#define STPMU1_VREF_CTRL_REG 0x24 -#define STPMU1_LDOX_CTRL_REG(ldo) (0x25 + (ldo)) -#define STPMU1_USB_CTRL_REG 0x40 -#define STPMU1_NVM_USER_STATUS_REG 0xb8 -#define STPMU1_NVM_USER_CONTROL_REG 0xb9 - -#define STPMU1_MASK_RESET_BUCK3 BIT(2) - -#define STPMU1_BUCK_EN BIT(0) -#define STPMU1_BUCK_MODE BIT(1) -#define STPMU1_BUCK_OUTPUT_MASK GENMASK(7, 2) -#define STPMU1_BUCK_OUTPUT_SHIFT 2 -#define STPMU1_BUCK2_1200000V (24 << STPMU1_BUCK_OUTPUT_SHIFT) -#define STPMU1_BUCK2_1350000V (30 << STPMU1_BUCK_OUTPUT_SHIFT) -#define STPMU1_BUCK3_1800000V (39 << STPMU1_BUCK_OUTPUT_SHIFT) - -#define STPMU1_VREF_EN BIT(0) - -#define STPMU1_LDO_EN BIT(0) -#define STPMU1_LDO12356_OUTPUT_MASK GENMASK(6, 2) -#define STPMU1_LDO12356_OUTPUT_SHIFT 2 -#define STPMU1_LDO3_MODE BIT(7) -#define STPMU1_LDO3_DDR_SEL 31 -#define STPMU1_LDO3_1800000 (9 << STPMU1_LDO12356_OUTPUT_SHIFT) -#define STPMU1_LDO4_UV 3300000 - -#define STPMU1_USB_BOOST_EN BIT(0) -#define STPMU1_USB_PWR_SW_EN GENMASK(2, 1) - -#define STPMU1_NVM_USER_CONTROL_PROGRAM BIT(0) -#define STPMU1_NVM_USER_CONTROL_READ BIT(1) - -#define STPMU1_NVM_USER_STATUS_BUSY BIT(0) -#define STPMU1_NVM_USER_STATUS_ERROR BIT(1) - -#define STPMU1_DEFAULT_START_UP_DELAY_MS 1 -#define STPMU1_DEFAULT_STOP_DELAY_MS 5 -#define STPMU1_USB_BOOST_START_UP_DELAY_MS 10 - -enum { - STPMU1_BUCK1, - STPMU1_BUCK2, - STPMU1_BUCK3, - STPMU1_BUCK4, - STPMU1_MAX_BUCK, -}; - -enum { - STPMU1_BUCK_MODE_HP, - STPMU1_BUCK_MODE_LP, -}; - -enum { - STPMU1_LDO1, - STPMU1_LDO2, - STPMU1_LDO3, - STPMU1_LDO4, - STPMU1_LDO5, - STPMU1_LDO6, - STPMU1_MAX_LDO, -}; - -enum { - STPMU1_LDO_MODE_NORMAL, - STPMU1_LDO_MODE_BYPASS, - STPMU1_LDO_MODE_SINK_SOURCE, -}; - -enum { - STPMU1_PWR_SW1, - STPMU1_PWR_SW2, - STPMU1_MAX_PWR_SW, -}; - -#endif diff --git a/lib/Kconfig b/lib/Kconfig index 8fe5d85..2120216 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -436,4 +436,8 @@ source lib/efi/Kconfig source lib/efi_loader/Kconfig source lib/optee/Kconfig +config TEST_FDTDEC + bool "enable fdtdec test" + depends on OF_LIBFDT + endmenu diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 21f1eee..9c9c302 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1261,6 +1261,231 @@ __weak void *board_fdt_blob_setup(void) } #endif +int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) +{ + fdt32_t value = cpu_to_fdt32(phandle); + + return fdt_setprop(blob, node, "phandle", &value, sizeof(value)); +} + +static int fdtdec_init_reserved_memory(void *blob) +{ + int na, ns, node, err; + fdt32_t value; + + /* inherit #address-cells and #size-cells from the root node */ + na = fdt_address_cells(blob, 0); + ns = fdt_size_cells(blob, 0); + + node = fdt_add_subnode(blob, 0, "reserved-memory"); + if (node < 0) + return node; + + err = fdt_setprop(blob, node, "ranges", NULL, 0); + if (err < 0) + return err; + + value = cpu_to_fdt32(ns); + + err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value)); + if (err < 0) + return err; + + value = cpu_to_fdt32(na); + + err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value)); + if (err < 0) + return err; + + return node; +} + +int fdtdec_add_reserved_memory(void *blob, const char *basename, + const struct fdt_memory *carveout, + uint32_t *phandlep) +{ + fdt32_t cells[4] = {}, *ptr = cells; + uint32_t upper, lower, phandle; + int parent, node, na, ns, err; + char name[64]; + + /* create an empty /reserved-memory node if one doesn't exist */ + parent = fdt_path_offset(blob, "/reserved-memory"); + if (parent < 0) { + parent = fdtdec_init_reserved_memory(blob); + if (parent < 0) + return parent; + } + + /* only 1 or 2 #address-cells and #size-cells are supported */ + na = fdt_address_cells(blob, parent); + if (na < 1 || na > 2) + return -FDT_ERR_BADNCELLS; + + ns = fdt_size_cells(blob, parent); + if (ns < 1 || ns > 2) + return -FDT_ERR_BADNCELLS; + + /* find a matching node and return the phandle to that */ + fdt_for_each_subnode(node, blob, parent) { + const char *name = fdt_get_name(blob, node, NULL); + phys_addr_t addr, size; + + addr = fdtdec_get_addr_size(blob, node, "reg", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("failed to read address/size for %s\n", name); + continue; + } + + if (addr == carveout->start && (addr + size) == carveout->end) { + *phandlep = fdt_get_phandle(blob, node); + return 0; + } + } + + /* + * Unpack the start address and generate the name of the new node + * base on the basename and the unit-address. + */ + lower = fdt_addr_unpack(carveout->start, &upper); + + if (na > 1 && upper > 0) + snprintf(name, sizeof(name), "%s@%x,%x", basename, upper, + lower); + else { + if (upper > 0) { + debug("address %08x:%08x exceeds addressable space\n", + upper, lower); + return -FDT_ERR_BADVALUE; + } + + snprintf(name, sizeof(name), "%s@%x", basename, lower); + } + + node = fdt_add_subnode(blob, parent, name); + if (node < 0) + return node; + + err = fdt_generate_phandle(blob, &phandle); + if (err < 0) + return err; + + err = fdtdec_set_phandle(blob, node, phandle); + if (err < 0) + return err; + + /* store one or two address cells */ + if (na > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + /* store one or two size cells */ + lower = fdt_size_unpack(carveout->end - carveout->start + 1, &upper); + + if (ns > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells)); + if (err < 0) + return err; + + /* return the phandle for the new node for the caller to use */ + if (phandlep) + *phandlep = phandle; + + return 0; +} + +int fdtdec_get_carveout(const void *blob, const char *node, const char *name, + unsigned int index, struct fdt_memory *carveout) +{ + const fdt32_t *prop; + uint32_t phandle; + int offset, len; + fdt_size_t size; + + offset = fdt_path_offset(blob, node); + if (offset < 0) + return offset; + + prop = fdt_getprop(blob, offset, name, &len); + if (!prop) { + debug("failed to get %s for %s\n", name, node); + return -FDT_ERR_NOTFOUND; + } + + if ((len % sizeof(phandle)) != 0) { + debug("invalid phandle property\n"); + return -FDT_ERR_BADPHANDLE; + } + + if (len < (sizeof(phandle) * (index + 1))) { + debug("invalid phandle index\n"); + return -FDT_ERR_BADPHANDLE; + } + + phandle = fdt32_to_cpu(prop[index]); + + offset = fdt_node_offset_by_phandle(blob, phandle); + if (offset < 0) { + debug("failed to find node for phandle %u\n", phandle); + return offset; + } + + carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset, + "reg", 0, &size, + true); + if (carveout->start == FDT_ADDR_T_NONE) { + debug("failed to read address/size from \"reg\" property\n"); + return -FDT_ERR_NOTFOUND; + } + + carveout->end = carveout->start + size - 1; + + return 0; +} + +int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, + unsigned int index, const char *name, + const struct fdt_memory *carveout) +{ + uint32_t phandle; + int err, offset; + fdt32_t value; + + /* XXX implement support for multiple phandles */ + if (index > 0) { + debug("invalid index %u\n", index); + return -FDT_ERR_BADOFFSET; + } + + err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle); + if (err < 0) { + debug("failed to add reserved memory: %d\n", err); + return err; + } + + offset = fdt_path_offset(blob, node); + if (offset < 0) { + debug("failed to find offset for node %s: %d\n", node, offset); + return offset; + } + + value = cpu_to_fdt32(phandle); + + err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value)); + if (err < 0) { + debug("failed to set %s property for node %s: %d\n", prop_name, + node, err); + return err; + } + + return 0; +} + int fdtdec_setup(void) { #if CONFIG_IS_ENABLED(OF_CONTROL) diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c index a82e27d..f6defe1 100644 --- a/lib/fdtdec_test.c +++ b/lib/fdtdec_test.c @@ -15,48 +15,28 @@ /* The size of our test fdt blob */ #define FDT_SIZE (16 * 1024) -/** - * Check if an operation failed, and if so, print an error - * - * @param oper_name Name of operation - * @param err Error code to check - * - * @return 0 if ok, -1 if there was an error - */ -static int fdt_checkerr(const char *oper_name, int err) -{ - if (err) { - printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err)); - return -1; - } +#define CHECK(op) ({ \ + int err = op; \ + if (err < 0) { \ + printf("%s: %s: %s\n", __func__, #op, \ + fdt_strerror(err)); \ + return err; \ + } \ + \ + err; \ + }) - return 0; -} +#define CHECKVAL(op, expected) ({ \ + int err = op; \ + if (err != expected) { \ + printf("%s: %s: expected %d, but returned %d\n",\ + __func__, #op, expected, err); \ + return err; \ + } \ + \ + err; \ + }) -/** - * Check the result of an operation and if incorrect, print an error - * - * @param oper_name Name of operation - * @param expected Expected value - * @param value Actual value - * - * @return 0 if ok, -1 if there was an error - */ -static int checkval(const char *oper_name, int expected, int value) -{ - if (expected != value) { - printf("%s: %s: expected %d, but returned %d\n", __func__, - oper_name, expected, value); - return -1; - } - - return 0; -} - -#define CHECK(op) if (fdt_checkerr(#op, op)) return -1 -#define CHECKVAL(op, expected) \ - if (checkval(#op, expected, op)) \ - return -1 #define CHECKOK(op) CHECKVAL(op, 0) /* maximum number of nodes / aliases to generate */ @@ -79,7 +59,9 @@ static int make_fdt(void *fdt, int size, const char *aliases, { char name[20], value[20]; const char *s; +#if defined(DEBUG) && defined(CONFIG_SANDBOX) int fd; +#endif CHECK(fdt_create(fdt, size)); CHECK(fdt_finish_reservemap(fdt)); @@ -136,7 +118,7 @@ static int run_test(const char *aliases, const char *nodes, const char *expect) CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0); CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c", COMPAT_UNKNOWN, - list, ARRAY_SIZE(list)), strlen(expect)); + list, ARRAY_SIZE(list)), (int)strlen(expect)); /* Check we got the right ones */ for (i = 0, s = expect; *s; s++, i++) { @@ -159,6 +141,156 @@ static int run_test(const char *aliases, const char *nodes, const char *expect) return 0; } +static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns) +{ + const char *basename = "/display"; + struct fdt_memory carveout = { +#ifdef CONFIG_PHYS_64BIT + .start = 0x180000000, + .end = 0x18fffffff, +#else + .start = 0x80000000, + .end = 0x8fffffff, +#endif + }; + fdt32_t cells[4], *ptr = cells; + uint32_t upper, lower; + char name[32]; + int offset; + + /* store one or two address cells */ + lower = fdt_addr_unpack(carveout.start, &upper); + + if (na > 1 && upper > 0) + snprintf(name, sizeof(name), "%s@%x,%x", basename, upper, + lower); + else + snprintf(name, sizeof(name), "%s@%x", basename, lower); + + if (na > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + /* store one or two size cells */ + lower = fdt_size_unpack(carveout.end - carveout.start + 1, &upper); + + if (ns > 1) + *ptr++ = cpu_to_fdt32(upper); + + *ptr++ = cpu_to_fdt32(lower); + + offset = CHECK(fdt_add_subnode(fdt, 0, name + 1)); + CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells))); + + return fdtdec_set_carveout(fdt, name, "memory-region", 0, + "framebuffer", &carveout); +} + +static int check_fdt_carveout(void *fdt, uint32_t address_cells, + uint32_t size_cells) +{ +#ifdef CONFIG_PHYS_64BIT + const char *name = "/display@1,80000000"; + const struct fdt_memory expected = { + .start = 0x180000000, + .end = 0x18fffffff, + }; +#else + const char *name = "/display@80000000"; + const struct fdt_memory expected = { + .start = 0x80000000, + .end = 0x8fffffff, + }; +#endif + struct fdt_memory carveout; + + printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start, + &expected.end, address_cells, size_cells); + + CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout)); + + if ((carveout.start != expected.start) || + (carveout.end != expected.end)) { + printf("carveout: %pap-%pap, expected %pap-%pap\n", + &carveout.start, &carveout.end, + &expected.start, &expected.end); + return 1; + } + + printf("pass\n"); + return 0; +} + +static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells, + uint32_t size_cells) +{ + fdt32_t na = cpu_to_fdt32(address_cells); + fdt32_t ns = cpu_to_fdt32(size_cells); +#if defined(DEBUG) && defined(CONFIG_SANDBOX) + char filename[512]; + int fd; +#endif + int err; + + CHECK(fdt_create(fdt, size)); + CHECK(fdt_finish_reservemap(fdt)); + CHECK(fdt_begin_node(fdt, "")); + CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na))); + CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns))); + CHECK(fdt_end_node(fdt)); + CHECK(fdt_finish(fdt)); + CHECK(fdt_pack(fdt)); + + CHECK(fdt_open_into(fdt, fdt, FDT_SIZE)); + + err = make_fdt_carveout_device(fdt, address_cells, size_cells); + +#if defined(DEBUG) && defined(CONFIG_SANDBOX) + snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb", + address_cells, size_cells); + + fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY); + if (fd < 0) { + printf("could not open .dtb file to write\n"); + goto out; + } + + os_write(fd, fdt, size); + os_close(fd); + +out: +#endif + return err; +} + +static int check_carveout(void) +{ + void *fdt; + + fdt = malloc(FDT_SIZE); + if (!fdt) { + printf("%s: out of memory\n", __func__); + return 1; + } + +#ifndef CONFIG_PHYS_64BIT + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0); + CHECKOK(check_fdt_carveout(fdt, 1, 1)); + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0); + CHECKOK(check_fdt_carveout(fdt, 1, 2)); +#else + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE); + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE); +#endif + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0); + CHECKOK(check_fdt_carveout(fdt, 2, 1)); + CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0); + CHECKOK(check_fdt_carveout(fdt, 2, 2)); + + return 0; +} + static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -200,6 +332,8 @@ static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, CHECKOK(run_test("2a 1a 0a", "a", " a")); CHECKOK(run_test("0a 1a 2a", "a", "a")); + CHECKOK(check_carveout()); + printf("Test passed\n"); return 0; } diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index b6ca4e0..693de9a 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -73,6 +73,37 @@ uint32_t fdt_get_max_phandle(const void *fdt) return 0; } +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 1b6c154..2403825 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -457,7 +457,6 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, return device_path_string(buf, end, ptr, field_width, precision, flags); #endif -#ifdef CONFIG_CMD_NET case 'a': flags |= SPECIAL | ZEROPAD; @@ -469,6 +468,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, break; } break; +#ifdef CONFIG_CMD_NET case 'm': flags |= SPECIAL; /* Fallthrough */ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 70de9bb..de67677 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -525,4 +525,5 @@ quiet_cmd_fdtgrep = FDTGREP $@ cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \ -n /chosen -n /config -O dtb | \ $(objtree)/tools/fdtgrep -r -O dtb - -o $@ \ + -P u-boot,dm-pre-reloc -P u-boot,dm-spl -P u-boot,dm-tpl \ $(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS))) diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 8c7c159..fa98efc 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4399,7 +4399,6 @@ CONFIG_THOR_RESET_OFF CONFIG_THUNDERX CONFIG_TIMESTAMP CONFIG_TIZEN -CONFIG_TI_KEYSTONE_SERDES CONFIG_TI_KSNAV CONFIG_TI_SPI_MMAP CONFIG_TMU_TIMER diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index dfb3236..dc49988 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -115,6 +115,37 @@ uint32_t fdt_get_max_phandle(const void *fdt) return 0; } +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { FDT_CHECK_HEADER(fdt); diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index fd73688..cf86ddb 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -139,6 +139,10 @@ #define FDT_ERR_MAX 17 +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ + /**********************************************************************/ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ @@ -314,6 +318,21 @@ const char *fdt_string(const void *fdt, int stroffset); uint32_t fdt_get_max_phandle(const void *fdt); /** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * highest phandle value in the device tree blob) will be returned in the + * @phandle parameter. + * + * Returns: + * 0 on success or a negative error-code on failure + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); + +/** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob * diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h index bd24746..3ff9e28 100644 --- a/scripts/dtc/libfdt/libfdt_env.h +++ b/scripts/dtc/libfdt/libfdt_env.h @@ -52,6 +52,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <stdbool.h> #include <stddef.h> #include <stdint.h> #include <stdlib.h> diff --git a/test/dm/syscon.c b/test/dm/syscon.c index a294dda..0ff9da7 100644 --- a/test/dm/syscon.c +++ b/test/dm/syscon.c @@ -67,6 +67,13 @@ static int dm_test_syscon_by_phandle(struct unit_test_state *uts) ut_assert(!IS_ERR(map)); ut_asserteq(4, map->range_count); + ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, + "third-syscon")); + map = syscon_regmap_lookup_by_phandle(dev, "third-syscon"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(4, map->range_count); + ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present"))); return 0; diff --git a/tools/kwbimage.c b/tools/kwbimage.c index a88a383..dffaf90 100644 --- a/tools/kwbimage.c +++ b/tools/kwbimage.c @@ -1273,6 +1273,13 @@ static void *image_create_v1(size_t *imagesz, struct image_tool_params *params, e = image_find_option(IMAGE_CFG_DEBUG); if (e) main_hdr->flags = e->debug ? 0x1 : 0; + e = image_find_option(IMAGE_CFG_BINARY); + if (e) { + char *s = strrchr(e->binary.file, '/'); + + if (strcmp(s, "/binary.0") == 0) + main_hdr->destaddr = cpu_to_le32(params->addr); + } #if defined(CONFIG_KWB_SECURE) if (image_get_csk_index() >= 0) { diff --git a/tools/mkimage.c b/tools/mkimage.c index 2899adf..d1e1a67 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -403,14 +403,21 @@ int main(int argc, char **argv) exit (EXIT_FAILURE); } - /* - * scan through mkimage registry for all supported image types - * and verify the input image file header for match - * Print the image information for matched image type - * Returns the error code if not matched - */ - retval = imagetool_verify_print_header_by_type(ptr, &sbuf, - tparams, ¶ms); + if (params.fflag) { + /* + * Verifies the header format based on the expected header for image + * type in tparams + */ + retval = imagetool_verify_print_header_by_type(ptr, &sbuf, + tparams, ¶ms); + } else { + /** + * When listing the image, we are not given the image type. Simply check all + * image types to find one that matches our header + */ + retval = imagetool_verify_print_header(ptr, &sbuf, + tparams, ¶ms); + } (void) munmap((void *)ptr, sbuf.st_size); (void) close (ifd); |