diff options
-rw-r--r-- | arch/arm/dts/k3-j721e-main.dtsi | 19 | ||||
-rw-r--r-- | arch/arm/dts/sunxi-u-boot.dtsi | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/dram_sunxi_dw.h | 11 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/dram_sunxi_dw.c | 149 | ||||
-rw-r--r-- | arch/sandbox/dts/test.dts | 72 | ||||
-rw-r--r-- | configs/omap35_logic_somlv_defconfig | 1 | ||||
-rw-r--r-- | configs/sandbox_defconfig | 1 | ||||
-rw-r--r-- | configs/sandbox_flattree_defconfig | 1 | ||||
-rw-r--r-- | drivers/clk/sunxi/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk_h6.c | 2 | ||||
-rw-r--r-- | drivers/clk/sunxi/clk_sun6i_rtc.c | 35 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-single.c | 474 | ||||
-rw-r--r-- | drivers/video/sunxi/Makefile | 2 | ||||
-rw-r--r-- | env/Kconfig | 22 | ||||
-rw-r--r-- | env/common.c | 27 | ||||
-rw-r--r-- | env/env.c | 3 | ||||
-rw-r--r-- | env/ext4.c | 3 | ||||
-rw-r--r-- | env/fat.c | 40 | ||||
-rw-r--r-- | env/flags.c | 5 | ||||
-rw-r--r-- | env/mmc.c | 6 | ||||
-rw-r--r-- | env/sf.c | 110 | ||||
-rw-r--r-- | include/configs/sunxi-common.h | 64 | ||||
-rw-r--r-- | include/env.h | 2 | ||||
-rw-r--r-- | include/env_internal.h | 1 | ||||
-rw-r--r-- | test/dm/pinmux.c | 91 |
26 files changed, 954 insertions, 194 deletions
diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi index e47b6c0eb70..07b489679ed 100644 --- a/arch/arm/dts/k3-j721e-main.dtsi +++ b/arch/arm/dts/k3-j721e-main.dtsi @@ -1078,13 +1078,12 @@ assigned-clocks = <&k3_clks 91 1>; assigned-clock-parents = <&k3_clks 91 2>; bus-width = <8>; - mmc-hs400-1_8v; + mmc-hs200-1_8v; mmc-ddr-1_8v; ti,otap-del-sel-legacy = <0xf>; ti,otap-del-sel-mmc-hs = <0xf>; ti,otap-del-sel-ddr52 = <0x5>; ti,otap-del-sel-hs200 = <0x6>; - ti,otap-del-sel-hs400 = <0x0>; ti,itap-del-sel-legacy = <0x10>; ti,itap-del-sel-mmc-hs = <0xa>; ti,itap-del-sel-ddr52 = <0x3>; @@ -1102,14 +1101,20 @@ assigned-clocks = <&k3_clks 92 0>; assigned-clock-parents = <&k3_clks 92 1>; ti,otap-del-sel-legacy = <0x0>; - ti,otap-del-sel-sd-hs = <0xf>; + ti,otap-del-sel-sd-hs = <0x0>; ti,otap-del-sel-sdr12 = <0xf>; ti,otap-del-sel-sdr25 = <0xf>; ti,otap-del-sel-sdr50 = <0xc>; ti,otap-del-sel-ddr50 = <0xc>; + ti,itap-del-sel-legacy = <0x0>; + ti,itap-del-sel-sd-hs = <0x0>; + ti,itap-del-sel-sdr12 = <0x0>; + ti,itap-del-sel-sdr25 = <0x0>; + ti,itap-del-sel-ddr50 = <0x2>; ti,trm-icp = <0x8>; ti,clkbuf-sel = <0x7>; dma-coherent; + sdhci-caps-mask = <0x2 0x0>; }; main_sdhci2: sdhci@4f98000 { @@ -1122,14 +1127,20 @@ assigned-clocks = <&k3_clks 93 0>; assigned-clock-parents = <&k3_clks 93 1>; ti,otap-del-sel-legacy = <0x0>; - ti,otap-del-sel-sd-hs = <0xf>; + ti,otap-del-sel-sd-hs = <0x0>; ti,otap-del-sel-sdr12 = <0xf>; ti,otap-del-sel-sdr25 = <0xf>; ti,otap-del-sel-sdr50 = <0xc>; ti,otap-del-sel-ddr50 = <0xc>; + ti,itap-del-sel-legacy = <0x0>; + ti,itap-del-sel-sd-hs = <0x0>; + ti,itap-del-sel-sdr12 = <0x0>; + ti,itap-del-sel-sdr25 = <0x0>; + ti,itap-del-sel-ddr50 = <0x2>; ti,trm-icp = <0x8>; ti,clkbuf-sel = <0x7>; dma-coherent; + sdhci-caps-mask = <0x2 0x0>; }; usbss0: cdns-usb@4104000 { diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi index cd096bf2a06..a4227a3c22d 100644 --- a/arch/arm/dts/sunxi-u-boot.dtsi +++ b/arch/arm/dts/sunxi-u-boot.dtsi @@ -42,7 +42,7 @@ os = "u-boot"; arch = "arm64"; compression = "none"; - load = <0x4a000000>; + load = <CONFIG_SYS_TEXT_BASE>; u-boot-nodtb { }; @@ -86,7 +86,7 @@ }; configurations { - default = "config-1"; + default = "@config-DEFAULT-SEQ"; @config-SEQ { description = "NAME"; diff --git a/arch/arm/include/asm/arch-sunxi/dram_sunxi_dw.h b/arch/arm/include/asm/arch-sunxi/dram_sunxi_dw.h index a5a7ebde44e..e843c14202b 100644 --- a/arch/arm/include/asm/arch-sunxi/dram_sunxi_dw.h +++ b/arch/arm/include/asm/arch-sunxi/dram_sunxi_dw.h @@ -215,12 +215,17 @@ struct sunxi_mctl_ctl_reg { #define NR_OF_BYTE_LANES (32 / BITS_PER_BYTE) /* The eight data lines (DQn) plus DM, DQS and DQSN */ #define LINES_PER_BYTE_LANE (BITS_PER_BYTE + 3) -struct dram_para { + +struct rank_para { u16 page_size; - u8 bus_full_width; - u8 dual_rank; u8 row_bits; u8 bank_bits; +}; + +struct dram_para { + u8 dual_rank; + u8 bus_full_width; + struct rank_para ranks[2]; const u8 dx_read_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE]; const u8 dx_write_delays[NR_OF_BYTE_LANES][LINES_PER_BYTE_LANE]; const u8 ac_delays[31]; diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index a29d11505aa..8e9012dbbfe 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -973,6 +973,7 @@ config VIDEO_DE2 depends on SUNXI_DE2 select DM_VIDEO select DISPLAY + select VIDEO_DW_HDMI imply VIDEO_DT_SIMPLEFB default y ---help--- diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index d0600011ffa..9107b114df5 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -399,18 +399,24 @@ static void mctl_set_cr(uint16_t socid, struct dram_para *para) #else #error Unsupported DRAM type! #endif - (para->bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) | + (para->ranks[0].bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) | MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) | (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) | - MCTL_CR_PAGE_SIZE(para->page_size) | - MCTL_CR_ROW_BITS(para->row_bits), &mctl_com->cr); + MCTL_CR_PAGE_SIZE(para->ranks[0].page_size) | + MCTL_CR_ROW_BITS(para->ranks[0].row_bits), &mctl_com->cr); + + if (para->dual_rank && (socid == SOCID_A64 || socid == SOCID_R40)) { + writel((para->ranks[1].bank_bits == 3 ? MCTL_CR_EIGHT_BANKS : MCTL_CR_FOUR_BANKS) | + MCTL_CR_BUS_FULL_WIDTH(para->bus_full_width) | + MCTL_CR_DUAL_RANK | + MCTL_CR_PAGE_SIZE(para->ranks[1].page_size) | + MCTL_CR_ROW_BITS(para->ranks[1].row_bits), &mctl_com->cr_r1); + } if (socid == SOCID_R40) { - if (para->dual_rank) - panic("Dual rank memory not supported\n"); - /* Mux pin to A15 address line for single rank memory. */ - setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15); + if (!para->dual_rank) + setbits_le32(&mctl_com->cr_r1, MCTL_CR_R1_MUX_A15); } } @@ -646,35 +652,105 @@ static int mctl_channel_init(uint16_t socid, struct dram_para *para) return 0; } -static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para) +/* + * Test if memory at offset offset matches memory at a certain base + */ +static bool mctl_mem_matches_base(u32 offset, ulong base) +{ + /* Try to write different values to RAM at two addresses */ + writel(0, base); + writel(0xaa55aa55, base + offset); + dsb(); + /* Check if the same value is actually observed when reading back */ + return readl(base) == + readl(base + offset); +} + +static void mctl_auto_detect_dram_size_rank(uint16_t socid, struct dram_para *para, ulong base, struct rank_para *rank) { /* detect row address bits */ - para->page_size = 512; - para->row_bits = 16; - para->bank_bits = 2; + rank->page_size = 512; + rank->row_bits = 16; + rank->bank_bits = 2; mctl_set_cr(socid, para); - for (para->row_bits = 11; para->row_bits < 16; para->row_bits++) - if (mctl_mem_matches((1 << (para->row_bits + para->bank_bits)) * para->page_size)) + for (rank->row_bits = 11; rank->row_bits < 16; rank->row_bits++) + if (mctl_mem_matches_base((1 << (rank->row_bits + rank->bank_bits)) * rank->page_size, base)) break; /* detect bank address bits */ - para->bank_bits = 3; + rank->bank_bits = 3; mctl_set_cr(socid, para); - for (para->bank_bits = 2; para->bank_bits < 3; para->bank_bits++) - if (mctl_mem_matches((1 << para->bank_bits) * para->page_size)) + for (rank->bank_bits = 2; rank->bank_bits < 3; rank->bank_bits++) + if (mctl_mem_matches_base((1 << rank->bank_bits) * rank->page_size, base)) break; /* detect page size */ - para->page_size = 8192; + rank->page_size = 8192; mctl_set_cr(socid, para); - for (para->page_size = 512; para->page_size < 8192; para->page_size *= 2) - if (mctl_mem_matches(para->page_size)) + for (rank->page_size = 512; rank->page_size < 8192; rank->page_size *= 2) + if (mctl_mem_matches_base(rank->page_size, base)) break; } +static unsigned long mctl_calc_rank_size(struct rank_para *rank) +{ + return (1UL << (rank->row_bits + rank->bank_bits)) * rank->page_size; +} + +/* + * Because we cannot do mctl_phy_init(PIR_QSGATE) on R40 now (which leads + * to failure), it's needed to detect the rank count of R40 in another way. + * + * The code here is modelled after time_out_detect() in BSP, which tries to + * access the memory and check for error code. + * + * TODO: auto detect half DQ width here + */ +static void mctl_r40_detect_rank_count(struct dram_para *para) +{ + ulong rank1_base = (ulong) CONFIG_SYS_SDRAM_BASE + + mctl_calc_rank_size(¶->ranks[0]); + struct sunxi_mctl_ctl_reg * const mctl_ctl = + (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; + + /* Enable read time out */ + setbits_le32(&mctl_ctl->pgcr[0], 0x1 << 25); + + (void) readl((void *) rank1_base); + udelay(10); + + if (readl(&mctl_ctl->pgsr[0]) & (0x1 << 13)) { + clrsetbits_le32(&mctl_ctl->dtcr, 0xf << 24, 0x1 << 24); + para->dual_rank = 0; + } + + /* Reset PHY FIFO to clear it */ + clrbits_le32(&mctl_ctl->pgcr[0], 0x1 << 26); + udelay(100); + setbits_le32(&mctl_ctl->pgcr[0], 0x1 << 26); + + /* Clear error status */ + setbits_le32(&mctl_ctl->pgcr[0], 0x1 << 24); + + /* Clear time out flag */ + clrbits_le32(&mctl_ctl->pgsr[0], 0x1 << 13); + + /* Disable read time out */ + clrbits_le32(&mctl_ctl->pgcr[0], 0x1 << 25); +} + +static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para) +{ + mctl_auto_detect_dram_size_rank(socid, para, (ulong)CONFIG_SYS_SDRAM_BASE, ¶->ranks[0]); + + if ((socid == SOCID_A64 || socid == SOCID_R40) && para->dual_rank) { + mctl_auto_detect_dram_size_rank(socid, para, (ulong)CONFIG_SYS_SDRAM_BASE + mctl_calc_rank_size(¶->ranks[0]), ¶->ranks[1]); + } +} + /* * The actual values used here are taken from Allwinner provided boot0 * binaries, though they are probably board specific, so would likely benefit @@ -769,12 +845,23 @@ unsigned long sunxi_dram_init(void) struct sunxi_mctl_ctl_reg * const mctl_ctl = (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE; + unsigned long size; + struct dram_para para = { .dual_rank = 1, .bus_full_width = 1, - .row_bits = 15, - .bank_bits = 3, - .page_size = 4096, + .ranks = { + { + .row_bits = 15, + .bank_bits = 3, + .page_size = 4096, + }, + { + .row_bits = 15, + .bank_bits = 3, + .page_size = 4096, + } + }, #if defined(CONFIG_MACH_SUN8I_H3) .dx_read_delays = SUN8I_H3_DX_READ_DELAYS, @@ -807,8 +894,6 @@ unsigned long sunxi_dram_init(void) uint16_t socid = SOCID_H3; #elif defined(CONFIG_MACH_SUN8I_R40) uint16_t socid = SOCID_R40; - /* Currently we cannot support R40 with dual rank memory */ - para.dual_rank = 0; #elif defined(CONFIG_MACH_SUN8I_V3S) uint16_t socid = SOCID_V3S; #elif defined(CONFIG_MACH_SUN50I) @@ -843,9 +928,21 @@ unsigned long sunxi_dram_init(void) setbits_le32(&mctl_com->cccr, 1 << 31); udelay(10); + if (socid == SOCID_R40) { + mctl_r40_detect_rank_count(¶); + mctl_set_cr(SOCID_R40, ¶); + } + mctl_auto_detect_dram_size(socid, ¶); mctl_set_cr(socid, ¶); - return (1UL << (para.row_bits + para.bank_bits)) * para.page_size * - (para.dual_rank ? 2 : 1); + size = mctl_calc_rank_size(¶.ranks[0]); + if (socid == SOCID_A64 || socid == SOCID_R40) { + if (para.dual_rank) + size += mctl_calc_rank_size(¶.ranks[1]); + } else if (para.dual_rank) { + size *= 2; + } + + return size; } diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dde4efb9334..48240aa26f6 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -634,6 +634,9 @@ reg = <0 1>; compatible = "sandbox,i2c"; clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_i2c0_pins>; + eeprom@2c { reg = <0x2c>; compatible = "i2c-eeprom"; @@ -714,6 +717,8 @@ lcd { u-boot,dm-pre-reloc; compatible = "sandbox,lcd-sdl"; + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_lcd_pins>; xres = <1366>; yres = <768>; }; @@ -964,6 +969,8 @@ pwm: pwm { compatible = "sandbox,pwm"; #pwm-cells = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_pwm_pins>; }; pwm2 { @@ -1035,6 +1042,9 @@ reg = <0 1>; compatible = "sandbox,spi"; cs-gpios = <0>, <0>, <&gpio_a 0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_spi0_pins>; + spi.bin@0 { reg = <0>; compatible = "spansion,m25p16", "jedec,spi-nor"; @@ -1124,6 +1134,8 @@ uart0: serial { compatible = "sandbox,serial"; u-boot,dm-pre-reloc; + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_uart0_pins>; }; usb_0: usb@0 { @@ -1392,6 +1404,66 @@ }; }; + pinctrl-single-no-width { + compatible = "pinctrl-single"; + reg = <0x0000 0x238>; + #pinctrl-cells = <1>; + pinctrl-single,function-mask = <0x7f>; + }; + + pinctrl-single-pins { + compatible = "pinctrl-single"; + reg = <0x0000 0x238>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x7f>; + + pinmux_pwm_pins: pinmux_pwm_pins { + pinctrl-single,pins = < 0x48 0x06 >; + }; + + pinmux_spi0_pins: pinmux_spi0_pins { + pinctrl-single,pins = < + 0x190 0x0c + 0x194 0x0c + 0x198 0x23 + 0x19c 0x0c + >; + }; + + pinmux_uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + 0x70 0x30 + 0x74 0x00 + >; + }; + }; + + pinctrl-single-bits { + compatible = "pinctrl-single"; + reg = <0x0000 0x50>; + #pinctrl-cells = <2>; + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xf>; + + pinmux_i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,bits = < + 0x10 0x00002200 0x0000ff00 + >; + }; + + pinmux_lcd_pins: pinmux_lcd_pins { + pinctrl-single,bits = < + 0x40 0x22222200 0xffffff00 + 0x44 0x22222222 0xffffffff + 0x48 0x00000022 0x000000ff + 0x48 0x02000000 0x0f000000 + 0x4c 0x02000022 0x0f0000ff + >; + }; + }; + hwspinlock@0 { compatible = "sandbox,hwspinlock"; }; diff --git a/configs/omap35_logic_somlv_defconfig b/configs/omap35_logic_somlv_defconfig index e6655c7828d..a8eab408f6e 100644 --- a/configs/omap35_logic_somlv_defconfig +++ b/configs/omap35_logic_somlv_defconfig @@ -4,6 +4,7 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_TEXT_BASE=0x80100000 CONFIG_TI_COMMON_CMD_OPTIONS=y +# CONFIG_SPL_GPIO_SUPPORT is not set CONFIG_SYS_MALLOC_F_LEN=0x4000 CONFIG_NR_DRAM_BANKS=2 CONFIG_SPL_TEXT_BASE=0x40200000 diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index c9318d4af56..6038dcba95c 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -198,6 +198,7 @@ CONFIG_PHY_SANDBOX=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_PINCTRL_SANDBOX=y +CONFIG_PINCTRL_SINGLE=y CONFIG_POWER_DOMAIN=y CONFIG_SANDBOX_POWER_DOMAIN=y CONFIG_DM_PMIC=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index b68f938cb37..689b3a9e202 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -142,6 +142,7 @@ CONFIG_PHY_SANDBOX=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_PINCTRL_SANDBOX=y +CONFIG_PINCTRL_SINGLE=y CONFIG_POWER_DOMAIN=y CONFIG_SANDBOX_POWER_DOMAIN=y CONFIG_DM_PMIC=y diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index 0dfc0593fb1..4f9282a8b9b 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o +obj-$(CONFIG_CLK_SUNXI) += clk_sun6i_rtc.o + obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c index ac8656fe895..df93d96b3b0 100644 --- a/drivers/clk/sunxi/clk_h6.c +++ b/drivers/clk/sunxi/clk_h6.c @@ -43,6 +43,7 @@ static struct ccu_clk_gate h6_gates[] = { [CLK_BUS_OHCI0] = GATE(0xa8c, BIT(0)), [CLK_BUS_OHCI3] = GATE(0xa8c, BIT(3)), [CLK_BUS_EHCI0] = GATE(0xa8c, BIT(4)), + [CLK_BUS_XHCI] = GATE(0xa8c, BIT(5)), [CLK_BUS_EHCI3] = GATE(0xa8c, BIT(7)), [CLK_BUS_OTG] = GATE(0xa8c, BIT(8)), }; @@ -71,6 +72,7 @@ static struct ccu_reset h6_resets[] = { [RST_BUS_OHCI0] = RESET(0xa8c, BIT(16)), [RST_BUS_OHCI3] = RESET(0xa8c, BIT(19)), [RST_BUS_EHCI0] = RESET(0xa8c, BIT(20)), + [RST_BUS_XHCI] = RESET(0xa8c, BIT(21)), [RST_BUS_EHCI3] = RESET(0xa8c, BIT(23)), [RST_BUS_OTG] = RESET(0xa8c, BIT(24)), }; diff --git a/drivers/clk/sunxi/clk_sun6i_rtc.c b/drivers/clk/sunxi/clk_sun6i_rtc.c new file mode 100644 index 00000000000..0c280d221ba --- /dev/null +++ b/drivers/clk/sunxi/clk_sun6i_rtc.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2018 Amarula Solutions. + * Copyright (C) 2020 Samuel Holland <samuel@sholland.org> + */ + +#include <clk-uclass.h> +#include <dm.h> + +static int clk_sun6i_rtc_enable(struct clk *clk) +{ + return 0; +} + +static const struct clk_ops clk_sun6i_rtc_ops = { + .enable = clk_sun6i_rtc_enable, +}; + +static const struct udevice_id sun6i_rtc_ids[] = { + { .compatible = "allwinner,sun6i-a31-rtc" }, + { .compatible = "allwinner,sun8i-a23-rtc" }, + { .compatible = "allwinner,sun8i-h3-rtc" }, + { .compatible = "allwinner,sun8i-r40-rtc" }, + { .compatible = "allwinner,sun8i-v3-rtc" }, + { .compatible = "allwinner,sun50i-h5-rtc" }, + { .compatible = "allwinner,sun50i-h6-rtc" }, + { } +}; + +U_BOOT_DRIVER(clk_sun6i_rtc) = { + .name = "clk_sun6i_rtc", + .id = UCLASS_CLK, + .of_match = sun6i_rtc_ids, + .ops = &clk_sun6i_rtc_ops, +}; diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 20c3c82aa98..48bdd0f6f5b 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1,34 +1,262 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch> + * Copyright (C) 2021 Dario Binacchi <dariobin@libero.it> */ #include <common.h> #include <dm.h> #include <dm/device_compat.h> +#include <dm/devres.h> #include <dm/pinctrl.h> #include <linux/libfdt.h> +#include <linux/list.h> #include <asm/io.h> +#include <sort.h> +/** + * struct single_pdata - platform data + * @base: first configuration register + * @offset: index of last configuration register + * @mask: configuration-value mask bits + * @width: configuration register bit width + * @bits_per_mux: true if one register controls more than one pin + */ struct single_pdata { - fdt_addr_t base; /* first configuration register */ - int offset; /* index of last configuration register */ - u32 mask; /* configuration-value mask bits */ - int width; /* configuration register bit width */ + fdt_addr_t base; + int offset; + u32 mask; + u32 width; bool bits_per_mux; }; +/** + * struct single_func - pinctrl function + * @node: list node + * @name: pinctrl function name + * @npins: number of entries in pins array + * @pins: pins array + */ +struct single_func { + struct list_head node; + const char *name; + unsigned int npins; + unsigned int *pins; +}; + +/** + * struct single_priv - private data + * @bits_per_pin: number of bits per pin + * @npins: number of selectable pins + * @pin_name: temporary buffer to store the pin name + */ +struct single_priv { +#if (IS_ENABLED(CONFIG_SANDBOX)) + u32 *sandbox_regs; +#endif + unsigned int bits_per_pin; + unsigned int npins; + char pin_name[PINNAME_SIZE]; + struct list_head functions; +}; + +/** + * struct single_fdt_pin_cfg - pin configuration + * + * This structure is used for the pin configuration parameters in case + * the register controls only one pin. + * + * @reg: configuration register offset + * @val: configuration register value + */ struct single_fdt_pin_cfg { - fdt32_t reg; /* configuration register offset */ - fdt32_t val; /* configuration register value */ + fdt32_t reg; + fdt32_t val; }; +/** + * struct single_fdt_bits_cfg - pin configuration + * + * This structure is used for the pin configuration parameters in case + * the register controls more than one pin. + * + * @reg: configuration register offset + * @val: configuration register value + * @mask: configuration register mask + */ struct single_fdt_bits_cfg { - fdt32_t reg; /* configuration register offset */ - fdt32_t val; /* configuration register value */ - fdt32_t mask; /* configuration register mask */ + fdt32_t reg; + fdt32_t val; + fdt32_t mask; }; +#if (!IS_ENABLED(CONFIG_SANDBOX)) + +static unsigned int single_read(struct udevice *dev, fdt_addr_t reg) +{ + struct single_pdata *pdata = dev_get_plat(dev); + + switch (pdata->width) { + case 8: + return readb(reg); + case 16: + return readw(reg); + default: /* 32 bits */ + return readl(reg); + } + + return readb(reg); +} + +static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg) +{ + struct single_pdata *pdata = dev_get_plat(dev); + + switch (pdata->width) { + case 8: + writeb(val, reg); + break; + case 16: + writew(val, reg); + break; + default: /* 32 bits */ + writel(val, reg); + } +} + +#else /* CONFIG_SANDBOX */ + +static unsigned int single_read(struct udevice *dev, fdt_addr_t reg) +{ + struct single_priv *priv = dev_get_priv(dev); + + return priv->sandbox_regs[reg]; +} + +static void single_write(struct udevice *dev, unsigned int val, fdt_addr_t reg) +{ + struct single_priv *priv = dev_get_priv(dev); + + priv->sandbox_regs[reg] = val; +} + +#endif /* CONFIG_SANDBOX */ + +/** + * single_get_pin_by_offset() - get a pin based on the register offset + * @dev: single driver instance + * @offset: register offset from the base + */ +static int single_get_pin_by_offset(struct udevice *dev, unsigned int offset) +{ + struct single_pdata *pdata = dev_get_plat(dev); + struct single_priv *priv = dev_get_priv(dev); + + if (offset > pdata->offset) { + dev_err(dev, "mux offset out of range: 0x%x (0x%x)\n", + offset, pdata->offset); + return -EINVAL; + } + + if (pdata->bits_per_mux) + return (offset * BITS_PER_BYTE) / priv->bits_per_pin; + + return offset / (pdata->width / BITS_PER_BYTE); +} + +static int single_get_offset_by_pin(struct udevice *dev, unsigned int pin) +{ + struct single_pdata *pdata = dev_get_plat(dev); + struct single_priv *priv = dev_get_priv(dev); + unsigned int mux_bytes; + + if (pin >= priv->npins) + return -EINVAL; + + mux_bytes = pdata->width / BITS_PER_BYTE; + if (pdata->bits_per_mux) { + int byte_num; + + byte_num = (priv->bits_per_pin * pin) / BITS_PER_BYTE; + return (byte_num / mux_bytes) * mux_bytes; + } + + return pin * mux_bytes; +} + +static const char *single_get_pin_function(struct udevice *dev, + unsigned int pin) +{ + struct single_priv *priv = dev_get_priv(dev); + struct single_func *func; + int i; + + list_for_each_entry(func, &priv->functions, node) { + for (i = 0; i < func->npins; i++) { + if (pin == func->pins[i]) + return func->name; + + if (pin < func->pins[i]) + break; + } + } + + return NULL; +} + +static int single_get_pin_muxing(struct udevice *dev, unsigned int pin, + char *buf, int size) +{ + struct single_pdata *pdata = dev_get_plat(dev); + struct single_priv *priv = dev_get_priv(dev); + fdt_addr_t reg; + const char *fname; + unsigned int val; + int offset, pin_shift = 0; + + offset = single_get_offset_by_pin(dev, pin); + if (offset < 0) + return offset; + + reg = pdata->base + offset; + val = single_read(dev, reg); + + if (pdata->bits_per_mux) + pin_shift = pin % (pdata->width / priv->bits_per_pin) * + priv->bits_per_pin; + + val &= (pdata->mask << pin_shift); + fname = single_get_pin_function(dev, pin); + snprintf(buf, size, "%pa 0x%08x %s", ®, val, + fname ? fname : "UNCLAIMED"); + return 0; +} + +static struct single_func *single_allocate_function(struct udevice *dev, + unsigned int group_pins) +{ + struct single_func *func; + + func = devm_kmalloc(dev, sizeof(*func), GFP_KERNEL); + if (!func) + return ERR_PTR(-ENOMEM); + + func->pins = devm_kmalloc(dev, sizeof(unsigned int) * group_pins, + GFP_KERNEL); + if (!func->pins) + return ERR_PTR(-ENOMEM); + + return func; +} + +static int single_pin_compare(const void *s1, const void *s2) +{ + int pin1 = *(const unsigned int *)s1; + int pin2 = *(const unsigned int *)s2; + + return pin1 - pin2; +} + /** * single_configure_pins() - Configure pins based on FDT data * @@ -42,75 +270,129 @@ struct single_fdt_bits_cfg { * @size: Size of the 'pins' array in bytes. * The number of register/value pairs in the 'pins' array therefore * equals to 'size / sizeof(struct single_fdt_pin_cfg)'. + * @fname: Function name. */ static int single_configure_pins(struct udevice *dev, const struct single_fdt_pin_cfg *pins, - int size) + int size, const char *fname) { struct single_pdata *pdata = dev_get_plat(dev); - int count = size / sizeof(struct single_fdt_pin_cfg); - phys_addr_t n, reg; - u32 val; + struct single_priv *priv = dev_get_priv(dev); + int n, pin, count = size / sizeof(struct single_fdt_pin_cfg); + struct single_func *func; + phys_addr_t reg; + u32 offset, val; + /* If function mask is null, needn't enable it. */ + if (!pdata->mask) + return 0; + + func = single_allocate_function(dev, count); + if (IS_ERR(func)) + return PTR_ERR(func); + + func->name = fname; + func->npins = 0; for (n = 0; n < count; n++, pins++) { - reg = fdt32_to_cpu(pins->reg); - if ((reg < 0) || (reg > pdata->offset)) { - dev_dbg(dev, " invalid register offset 0x%pa\n", ®); + offset = fdt32_to_cpu(pins->reg); + if (offset < 0 || offset > pdata->offset) { + dev_err(dev, " invalid register offset 0x%x\n", + offset); continue; } - reg += pdata->base; + + reg = pdata->base + offset; val = fdt32_to_cpu(pins->val) & pdata->mask; - switch (pdata->width) { - case 16: - writew((readw(reg) & ~pdata->mask) | val, reg); - break; - case 32: - writel((readl(reg) & ~pdata->mask) | val, reg); - break; - default: - dev_warn(dev, "unsupported register width %i\n", - pdata->width); + pin = single_get_pin_by_offset(dev, offset); + if (pin < 0) { + dev_err(dev, " failed to get pin by offset %x\n", + offset); continue; } - dev_dbg(dev, " reg/val 0x%pa/0x%08x\n", ®, val); + + single_write(dev, (single_read(dev, reg) & ~pdata->mask) | val, + reg); + dev_dbg(dev, " reg/val %pa/0x%08x\n", ®, val); + func->pins[func->npins] = pin; + func->npins++; } + + qsort(func->pins, func->npins, sizeof(func->pins[0]), + single_pin_compare); + list_add(&func->node, &priv->functions); return 0; } static int single_configure_bits(struct udevice *dev, const struct single_fdt_bits_cfg *pins, - int size) + int size, const char *fname) { struct single_pdata *pdata = dev_get_plat(dev); - int count = size / sizeof(struct single_fdt_bits_cfg); - phys_addr_t n, reg; - u32 val, mask; + struct single_priv *priv = dev_get_priv(dev); + int n, pin, count = size / sizeof(struct single_fdt_bits_cfg); + int npins_in_reg, pin_num_from_lsb; + struct single_func *func; + phys_addr_t reg; + u32 offset, val, mask, bit_pos, val_pos, mask_pos, submask; + npins_in_reg = pdata->width / priv->bits_per_pin; + func = single_allocate_function(dev, count * npins_in_reg); + if (IS_ERR(func)) + return PTR_ERR(func); + + func->name = fname; + func->npins = 0; for (n = 0; n < count; n++, pins++) { - reg = fdt32_to_cpu(pins->reg); - if ((reg < 0) || (reg > pdata->offset)) { - dev_dbg(dev, " invalid register offset 0x%pa\n", ®); + offset = fdt32_to_cpu(pins->reg); + if (offset < 0 || offset > pdata->offset) { + dev_dbg(dev, " invalid register offset 0x%x\n", + offset); + continue; + } + + reg = pdata->base + offset; + + pin = single_get_pin_by_offset(dev, offset); + if (pin < 0) { + dev_err(dev, " failed to get pin by offset 0x%pa\n", + ®); continue; } - reg += pdata->base; mask = fdt32_to_cpu(pins->mask); val = fdt32_to_cpu(pins->val) & mask; + single_write(dev, (single_read(dev, reg) & ~mask) | val, reg); + dev_dbg(dev, " reg/val %pa/0x%08x\n", ®, val); - switch (pdata->width) { - case 16: - writew((readw(reg) & ~mask) | val, reg); - break; - case 32: - writel((readl(reg) & ~mask) | val, reg); - break; - default: - dev_warn(dev, "unsupported register width %i\n", - pdata->width); - continue; + while (mask) { + bit_pos = __ffs(mask); + pin_num_from_lsb = bit_pos / priv->bits_per_pin; + mask_pos = pdata->mask << bit_pos; + val_pos = val & mask_pos; + submask = mask & mask_pos; + + if ((mask & mask_pos) == 0) { + dev_err(dev, "Invalid mask at 0x%x\n", offset); + break; + } + + mask &= ~mask_pos; + + if (submask != mask_pos) { + dev_warn(dev, + "Invalid submask 0x%x at 0x%x\n", + submask, offset); + continue; + } + + func->pins[func->npins] = pin + pin_num_from_lsb; + func->npins++; } - dev_dbg(dev, " reg/val 0x%pa/0x%08x\n", ®, val); } + + qsort(func->pins, func->npins, sizeof(func->pins[0]), + single_pin_compare); + list_add(&func->node, &priv->functions); return 0; } static int single_set_state(struct udevice *dev, @@ -128,7 +410,7 @@ static int single_set_state(struct udevice *dev, dev_dbg(dev, " invalid pin configuration in fdt\n"); return -FDT_ERR_BADSTRUCTURE; } - single_configure_pins(dev, prop, len); + single_configure_pins(dev, prop, len, config->name); return 0; } @@ -140,7 +422,7 @@ static int single_set_state(struct udevice *dev, dev_dbg(dev, " invalid bits configuration in fdt\n"); return -FDT_ERR_BADSTRUCTURE; } - single_configure_bits(dev, prop_bits, len); + single_configure_bits(dev, prop_bits, len, config->name); return 0; } @@ -148,20 +430,83 @@ static int single_set_state(struct udevice *dev, return len; } +static const char *single_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + struct single_priv *priv = dev_get_priv(dev); + + if (selector >= priv->npins) + snprintf(priv->pin_name, PINNAME_SIZE, "Error"); + else + snprintf(priv->pin_name, PINNAME_SIZE, "PIN%u", selector); + + return priv->pin_name; +} + +static int single_get_pins_count(struct udevice *dev) +{ + struct single_priv *priv = dev_get_priv(dev); + + return priv->npins; +} + +static int single_probe(struct udevice *dev) +{ + struct single_pdata *pdata = dev_get_plat(dev); + struct single_priv *priv = dev_get_priv(dev); + u32 size; + + INIT_LIST_HEAD(&priv->functions); + + size = pdata->offset + pdata->width / BITS_PER_BYTE; + #if (CONFIG_IS_ENABLED(SANDBOX)) + priv->sandbox_regs = + devm_kzalloc(dev, size * sizeof(*priv->sandbox_regs), + GFP_KERNEL); + if (!priv->sandbox_regs) + return -ENOMEM; + #endif + + priv->npins = size / (pdata->width / BITS_PER_BYTE); + if (pdata->bits_per_mux) { + priv->bits_per_pin = fls(pdata->mask); + priv->npins *= (pdata->width / priv->bits_per_pin); + } + + dev_dbg(dev, "%d pins\n", priv->npins); + return 0; +} + static int single_of_to_plat(struct udevice *dev) { fdt_addr_t addr; - u32 of_reg[2]; - int res; + fdt_size_t size; struct single_pdata *pdata = dev_get_plat(dev); + int ret; - pdata->width = - dev_read_u32_default(dev, "pinctrl-single,register-width", 0); + ret = dev_read_u32(dev, "pinctrl-single,register-width", &pdata->width); + if (ret) { + dev_err(dev, "missing register width\n"); + return ret; + } - res = dev_read_u32_array(dev, "reg", of_reg, 2); - if (res) - return res; - pdata->offset = of_reg[1] - pdata->width / 8; + switch (pdata->width) { + case 8: + case 16: + case 32: + break; + default: + dev_err(dev, "wrong register width\n"); + return -EINVAL; + } + + addr = dev_read_addr_size(dev, "reg", &size); + if (addr == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get base register size\n"); + return -EINVAL; + } + + pdata->offset = size - pdata->width / BITS_PER_BYTE; addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) { @@ -170,15 +515,22 @@ static int single_of_to_plat(struct udevice *dev) } pdata->base = addr; - pdata->mask = dev_read_u32_default(dev, "pinctrl-single,function-mask", - 0xffffffff); + ret = dev_read_u32(dev, "pinctrl-single,function-mask", &pdata->mask); + if (ret) { + pdata->mask = 0; + dev_warn(dev, "missing function register mask\n"); + } + pdata->bits_per_mux = dev_read_bool(dev, "pinctrl-single,bit-per-mux"); return 0; } const struct pinctrl_ops single_pinctrl_ops = { + .get_pins_count = single_get_pins_count, + .get_pin_name = single_get_pin_name, .set_state = single_set_state, + .get_pin_muxing = single_get_pin_muxing, }; static const struct udevice_id single_pinctrl_match[] = { @@ -192,5 +544,7 @@ U_BOOT_DRIVER(single_pinctrl) = { .of_match = single_pinctrl_match, .ops = &single_pinctrl_ops, .plat_auto = sizeof(struct single_pdata), + .priv_auto = sizeof(struct single_priv), .of_to_plat = single_of_to_plat, + .probe = single_probe, }; diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile index 147e1879922..4321673312b 100644 --- a/drivers/video/sunxi/Makefile +++ b/drivers/video/sunxi/Makefile @@ -4,4 +4,4 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o simplefb_common.o lcdc.o tve_common.o ../videomodes.o -obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o simplefb_common.o lcdc.o ../dw_hdmi.o sunxi_lcd.o +obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o simplefb_common.o lcdc.o sunxi_lcd.o diff --git a/env/Kconfig b/env/Kconfig index b473d7cfe1e..08e49c2a47f 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -324,6 +324,20 @@ config ENV_IS_IN_SPI_FLASH during a "saveenv" operation. CONFIG_ENV_OFFSET_REDUND must be aligned to an erase sector boundary. +config ENV_SECT_SIZE_AUTO + bool "Use automatically detected sector size" + depends on ENV_IS_IN_SPI_FLASH + help + Some boards exist in multiple variants, with different + flashes having different sector sizes. In such cases, you + can select this option to make U-Boot use the actual sector + size when figuring out how much to erase, which can thus be + more efficient on the flashes with smaller erase size. Since + the environment must always be aligned on a sector boundary, + CONFIG_ENV_OFFSET must be aligned to the largest of the + different sector sizes, and CONFIG_ENV_SECT_SIZE should be + set to that value. + config USE_ENV_SPI_BUS bool "SPI flash bus for environment" depends on ENV_IS_IN_SPI_FLASH @@ -462,6 +476,14 @@ config ENV_FAT_FILE It's a string of the FAT file name. This file use to store the environment. +config ENV_FAT_FILE_REDUND + string "Name of the FAT file to use for the environment" + depends on ENV_IS_IN_FAT && SYS_REDUNDAND_ENVIRONMENT + default "uboot-redund.env" + help + It's a string of the FAT file name. This file use to store the + redundant environment. + config ENV_EXT4_INTERFACE string "Name of the block device for the environment" depends on ENV_IS_IN_EXT4 diff --git a/env/common.c b/env/common.c index 2ee423beb5c..49bbb05eece 100644 --- a/env/common.c +++ b/env/common.c @@ -145,7 +145,7 @@ static unsigned char env_flags; int env_check_redund(const char *buf1, int buf1_read_fail, const char *buf2, int buf2_read_fail) { - int crc1_ok, crc2_ok; + int crc1_ok = 0, crc2_ok = 0; env_t *tmp_env1, *tmp_env2; tmp_env1 = (env_t *)buf1; @@ -153,25 +153,18 @@ int env_check_redund(const char *buf1, int buf1_read_fail, if (buf1_read_fail && buf2_read_fail) { puts("*** Error - No Valid Environment Area found\n"); + return -EIO; } else if (buf1_read_fail || buf2_read_fail) { puts("*** Warning - some problems detected "); puts("reading environment; recovered successfully\n"); } - if (buf1_read_fail && buf2_read_fail) { - return -EIO; - } else if (!buf1_read_fail && buf2_read_fail) { - gd->env_valid = ENV_VALID; - return -EINVAL; - } else if (buf1_read_fail && !buf2_read_fail) { - gd->env_valid = ENV_REDUND; - return -ENOENT; - } - - crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == - tmp_env1->crc; - crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == - tmp_env2->crc; + if (!buf1_read_fail) + crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == + tmp_env1->crc; + if (!buf2_read_fail) + crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == + tmp_env2->crc; if (!crc1_ok && !crc2_ok) { return -ENOMSG; /* needed for env_load() */ @@ -208,10 +201,6 @@ int env_import_redund(const char *buf1, int buf1_read_fail, if (ret == -EIO) { env_set_default("bad env area", 0); return -EIO; - } else if (ret == -EINVAL) { - return env_import((char *)buf1, 1, flags); - } else if (ret == -ENOENT) { - return env_import((char *)buf2, 1, flags); } else if (ret == -ENOMSG) { env_set_default("bad CRC", 0); return -ENOMSG; diff --git a/env/env.c b/env/env.c index caefa33e1d4..e5340080060 100644 --- a/env/env.c +++ b/env/env.c @@ -335,6 +335,9 @@ int env_init(void) debug("%s: Environment %s init done (ret=%d)\n", __func__, drv->name, ret); + + if (gd->env_valid == ENV_INVALID) + ret = -ENOENT; } if (!prio) diff --git a/env/ext4.c b/env/ext4.c index ec643f2226a..9f65afb8a42 100644 --- a/env/ext4.c +++ b/env/ext4.c @@ -188,6 +188,5 @@ U_BOOT_ENV_LOCATION(ext4) = { ENV_NAME("EXT4") .load = env_ext4_load, .save = ENV_SAVE_PTR(env_ext4_save), - .erase = CONFIG_IS_ENABLED(CMD_ERASEENV) ? env_ext4_erase : - NULL, + .erase = ENV_ERASE_PTR(env_ext4_erase), }; diff --git a/env/fat.c b/env/fat.c index 653a38fd937..9d37d26f9ed 100644 --- a/env/fat.c +++ b/env/fat.c @@ -18,6 +18,7 @@ #include <fat.h> #include <mmc.h> #include <asm/cache.h> +#include <asm/global_data.h> #include <linux/stddef.h> #ifdef CONFIG_SPL_BUILD @@ -29,6 +30,8 @@ # define LOADENV #endif +DECLARE_GLOBAL_DATA_PTR; + static char *env_fat_device_and_part(void) { #ifdef CONFIG_MMC @@ -53,6 +56,7 @@ static int env_fat_save(void) env_t __aligned(ARCH_DMA_MINALIGN) env_new; struct blk_desc *dev_desc = NULL; struct disk_partition info; + const char *file = CONFIG_ENV_FAT_FILE; int dev, part; int err; loff_t size; @@ -78,29 +82,41 @@ static int env_fat_save(void) return 1; } - err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t), - &size); +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT + if (gd->env_valid == ENV_VALID) + file = CONFIG_ENV_FAT_FILE_REDUND; +#endif + + err = file_fat_write(file, (void *)&env_new, 0, sizeof(env_t), &size); if (err == -1) { /* * This printf is embedded in the messages from env_save that * will calling it. The missing \n is intentional. */ printf("Unable to write \"%s\" from %s%d:%d... ", - CONFIG_ENV_FAT_FILE, CONFIG_ENV_FAT_INTERFACE, dev, part); + file, CONFIG_ENV_FAT_INTERFACE, dev, part); return 1; } +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT + gd->env_valid = (gd->env_valid == ENV_REDUND) ? ENV_VALID : ENV_REDUND; +#endif + return 0; } #ifdef LOADENV static int env_fat_load(void) { - ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + ALLOC_CACHE_ALIGN_BUFFER(char, buf1, CONFIG_ENV_SIZE); +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT + ALLOC_CACHE_ALIGN_BUFFER(char, buf2, CONFIG_ENV_SIZE); + int err2; +#endif struct blk_desc *dev_desc = NULL; struct disk_partition info; int dev, part; - int err; + int err1; #ifdef CONFIG_MMC if (!strcmp(CONFIG_ENV_FAT_INTERFACE, "mmc")) @@ -124,8 +140,15 @@ static int env_fat_load(void) goto err_env_relocate; } - err = file_fat_read(CONFIG_ENV_FAT_FILE, buf, CONFIG_ENV_SIZE); - if (err == -1) { + err1 = file_fat_read(CONFIG_ENV_FAT_FILE, buf1, CONFIG_ENV_SIZE); +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT + err2 = file_fat_read(CONFIG_ENV_FAT_FILE_REDUND, buf2, CONFIG_ENV_SIZE); + + err1 = (err1 >= 0) ? 0 : -1; + err2 = (err2 >= 0) ? 0 : -1; + return env_import_redund(buf1, err1, buf2, err2, H_EXTERNAL); +#else + if (err1 < 0) { /* * This printf is embedded in the messages from env_save that * will calling it. The missing \n is intentional. @@ -135,7 +158,8 @@ static int env_fat_load(void) goto err_env_relocate; } - return env_import(buf, 1, H_EXTERNAL); + return env_import(buf1, 1, H_EXTERNAL); +#endif err_env_relocate: env_set_default(NULL, 0); diff --git a/env/flags.c b/env/flags.c index df4aed26b2c..e3e833c4333 100644 --- a/env/flags.c +++ b/env/flags.c @@ -563,12 +563,13 @@ int env_flags_validate(const struct env_entry *item, const char *newval, return 1; #endif -#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE if (flag & H_FORCE) { +#ifdef CONFIG_ENV_ACCESS_IGNORE_FORCE printf("## Error: Can't force access to \"%s\"\n", name); +#else return 0; - } #endif + } switch (op) { case env_op_delete: if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_DELETE) { diff --git a/env/mmc.c b/env/mmc.c index 9b226be1d5b..09e94f0bd3b 100644 --- a/env/mmc.c +++ b/env/mmc.c @@ -233,7 +233,6 @@ fini: return ret; } -#if defined(CONFIG_CMD_ERASEENV) static inline int erase_env(struct mmc *mmc, unsigned long size, unsigned long offset) { @@ -279,7 +278,6 @@ static int env_mmc_erase(void) return ret; } -#endif /* CONFIG_CMD_ERASEENV */ #endif /* CONFIG_CMD_SAVEENV && !CONFIG_SPL_BUILD */ static inline int read_env(struct mmc *mmc, unsigned long size, @@ -394,8 +392,6 @@ U_BOOT_ENV_LOCATION(mmc) = { .load = env_mmc_load, #ifndef CONFIG_SPL_BUILD .save = env_save_ptr(env_mmc_save), -#if defined(CONFIG_CMD_ERASEENV) - .erase = env_mmc_erase, -#endif + .erase = ENV_ERASE_PTR(env_mmc_erase) #endif }; @@ -28,16 +28,23 @@ #define INITENV #endif +#define OFFSET_INVALID (~(u32)0) + #ifdef CONFIG_ENV_OFFSET_REDUND +#define ENV_OFFSET_REDUND CONFIG_ENV_OFFSET_REDUND + static ulong env_offset = CONFIG_ENV_OFFSET; static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND; + +#else + +#define ENV_OFFSET_REDUND OFFSET_INVALID + #endif /* CONFIG_ENV_OFFSET_REDUND */ DECLARE_GLOBAL_DATA_PTR; -static struct spi_flash *env_flash; - -static int setup_flash_device(void) +static int setup_flash_device(struct spi_flash **env_flash) { #if CONFIG_IS_ENABLED(DM_SPI_FLASH) struct udevice *new; @@ -52,14 +59,11 @@ static int setup_flash_device(void) return ret; } - env_flash = dev_get_uclass_priv(new); + *env_flash = dev_get_uclass_priv(new); #else - if (env_flash) - spi_flash_free(env_flash); - - env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, - CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); - if (!env_flash) { + *env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, + CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); + if (!*env_flash) { env_set_default("spi_flash_probe() failed", 0); return -EIO; } @@ -72,13 +76,18 @@ static int env_sf_save(void) { env_t env_new; char *saved_buffer = NULL, flag = ENV_REDUND_OBSOLETE; - u32 saved_size, saved_offset, sector; + u32 saved_size = 0, saved_offset = 0, sector; + u32 sect_size = CONFIG_ENV_SECT_SIZE; int ret; + struct spi_flash *env_flash; - ret = setup_flash_device(); + ret = setup_flash_device(&env_flash); if (ret) return ret; + if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO)) + sect_size = env_flash->mtd.erasesize; + ret = env_export(&env_new); if (ret) return -EIO; @@ -93,8 +102,8 @@ static int env_sf_save(void) } /* Is the sector larger than the env (i.e. embedded) */ - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { - saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; + if (sect_size > CONFIG_ENV_SIZE) { + saved_size = sect_size - CONFIG_ENV_SIZE; saved_offset = env_new_offset + CONFIG_ENV_SIZE; saved_buffer = memalign(ARCH_DMA_MINALIGN, saved_size); if (!saved_buffer) { @@ -107,11 +116,11 @@ static int env_sf_save(void) goto done; } - sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); + sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size); puts("Erasing SPI flash..."); ret = spi_flash_erase(env_flash, env_new_offset, - sector * CONFIG_ENV_SECT_SIZE); + sector * sect_size); if (ret) goto done; @@ -122,7 +131,7 @@ static int env_sf_save(void) if (ret) goto done; - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + if (sect_size > CONFIG_ENV_SIZE) { ret = spi_flash_write(env_flash, saved_offset, saved_size, saved_buffer); if (ret) @@ -141,6 +150,8 @@ static int env_sf_save(void) printf("Valid environment: %d\n", (int)gd->env_valid); done: + spi_flash_free(env_flash); + if (saved_buffer) free(saved_buffer); @@ -152,6 +163,7 @@ static int env_sf_load(void) int ret; int read1_fail, read2_fail; env_t *tmp_env1, *tmp_env2; + struct spi_flash *env_flash; tmp_env1 = (env_t *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE); @@ -163,7 +175,7 @@ static int env_sf_load(void) goto out; } - ret = setup_flash_device(); + ret = setup_flash_device(&env_flash); if (ret) goto out; @@ -176,7 +188,6 @@ static int env_sf_load(void) read2_fail, H_EXTERNAL); spi_flash_free(env_flash); - env_flash = NULL; out: free(tmp_env1); free(tmp_env2); @@ -186,18 +197,23 @@ out: #else static int env_sf_save(void) { - u32 saved_size, saved_offset, sector; + u32 saved_size = 0, saved_offset = 0, sector; + u32 sect_size = CONFIG_ENV_SECT_SIZE; char *saved_buffer = NULL; int ret = 1; env_t env_new; + struct spi_flash *env_flash; - ret = setup_flash_device(); + ret = setup_flash_device(&env_flash); if (ret) return ret; + if (IS_ENABLED(CONFIG_ENV_SECT_SIZE_AUTO)) + sect_size = env_flash->mtd.erasesize; + /* Is the sector larger than the env (i.e. embedded) */ - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { - saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE; + if (sect_size > CONFIG_ENV_SIZE) { + saved_size = sect_size - CONFIG_ENV_SIZE; saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE; saved_buffer = malloc(saved_size); if (!saved_buffer) @@ -213,11 +229,11 @@ static int env_sf_save(void) if (ret) goto done; - sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, CONFIG_ENV_SECT_SIZE); + sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size); puts("Erasing SPI flash..."); ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, - sector * CONFIG_ENV_SECT_SIZE); + sector * sect_size); if (ret) goto done; @@ -227,7 +243,7 @@ static int env_sf_save(void) if (ret) goto done; - if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) { + if (sect_size > CONFIG_ENV_SIZE) { ret = spi_flash_write(env_flash, saved_offset, saved_size, saved_buffer); if (ret) @@ -238,6 +254,8 @@ static int env_sf_save(void) puts("done\n"); done: + spi_flash_free(env_flash); + if (saved_buffer) free(saved_buffer); @@ -248,6 +266,7 @@ static int env_sf_load(void) { int ret; char *buf = NULL; + struct spi_flash *env_flash; buf = (char *)memalign(ARCH_DMA_MINALIGN, CONFIG_ENV_SIZE); if (!buf) { @@ -255,7 +274,7 @@ static int env_sf_load(void) return -EIO; } - ret = setup_flash_device(); + ret = setup_flash_device(&env_flash); if (ret) goto out; @@ -272,7 +291,6 @@ static int env_sf_load(void) err_read: spi_flash_free(env_flash); - env_flash = NULL; out: free(buf); @@ -280,6 +298,30 @@ out: } #endif +static int env_sf_erase(void) +{ + int ret; + env_t env; + struct spi_flash *env_flash; + + ret = setup_flash_device(&env_flash); + if (ret) + return ret; + + memset(&env, 0, sizeof(env_t)); + ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, &env); + if (ret) + goto done; + + if (ENV_OFFSET_REDUND != OFFSET_INVALID) + ret = spi_flash_write(env_flash, ENV_OFFSET_REDUND, CONFIG_ENV_SIZE, &env); + +done: + spi_flash_free(env_flash); + + return ret; +} + #if CONFIG_ENV_ADDR != 0x0 __weak void *env_sf_get_env_addr(void) { @@ -320,6 +362,7 @@ static int env_sf_init_early(void) int crc1_ok; env_t *tmp_env2 = NULL; env_t *tmp_env1; + struct spi_flash *env_flash; /* * if malloc is not ready yet, we cannot use @@ -337,7 +380,7 @@ static int env_sf_init_early(void) if (!tmp_env1 || !tmp_env2) goto out; - ret = setup_flash_device(); + ret = setup_flash_device(&env_flash); if (ret) goto out; @@ -351,7 +394,7 @@ static int env_sf_init_early(void) ret = env_check_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2, read2_fail); - if (ret == -EIO || ret == -ENOMSG) + if (ret < 0) goto err_read; if (gd->env_valid == ENV_VALID) @@ -372,10 +415,12 @@ static int env_sf_init_early(void) gd->env_addr = (unsigned long)&tmp_env1->data; } + spi_flash_free(env_flash); + return 0; err_read: spi_flash_free(env_flash); - env_flash = NULL; + free(tmp_env1); if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) free(tmp_env2); @@ -406,6 +451,7 @@ U_BOOT_ENV_LOCATION(sf) = { .location = ENVL_SPI_FLASH, ENV_NAME("SPIFlash") .load = env_sf_load, - .save = CONFIG_IS_ENABLED(SAVEENV) ? ENV_SAVE_PTR(env_sf_save) : NULL, + .save = ENV_SAVE_PTR(env_sf_save), + .erase = ENV_ERASE_PTR(env_sf_erase), .init = env_sf_init, }; diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 33a4d7b6373..9e37e996847 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -62,7 +62,7 @@ #define SDRAM_OFFSET(x) 0x2##x #define CONFIG_SYS_SDRAM_BASE 0x20000000 #define CONFIG_SYS_LOAD_ADDR 0x22000000 /* default load address */ -/* Note SPL_STACK_R_ADDR is set through Kconfig, we include it here +/* Note SPL_STACK_R_ADDR is set through Kconfig, we include it here * since it needs to fit in with the other values. By also #defining it * we get warnings if the Kconfig value mismatches. */ #define CONFIG_SPL_STACK_R_ADDR 0x2fe00000 @@ -72,7 +72,7 @@ #define CONFIG_SYS_SDRAM_BASE 0x40000000 #define CONFIG_SYS_LOAD_ADDR 0x42000000 /* default load address */ /* V3s do not have enough memory to place code at 0x4a000000 */ -/* Note SPL_STACK_R_ADDR is set through Kconfig, we include it here +/* Note SPL_STACK_R_ADDR is set through Kconfig, we include it here * since it needs to fit in with the other values. By also #defining it * we get warnings if the Kconfig value mismatches. */ #define CONFIG_SPL_STACK_R_ADDR 0x4fe00000 @@ -240,40 +240,44 @@ extern int soft_i2c_gpio_scl; * There is no compression for arm64 kernels (yet), so leave some space * for really big kernels, say 256MB for now. * Scripts, PXE and DTBs should go afterwards, leaving the rest for the initrd. - * Align the initrd to a 2MB page. */ -#define BOOTM_SIZE __stringify(0xa000000) -#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(0080000)) -#define FDT_ADDR_R __stringify(SDRAM_OFFSET(FA00000)) -#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(FC00000)) -#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(FD00000)) -#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(FE00000)) +#define BOOTM_SIZE __stringify(0xa000000) +#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(0080000)) +#define KERNEL_COMP_ADDR_R __stringify(SDRAM_OFFSET(4000000)) +#define KERNEL_COMP_SIZE __stringify(0xb000000) +#define FDT_ADDR_R __stringify(SDRAM_OFFSET(FA00000)) +#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(FC00000)) +#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(FD00000)) +#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(FE00000)) +#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(FF00000)) #else /* * 160M RAM (256M minimum minus 64MB heap + 32MB for u-boot, stack, fb, etc. * 32M uncompressed kernel, 16M compressed kernel, 1M fdt, - * 1M script, 1M pxe and the ramdisk at the end. + * 1M script, 1M pxe, 1M dt overlay and the ramdisk at the end. */ #ifndef CONFIG_MACH_SUN8I_V3S -#define BOOTM_SIZE __stringify(0xa000000) -#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(2000000)) -#define FDT_ADDR_R __stringify(SDRAM_OFFSET(3000000)) -#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(3100000)) -#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(3200000)) -#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(3300000)) +#define BOOTM_SIZE __stringify(0xa000000) +#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(2000000)) +#define FDT_ADDR_R __stringify(SDRAM_OFFSET(3000000)) +#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(3100000)) +#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(3200000)) +#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(3300000)) +#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(3400000)) #else /* * 64M RAM minus 2MB heap + 16MB for u-boot, stack, fb, etc. * 16M uncompressed kernel, 8M compressed kernel, 1M fdt, - * 1M script, 1M pxe and the ramdisk at the end. + * 1M script, 1M pxe, 1M dt overlay and the ramdisk at the end. */ -#define BOOTM_SIZE __stringify(0x2e00000) -#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(1000000)) -#define FDT_ADDR_R __stringify(SDRAM_OFFSET(1800000)) -#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(1900000)) -#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(1A00000)) -#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(1B00000)) +#define BOOTM_SIZE __stringify(0x2e00000) +#define KERNEL_ADDR_R __stringify(SDRAM_OFFSET(1000000)) +#define FDT_ADDR_R __stringify(SDRAM_OFFSET(1800000)) +#define SCRIPT_ADDR_R __stringify(SDRAM_OFFSET(1900000)) +#define PXEFILE_ADDR_R __stringify(SDRAM_OFFSET(1A00000)) +#define FDTOVERLAY_ADDR_R __stringify(SDRAM_OFFSET(1B00000)) +#define RAMDISK_ADDR_R __stringify(SDRAM_OFFSET(1C00000)) #endif #endif @@ -283,8 +287,21 @@ extern int soft_i2c_gpio_scl; "fdt_addr_r=" FDT_ADDR_R "\0" \ "scriptaddr=" SCRIPT_ADDR_R "\0" \ "pxefile_addr_r=" PXEFILE_ADDR_R "\0" \ + "fdtoverlay_addr_r=" FDTOVERLAY_ADDR_R "\0" \ "ramdisk_addr_r=" RAMDISK_ADDR_R "\0" +#ifdef CONFIG_ARM64 + +#define MEM_LAYOUT_ENV_EXTRA_SETTINGS \ + "kernel_comp_addr_r=" KERNEL_COMP_ADDR_R "\0" \ + "kernel_comp_size=" KERNEL_COMP_SIZE "\0" + +#else + +#define MEM_LAYOUT_ENV_EXTRA_SETTINGS "" + +#endif + #define DFU_ALT_INFO_RAM \ "dfu_alt_info_ram=" \ "kernel ram " KERNEL_ADDR_R " 0x1000000;" \ @@ -435,6 +452,7 @@ extern int soft_i2c_gpio_scl; #define CONFIG_EXTRA_ENV_SETTINGS \ CONSOLE_ENV_SETTINGS \ MEM_LAYOUT_ENV_SETTINGS \ + MEM_LAYOUT_ENV_EXTRA_SETTINGS \ DFU_ALT_INFO_RAM \ "fdtfile=" FDTFILE "\0" \ "console=ttyS0,115200\0" \ diff --git a/include/env.h b/include/env.h index c15339a93f1..b5731e4b9a7 100644 --- a/include/env.h +++ b/include/env.h @@ -328,8 +328,6 @@ int env_export(struct environment_s *env_out); * @buf2_read_fail: 0 if buf2 is valid, non-zero if invalid * @return 0 if OK, * -EIO if no environment is valid, - * -EINVAL if read of second entry is good - * -ENOENT if read of first entry is good * -ENOMSG if the CRC was bad */ diff --git a/include/env_internal.h b/include/env_internal.h index 708c833a550..b7bddcb00d8 100644 --- a/include/env_internal.h +++ b/include/env_internal.h @@ -211,6 +211,7 @@ struct env_driver { #endif #define ENV_SAVE_PTR(x) (CONFIG_IS_ENABLED(SAVEENV) ? (x) : NULL) +#define ENV_ERASE_PTR(x) (CONFIG_IS_ENABLED(CMD_ERASEENV) ? (x) : NULL) extern struct hsearch_data env_htab; diff --git a/test/dm/pinmux.c b/test/dm/pinmux.c index 047184d4bcb..265df4ccb97 100644 --- a/test/dm/pinmux.c +++ b/test/dm/pinmux.c @@ -9,16 +9,21 @@ #include <dm/test.h> #include <test/ut.h> -static int dm_test_pinmux(struct unit_test_state *uts) -{ - char buf[64]; - struct udevice *dev; - +static char buf[64]; #define test_muxing(selector, expected) do { \ ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \ ut_asserteq_str(expected, (char *)&buf); \ } while (0) +#define test_name(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_name(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +static int dm_test_pinmux(struct unit_test_state *uts) +{ + struct udevice *dev; + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, "pinctrl", &dev)); test_muxing(0, "UART TX."); test_muxing(1, "UART RX."); @@ -54,4 +59,80 @@ static int dm_test_pinmux(struct unit_test_state *uts) return 0; } + DM_TEST(dm_test_pinmux, UT_TESTF_SCAN_FDT); + +static int dm_test_pinctrl_single(struct unit_test_state *uts) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_name(UCLASS_PINCTRL, + "pinctrl-single-no-width", &dev); + ut_asserteq(-EINVAL, ret); + ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_SERIAL, "serial", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_SPI, "spi@0", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, + "pinctrl-single-pins", &dev)); + ut_asserteq(142, pinctrl_get_pins_count(dev)); + test_name(0, "PIN0"); + test_name(141, "PIN141"); + test_name(142, "Error"); + test_muxing(0, "0x00000000 0x00000000 UNCLAIMED"); + test_muxing(18, "0x00000048 0x00000006 pinmux_pwm_pins"); + test_muxing(28, "0x00000070 0x00000030 pinmux_uart0_pins"); + test_muxing(29, "0x00000074 0x00000000 pinmux_uart0_pins"); + test_muxing(100, "0x00000190 0x0000000c pinmux_spi0_pins"); + test_muxing(101, "0x00000194 0x0000000c pinmux_spi0_pins"); + test_muxing(102, "0x00000198 0x00000023 pinmux_spi0_pins"); + test_muxing(103, "0x0000019c 0x0000000c pinmux_spi0_pins"); + ret = pinctrl_get_pin_muxing(dev, 142, buf, sizeof(buf)); + ut_asserteq(-EINVAL, ret); + ut_assertok(uclass_get_device_by_name(UCLASS_I2C, "i2c@0", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_VIDEO, "lcd", &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, + "pinctrl-single-bits", &dev)); + ut_asserteq(160, pinctrl_get_pins_count(dev)); + test_name(0, "PIN0"); + test_name(159, "PIN159"); + test_name(160, "Error"); + test_muxing(0, "0x00000000 0x00000000 UNCLAIMED"); + test_muxing(34, "0x00000010 0x00000200 pinmux_i2c0_pins"); + test_muxing(35, "0x00000010 0x00002000 pinmux_i2c0_pins"); + test_muxing(130, "0x00000040 0x00000200 pinmux_lcd_pins"); + test_muxing(131, "0x00000040 0x00002000 pinmux_lcd_pins"); + test_muxing(132, "0x00000040 0x00020000 pinmux_lcd_pins"); + test_muxing(133, "0x00000040 0x00200000 pinmux_lcd_pins"); + test_muxing(134, "0x00000040 0x02000000 pinmux_lcd_pins"); + test_muxing(135, "0x00000040 0x20000000 pinmux_lcd_pins"); + test_muxing(136, "0x00000044 0x00000002 pinmux_lcd_pins"); + test_muxing(137, "0x00000044 0x00000020 pinmux_lcd_pins"); + test_muxing(138, "0x00000044 0x00000200 pinmux_lcd_pins"); + test_muxing(139, "0x00000044 0x00002000 pinmux_lcd_pins"); + test_muxing(140, "0x00000044 0x00020000 pinmux_lcd_pins"); + test_muxing(141, "0x00000044 0x00200000 pinmux_lcd_pins"); + test_muxing(142, "0x00000044 0x02000000 pinmux_lcd_pins"); + test_muxing(143, "0x00000044 0x20000000 pinmux_lcd_pins"); + test_muxing(144, "0x00000048 0x00000002 pinmux_lcd_pins"); + test_muxing(145, "0x00000048 0x00000020 pinmux_lcd_pins"); + test_muxing(146, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(147, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(148, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(149, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(150, "0x00000048 0x02000000 pinmux_lcd_pins"); + test_muxing(151, "0x00000048 0x00000000 UNCLAIMED"); + test_muxing(152, "0x0000004c 0x00000002 pinmux_lcd_pins"); + test_muxing(153, "0x0000004c 0x00000020 pinmux_lcd_pins"); + test_muxing(154, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(155, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(156, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(157, "0x0000004c 0x00000000 UNCLAIMED"); + test_muxing(158, "0x0000004c 0x02000000 pinmux_lcd_pins"); + test_muxing(159, "0x0000004c 0x00000000 UNCLAIMED"); + ret = pinctrl_get_pin_muxing(dev, 160, buf, sizeof(buf)); + ut_asserteq(-EINVAL, ret); + return 0; +} + +DM_TEST(dm_test_pinctrl_single, UT_TESTF_SCAN_FDT); |