Merge tag 'efi-2021-07-rc1-2' of https://source.denx.de/u-boot/custodians/u-boot-efi
Pull request for efi-2021-07-rc1-2
Documentation:
man-page for fatinfo
Bug fixes:
memory leak in efi_capsule_scan_dir()
incorrect invocations of EFI_CALL macro creating ESRT table
buffer overflow in tcg2_create_digest()
diff --git a/arch/arc/dts/iot_devkit.dts b/arch/arc/dts/iot_devkit.dts
index c0173fa..2122827 100644
--- a/arch/arc/dts/iot_devkit.dts
+++ b/arch/arc/dts/iot_devkit.dts
@@ -39,7 +39,7 @@
};
usbphy: phy {
- compatible = "nop-phy";
+ compatible = "usb-nop-xceiv";
#phy-cells = <0>;
};
diff --git a/arch/arm/dts/imx8mm.dtsi b/arch/arm/dts/imx8mm.dtsi
index c824f26..b142b80 100644
--- a/arch/arm/dts/imx8mm.dtsi
+++ b/arch/arm/dts/imx8mm.dtsi
@@ -4,6 +4,8 @@
*/
#include <dt-bindings/clock/imx8mm-clock.h>
+#include <dt-bindings/power/imx8mm-power.h>
+#include <dt-bindings/reset/imx8mq-reset.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -241,6 +243,7 @@
};
usbphynop1: usbphynop1 {
+ #phy-cells = <0>;
compatible = "usb-nop-xceiv";
clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
@@ -249,6 +252,7 @@
};
usbphynop2: usbphynop2 {
+ #phy-cells = <0>;
compatible = "usb-nop-xceiv";
clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
@@ -590,6 +594,75 @@
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
};
+
+ gpc: gpc@303a0000 {
+ compatible = "fsl,imx8mm-gpc";
+ reg = <0x303a0000 0x10000>;
+ interrupt-parent = <&gic>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ pgc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pgc_hsiomix: power-domain@0 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_HSIOMIX>;
+ clocks = <&clk IMX8MM_CLK_USB_BUS>;
+ };
+
+ pgc_pcie: power-domain@1 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_PCIE>;
+ power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_otg1: power-domain@2 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_OTG1>;
+ power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_otg2: power-domain@3 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_OTG2>;
+ power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_gpumix: power-domain@4 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_GPUMIX>;
+ clocks = <&clk IMX8MM_CLK_GPU_BUS_ROOT>,
+ <&clk IMX8MM_CLK_GPU_AHB>;
+ };
+
+ pgc_gpu: power-domain@5 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_GPU>;
+ clocks = <&clk IMX8MM_CLK_GPU_AHB>,
+ <&clk IMX8MM_CLK_GPU_BUS_ROOT>,
+ <&clk IMX8MM_CLK_GPU2D_ROOT>,
+ <&clk IMX8MM_CLK_GPU3D_ROOT>;
+ resets = <&src IMX8MQ_RESET_GPU_RESET>;
+ power-domains = <&pgc_gpumix>;
+ };
+
+ dispmix_pd: power-domain@10 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_DISPMIX>;
+ clocks = <&clk IMX8MM_CLK_DISP_ROOT>,
+ <&clk IMX8MM_CLK_DISP_AXI_ROOT>,
+ <&clk IMX8MM_CLK_DISP_APB_ROOT>;
+ };
+
+ mipi_pd: power-domain@11 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_MIPI>;
+ power-domains = <&dispmix_pd>;
+ };
+ };
+ };
};
aips2: bus@30400000 {
@@ -936,8 +1009,9 @@
clock-names = "usb1_ctrl_root_clk";
assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
- fsl,usbphy = <&usbphynop1>;
+ phys = <&usbphynop1>;
fsl,usbmisc = <&usbmisc1 0>;
+ power-domains = <&pgc_otg1>;
status = "disabled";
};
@@ -955,8 +1029,9 @@
clock-names = "usb1_ctrl_root_clk";
assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
- fsl,usbphy = <&usbphynop2>;
+ phys = <&usbphynop2>;
fsl,usbmisc = <&usbmisc2 0>;
+ power-domains = <&pgc_otg2>;
status = "disabled";
};
diff --git a/arch/arm/dts/imx8mn.dtsi b/arch/arm/dts/imx8mn.dtsi
index 16ea500..edcb415 100644
--- a/arch/arm/dts/imx8mn.dtsi
+++ b/arch/arm/dts/imx8mn.dtsi
@@ -4,6 +4,8 @@
*/
#include <dt-bindings/clock/imx8mn-clock.h>
+#include <dt-bindings/power/imx8mn-power.h>
+#include <dt-bindings/reset/imx8mq-reset.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -612,6 +614,54 @@
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
};
+
+ gpc: gpc@303a0000 {
+ compatible = "fsl,imx8mn-gpc";
+ reg = <0x303a0000 0x10000>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+
+ pgc {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pgc_hsiomix: power-domain@0 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MN_POWER_DOMAIN_HSIOMIX>;
+ clocks = <&clk IMX8MN_CLK_USB_BUS>;
+ };
+
+ pgc_otg1: power-domain@1 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MN_POWER_DOMAIN_OTG1>;
+ power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_gpumix: power-domain@2 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MN_POWER_DOMAIN_GPUMIX>;
+ clocks = <&clk IMX8MN_CLK_GPU_CORE_ROOT>,
+ <&clk IMX8MN_CLK_GPU_SHADER_DIV>,
+ <&clk IMX8MN_CLK_GPU_BUS_ROOT>,
+ <&clk IMX8MN_CLK_GPU_AHB>;
+ resets = <&src IMX8MQ_RESET_GPU_RESET>;
+ };
+
+ dispmix_pd: power-domain@3 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MN_POWER_DOMAIN_DISPMIX>;
+ clocks = <&clk IMX8MN_CLK_DISP_PIXEL_ROOT>,
+ <&clk IMX8MN_CLK_DISP_AXI_ROOT>,
+ <&clk IMX8MN_CLK_DISP_APB_ROOT>;
+ };
+
+ mipi_pd: power-domain@4 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MN_POWER_DOMAIN_MIPI>;
+ power-domains = <&dispmix_pd>;
+ };
+ };
+ };
};
aips2: bus@30400000 {
@@ -962,8 +1012,9 @@
clock-names = "usb1_ctrl_root_clk";
assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>;
assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>;
- fsl,usbphy = <&usbphynop1>;
+ phys = <&usbphynop1>;
fsl,usbmisc = <&usbmisc1 0>;
+ power-domains = <&pgc_otg1>;
status = "disabled";
};
@@ -1030,6 +1081,7 @@
};
usbphynop1: usbphynop1 {
+ #phy-cells = <0>;
compatible = "usb-nop-xceiv";
clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
diff --git a/arch/arm/dts/k3-j721e-main.dtsi b/arch/arm/dts/k3-j721e-main.dtsi
index e47b6c0..07b4896 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/keystone-k2g-evm.dts b/arch/arm/dts/keystone-k2g-evm.dts
index 7c5deef..b5b511c 100644
--- a/arch/arm/dts/keystone-k2g-evm.dts
+++ b/arch/arm/dts/keystone-k2g-evm.dts
@@ -38,7 +38,6 @@
&usb0_phy {
status = "okay";
- compatible = "nop-phy";
};
&usb0 {
@@ -51,7 +50,6 @@
};
&usb1_phy {
- compatible = "nop-phy";
status = "okay";
};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index cd096bf..a4227a3 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 a5a7ebd..e843c14 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 @@
#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 a29d115..8e9012d 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -973,6 +973,7 @@
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 d060001..9107b11 100644
--- a/arch/arm/mach-sunxi/dram_sunxi_dw.c
+++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c
@@ -399,18 +399,24 @@
#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 (socid == SOCID_R40) {
- if (para->dual_rank)
- panic("Dual rank memory not supported\n");
+ 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) {
/* 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 @@
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 @@
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 @@
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 @@
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, ¶);
+ 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 (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
- (para.dual_rank ? 2 : 1);
+ return size;
}
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index dde4efb..48240aa 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 e6655c7..a8eab40 100644
--- a/configs/omap35_logic_somlv_defconfig
+++ b/configs/omap35_logic_somlv_defconfig
@@ -4,6 +4,7 @@
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 c9318d4..6038dcb 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -198,6 +198,7 @@
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 b68f938..689b3a9 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -142,6 +142,7 @@
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/verdin-imx8mm_defconfig b/configs/verdin-imx8mm_defconfig
index ea0b597..c8c3420 100644
--- a/configs/verdin-imx8mm_defconfig
+++ b/configs/verdin-imx8mm_defconfig
@@ -37,7 +37,6 @@
CONFIG_SPL_SEPARATE_BSS=y
CONFIG_SPL_I2C_SUPPORT=y
CONFIG_SPL_POWER_SUPPORT=y
-CONFIG_SPL_USB_HOST_SUPPORT=y
CONFIG_SPL_WATCHDOG_SUPPORT=y
CONFIG_SYS_PROMPT="Verdin iMX8MM # "
# CONFIG_BOOTM_NETBSD is not set
@@ -50,6 +49,7 @@
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_UUID=y
CONFIG_CMD_REGULATOR=y
@@ -89,6 +89,8 @@
CONFIG_PINCTRL=y
CONFIG_SPL_PINCTRL=y
CONFIG_PINCTRL_IMX8M=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_IMX8M_POWER_DOMAIN=y
CONFIG_DM_PMIC=y
CONFIG_SPL_DM_PMIC_PCA9450=y
CONFIG_DM_PMIC_PFUZE100=y
@@ -101,5 +103,9 @@
CONFIG_SYSRESET_PSCI=y
CONFIG_SYSRESET_WATCHDOG=y
CONFIG_DM_THERMAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+# CONFIG_SPL_DM_USB is not set
+CONFIG_USB_EHCI_HCD=y
CONFIG_IMX_WATCHDOG=y
CONFIG_OF_LIBFDT_OVERLAY=y
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 0dfc059..4f9282a 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 ac8656f..df93d96 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -43,6 +43,7 @@
[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 @@
[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 0000000..0c280d2
--- /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/phy/nop-phy.c b/drivers/phy/nop-phy.c
index 84aac80..9f12ebc 100644
--- a/drivers/phy/nop-phy.c
+++ b/drivers/phy/nop-phy.c
@@ -43,6 +43,7 @@
static const struct udevice_id nop_phy_ids[] = {
{ .compatible = "nop-phy" },
+ { .compatible = "usb-nop-xceiv" },
{ }
};
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 20c3c82..48bdd0f 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 @@
* @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 @@
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 @@
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 @@
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 @@
}
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 @@
.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/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c
index c4cd07f..5d34bc1 100644
--- a/drivers/power/domain/imx8m-power-domain.c
+++ b/drivers/power/domain/imx8m-power-domain.c
@@ -120,6 +120,8 @@
static const struct udevice_id imx8m_power_domain_ids[] = {
{ .compatible = "fsl,imx8mq-gpc" },
+ { .compatible = "fsl,imx8mm-gpc" },
+ { .compatible = "fsl,imx8mn-gpc" },
{ }
};
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0971a7c..bf5d82f 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -156,7 +156,9 @@
config USB_EHCI_MX7
bool "Support for i.MX7 on-chip EHCI USB controller"
- depends on ARCH_MX7
+ depends on ARCH_MX7 || IMX8M
+ select PHY if IMX8M
+ select NOP_PHY if IMX8M
default y
---help---
Enables support for the on-chip EHCI controller on i.MX7 SoCs.
diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c
index aeea539..7642a31 100644
--- a/drivers/usb/host/ehci-mx6.c
+++ b/drivers/usb/host/ehci-mx6.c
@@ -5,6 +5,7 @@
*/
#include <common.h>
+#include <clk.h>
#include <log.h>
#include <usb.h>
#include <errno.h>
@@ -67,49 +68,41 @@
#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
#define UCMD_RESET (1 << 1) /* controller reset */
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
-static const unsigned phy_bases[] = {
- USB_PHY0_BASE_ADDR,
-#if defined(USB_PHY1_BASE_ADDR)
- USB_PHY1_BASE_ADDR,
+/* If this is not defined, assume MX6/MX7/MX8M SoC default */
+#ifndef CONFIG_MXC_USB_PORTSC
+#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW)
#endif
-};
-static void usb_internal_phy_clock_gate(int index, int on)
-{
- void __iomem *phy_reg;
-
- if (index >= ARRAY_SIZE(phy_bases))
- return;
-
- phy_reg = (void __iomem *)phy_bases[index];
- phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
- writel(USBPHY_CTRL_CLKGATE, phy_reg);
-}
+/* Base address for this IP block is 0x02184800 */
+struct usbnc_regs {
+ u32 ctrl[4]; /* otg/host1-3 */
+ u32 uh2_hsic_ctrl;
+ u32 uh3_hsic_ctrl;
+ u32 otg_phy_ctrl_0;
+ u32 uh1_phy_ctrl_0;
+ u32 reserve1[4];
+ u32 phy_cfg1;
+ u32 phy_cfg2;
+ u32 reserve2;
+ u32 phy_status;
+ u32 reserve3[4];
+ u32 adp_cfg1;
+ u32 adp_cfg2;
+ u32 adp_status;
+};
-static void usb_power_config(int index)
+#if defined(CONFIG_MX6) && !defined(CONFIG_PHY)
+static void usb_power_config_mx6(struct anatop_regs __iomem *anatop,
+ int anatop_bits_index)
{
-#if defined(CONFIG_MX7ULP)
- struct usbphy_regs __iomem *usbphy =
- (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
-
- if (index > 0)
- return;
-
- writel(ANADIG_USB2_CHRG_DETECT_EN_B |
- ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
- &usbphy->usb1_chrg_detect);
-
- scg_enable_usb_pll(true);
-
-#else
- struct anatop_regs __iomem *anatop =
- (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
void __iomem *chrg_detect;
void __iomem *pll_480_ctrl_clr;
void __iomem *pll_480_ctrl_set;
- switch (index) {
+ if (!is_mx6())
+ return;
+
+ switch (anatop_bits_index) {
case 0:
chrg_detect = &anatop->usb1_chrg_detect;
pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr;
@@ -142,22 +135,70 @@
ANADIG_USB2_PLL_480_CTRL_POWER |
ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
pll_480_ctrl_set);
+}
+#else
+static void __maybe_unused
+usb_power_config_mx6(void *anatop, int anatop_bits_index) { }
+#endif
+
+#if defined(CONFIG_MX7) && !defined(CONFIG_PHY)
+static void usb_power_config_mx7(struct usbnc_regs *usbnc)
+{
+ void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
+
+ if (!is_mx7())
+ return;
+
+ /*
+ * Clear the ACAENB to enable usb_otg_id detection,
+ * otherwise it is the ACA detection enabled.
+ */
+ clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
+}
+#else
+static void __maybe_unused
+usb_power_config_mx7(void *usbnc) { }
+#endif
+
+#if defined(CONFIG_MX7ULP) && !defined(CONFIG_PHY)
+static void usb_power_config_mx7ulp(struct usbphy_regs __iomem *usbphy)
+{
+ if (!is_mx7ulp())
+ return;
+
+ writel(ANADIG_USB2_CHRG_DETECT_EN_B |
+ ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
+ &usbphy->usb1_chrg_detect);
+ scg_enable_usb_pll(true);
+}
+#else
+static void __maybe_unused
+usb_power_config_mx7ulp(void *usbphy) { }
#endif
+
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+static const unsigned phy_bases[] = {
+ USB_PHY0_BASE_ADDR,
+#if defined(USB_PHY1_BASE_ADDR)
+ USB_PHY1_BASE_ADDR,
+#endif
+};
+
+#if !defined(CONFIG_PHY)
+static void usb_internal_phy_clock_gate(void __iomem *phy_reg, int on)
+{
+ phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
+ writel(USBPHY_CTRL_CLKGATE, phy_reg);
}
/* Return 0 : host node, <>0 : device mode */
-static int usb_phy_enable(int index, struct usb_ehci *ehci)
+static int usb_phy_enable(struct usb_ehci *ehci, void __iomem *phy_reg)
{
- void __iomem *phy_reg;
void __iomem *phy_ctrl;
void __iomem *usb_cmd;
int ret;
- if (index >= ARRAY_SIZE(phy_bases))
- return 0;
-
- phy_reg = (void __iomem *)phy_bases[index];
phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
usb_cmd = (void __iomem *)&ehci->usbcmd;
@@ -188,6 +229,7 @@
return 0;
}
+#endif
int usb_phy_mode(int port)
{
@@ -206,52 +248,7 @@
return USB_INIT_HOST;
}
-#if defined(CONFIG_MX7ULP)
-struct usbnc_regs {
- u32 ctrl1;
- u32 ctrl2;
- u32 reserve0[2];
- u32 hsic_ctrl;
-};
-#else
-/* Base address for this IP block is 0x02184800 */
-struct usbnc_regs {
- u32 ctrl[4]; /* otg/host1-3 */
- u32 uh2_hsic_ctrl;
- u32 uh3_hsic_ctrl;
- u32 otg_phy_ctrl_0;
- u32 uh1_phy_ctrl_0;
-};
-#endif
-
#elif defined(CONFIG_MX7)
-struct usbnc_regs {
- u32 ctrl1;
- u32 ctrl2;
- u32 reserve1[10];
- u32 phy_cfg1;
- u32 phy_cfg2;
- u32 reserve2;
- u32 phy_status;
- u32 reserve3[4];
- u32 adp_cfg1;
- u32 adp_cfg2;
- u32 adp_status;
-};
-
-static void usb_power_config(int index)
-{
- struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
- (0x10000 * index) + USBNC_OFFSET);
- void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
-
- /*
- * Clear the ACAENB to enable usb_otg_id detection,
- * otherwise it is the ACA detection enabled.
- */
- clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
-}
-
int usb_phy_mode(int port)
{
struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
@@ -268,17 +265,9 @@
}
#endif
-static void usb_oc_config(int index)
+static void usb_oc_config(struct usbnc_regs *usbnc, int index)
{
-#if defined(CONFIG_MX6)
- struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
- USB_OTHERREGS_OFFSET);
void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
-#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP)
- struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
- (0x10000 * index) + USBNC_OFFSET);
- void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1);
-#endif
#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
/* mx6qarm2 seems to required a different setting*/
@@ -297,6 +286,7 @@
#endif
}
+#if !CONFIG_IS_ENABLED(DM_USB)
/**
* board_usb_phy_mode - override usb phy mode
* @port: usb host/otg port
@@ -340,41 +330,29 @@
*/
int __weak board_ehci_power(int port, int on)
{
- return 0;
-}
-
-int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
-{
- int ret;
-
- enable_usboh3_clk(1);
- mdelay(1);
-
- /* Do board specific initialization */
- ret = board_ehci_hcd_init(index);
- if (ret)
- return ret;
-
- usb_power_config(index);
- usb_oc_config(index);
-
-#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
- usb_internal_phy_clock_gate(index, 1);
- usb_phy_enable(index, ehci);
-#endif
-
return 0;
}
-#if !CONFIG_IS_ENABLED(DM_USB)
int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
enum usb_init_type type;
#if defined(CONFIG_MX6)
u32 controller_spacing = 0x200;
-#elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP)
+ struct anatop_regs __iomem *anatop =
+ (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ USB_OTHERREGS_OFFSET);
+#elif defined(CONFIG_MX7)
u32 controller_spacing = 0x10000;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ (0x10000 * index) + USBNC_OFFSET);
+#elif defined(CONFIG_MX7ULP)
+ u32 controller_spacing = 0x10000;
+ struct usbphy_regs __iomem *usbphy =
+ (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
+ struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
+ (0x10000 * index) + USBNC_OFFSET);
#endif
struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR +
(controller_spacing * index));
@@ -391,15 +369,38 @@
}
}
- ret = ehci_mx6_common_init(ehci, index);
- if (ret)
+ enable_usboh3_clk(1);
+ mdelay(1);
+
+ /* Do board specific initialization */
+ ret = board_ehci_hcd_init(index);
+ if (ret) {
+ enable_usboh3_clk(0);
return ret;
+ }
+
+#if defined(CONFIG_MX6)
+ usb_power_config_mx6(anatop, index);
+#elif defined (CONFIG_MX7)
+ usb_power_config_mx7(usbnc);
+#elif defined (CONFIG_MX7ULP)
+ usb_power_config_mx7ulp(usbphy);
+#endif
+
+ usb_oc_config(usbnc, index);
+
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
+ if (index < ARRAY_SIZE(phy_bases)) {
+ usb_internal_phy_clock_gate((void __iomem *)phy_bases[index], 1);
+ usb_phy_enable(ehci, (void __iomem *)phy_bases[index]);
+ }
+#endif
type = board_usb_phy_mode(index);
if (hccr && hcor) {
- *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
+ *hccr = (struct ehci_hccr *)((uintptr_t)&ehci->caplength);
+ *hcor = (struct ehci_hcor *)((uintptr_t)*hccr +
HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
}
@@ -428,8 +429,13 @@
struct ehci_ctrl ctrl;
struct usb_ehci *ehci;
struct udevice *vbus_supply;
+ struct clk clk;
+ struct phy phy;
enum usb_init_type init_type;
int portnr;
+ void __iomem *phy_addr;
+ void __iomem *misc_addr;
+ void __iomem *anatop_addr;
};
static int mx6_init_after_reset(struct ehci_ctrl *dev)
@@ -437,14 +443,23 @@
struct ehci_mx6_priv_data *priv = dev->priv;
enum usb_init_type type = priv->init_type;
struct usb_ehci *ehci = priv->ehci;
- int ret;
- ret = ehci_mx6_common_init(priv->ehci, priv->portnr);
- if (ret)
- return ret;
+#if !defined(CONFIG_PHY)
+ usb_power_config_mx6(priv->anatop_addr, priv->portnr);
+ usb_power_config_mx7(priv->misc_addr);
+ usb_power_config_mx7ulp(priv->phy_addr);
+#endif
+
+ usb_oc_config(priv->misc_addr, priv->portnr);
+
+#if !defined(CONFIG_PHY) && (defined(CONFIG_MX6) || defined(CONFIG_MX7ULP))
+ usb_internal_phy_clock_gate(priv->phy_addr, 1);
+ usb_phy_enable(ehci, priv->phy_addr);
+#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
if (priv->vbus_supply) {
+ int ret;
ret = regulator_set_enable(priv->vbus_supply,
(type == USB_INIT_DEVICE) ?
false : true);
@@ -541,46 +556,58 @@
return 0;
}
-static int ehci_usb_bind(struct udevice *dev)
+static int mx6_parse_dt_addrs(struct udevice *dev)
{
- /*
- * TODO:
- * This driver is only partly converted to DT probing and still uses
- * a tremendous amount of hard-coded addresses. To make things worse,
- * the driver depends on specific sequential indexing of controllers,
- * from which it derives offsets in the PHY and ANATOP register sets.
- *
- * Here we attempt to calculate these indexes from DT information as
- * well as we can. The USB controllers on all existing iMX6 SoCs
- * are placed next to each other, at addresses incremented by 0x200,
- * and iMX7 their addresses are shifted by 0x10000.
- * Thus, the index is derived from the multiple of 0x200 (0x10000 for
- * iMX7) offset from the first controller address.
- *
- * However, to complete conversion of this driver to DT probing, the
- * following has to be done:
- * - DM clock framework support for iMX must be implemented
- * - usb_power_config() has to be converted to clock framework
- * -> Thus, the ad-hoc "index" variable goes away.
- * - USB PHY handling has to be factored out into separate driver
- * -> Thus, the ad-hoc "index" variable goes away from the PHY
- * code, the PHY driver must parse it's address from DT. This
- * USB driver must find the PHY driver via DT phandle.
- * -> usb_power_config() shall be moved to PHY driver
- * With these changes in place, the ad-hoc indexing goes away and
- * the driver is fully converted to DT probing.
- */
+ struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
+ int phy_off, misc_off;
+ const void *blob = gd->fdt_blob;
+ int offset = dev_of_offset(dev);
+ void *__iomem addr;
+ int ret, devnump;
- /*
- * FIXME: This cannot work with the new sequence numbers.
- * Please complete the DM conversion.
- *
- * u32 controller_spacing = is_mx7() ? 0x10000 : 0x200;
- * fdt_addr_t addr = devfdt_get_addr_index(dev, 0);
- *
- * dev->req_seq = (addr - USB_BASE_ADDR) / controller_spacing;
- */
+ phy_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbphy");
+ if (phy_off < 0) {
+ phy_off = fdtdec_lookup_phandle(blob, offset, "phys");
+ if (phy_off < 0)
+ return -EINVAL;
+ }
+ ret = fdtdec_get_alias_seq(blob, dev->uclass->uc_drv->name,
+ phy_off, &devnump);
+ if (ret < 0)
+ return ret;
+
+ misc_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbmisc");
+ if (misc_off < 0)
+ return -EINVAL;
+
+ addr = (void __iomem *)fdtdec_get_addr(blob, phy_off, "reg");
+ if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->phy_addr = addr;
+ priv->portnr = devnump;
+
+ addr = (void __iomem *)fdtdec_get_addr(blob, misc_off, "reg");
+ if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->misc_addr = addr;
+
+#if !defined(CONFIG_PHY) && defined(CONFIG_MX6)
+ int anatop_off;
+
+ /* Resolve ANATOP offset through USB PHY node */
+ anatop_off = fdtdec_lookup_phandle(blob, phy_off, "fsl,anatop");
+ if (anatop_off < 0)
+ return -EINVAL;
+
+ addr = (void __iomem *)fdtdec_get_addr(blob, anatop_off, "reg");
+ if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->anatop_addr = addr;
+#endif
return 0;
}
@@ -602,19 +629,46 @@
}
}
+ ret = mx6_parse_dt_addrs(dev);
+ if (ret)
+ return ret;
+
priv->ehci = ehci;
- priv->portnr = dev_seq(dev);
priv->init_type = type;
+#if CONFIG_IS_ENABLED(CLK)
+ ret = clk_get_by_index(dev, 0, &priv->clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(&priv->clk);
+ if (ret)
+ return ret;
+#else
+ /* Compatibility with DM_USB and !CLK */
+ enable_usboh3_clk(1);
+ mdelay(1);
+#endif
+
#if CONFIG_IS_ENABLED(DM_REGULATOR)
ret = device_get_supply_regulator(dev, "vbus-supply",
&priv->vbus_supply);
if (ret)
debug("%s: No vbus supply\n", dev->name);
#endif
- ret = ehci_mx6_common_init(ehci, priv->portnr);
- if (ret)
- return ret;
+
+#if !defined(CONFIG_PHY)
+ usb_power_config_mx6(priv->anatop_addr, priv->portnr);
+ usb_power_config_mx7(priv->misc_addr);
+ usb_power_config_mx7ulp(priv->phy_addr);
+#endif
+
+ usb_oc_config(priv->misc_addr, priv->portnr);
+
+#if !defined(CONFIG_PHY) && (defined(CONFIG_MX6) || defined(CONFIG_MX7ULP))
+ usb_internal_phy_clock_gate(priv->phy_addr, 1);
+ usb_phy_enable(ehci, priv->phy_addr);
+#endif
#if CONFIG_IS_ENABLED(DM_REGULATOR)
if (priv->vbus_supply) {
@@ -623,7 +677,7 @@
false : true);
if (ret && ret != -ENOSYS) {
printf("Error enabling VBUS supply (ret=%i)\n", ret);
- return ret;
+ goto err_clk;
}
}
#endif
@@ -636,15 +690,66 @@
mdelay(10);
- hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
- hcor = (struct ehci_hcor *)((uint32_t)hccr +
+#if defined(CONFIG_PHY)
+ ret = ehci_setup_phy(dev, &priv->phy, 0);
+ if (ret)
+ goto err_regulator;
+#endif
+
+ hccr = (struct ehci_hccr *)((uintptr_t)&ehci->caplength);
+ hcor = (struct ehci_hcor *)((uintptr_t)hccr +
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
+ ret = ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type);
+ if (ret)
+ goto err_phy;
+
+ return ret;
+
+err_phy:
+#if defined(CONFIG_PHY)
+ ehci_shutdown_phy(dev, &priv->phy);
+err_regulator:
+#endif
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->vbus_supply)
+ regulator_set_enable(priv->vbus_supply, false);
+err_clk:
+#endif
+#if CONFIG_IS_ENABLED(CLK)
+ clk_disable(&priv->clk);
+#else
+ /* Compatibility with DM_USB and !CLK */
+ enable_usboh3_clk(0);
+#endif
+ return ret;
+}
+
- return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type);
+int ehci_usb_remove(struct udevice *dev)
+{
+ struct ehci_mx6_priv_data *priv __maybe_unused = dev_get_priv(dev);
+
+ ehci_deregister(dev);
+
+#if defined(CONFIG_PHY)
+ ehci_shutdown_phy(dev, &priv->phy);
+#endif
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+ if (priv->vbus_supply)
+ regulator_set_enable(priv->vbus_supply, false);
+#endif
+
+#if CONFIG_IS_ENABLED(CLK)
+ clk_disable(&priv->clk);
+#endif
+
+ return 0;
}
static const struct udevice_id mx6_usb_ids[] = {
{ .compatible = "fsl,imx27-usb" },
+ { .compatible = "fsl,imx7d-usb" },
{ }
};
@@ -653,9 +758,8 @@
.id = UCLASS_USB,
.of_match = mx6_usb_ids,
.of_to_plat = ehci_usb_of_to_plat,
- .bind = ehci_usb_bind,
.probe = ehci_usb_probe,
- .remove = ehci_deregister,
+ .remove = ehci_usb_remove,
.ops = &ehci_usb_ops,
.plat_auto = sizeof(struct usb_plat),
.priv_auto = sizeof(struct ehci_mx6_priv_data),
diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
index 147e187..4321673 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 b473d7c..08e49c2 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -324,6 +324,20 @@
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 @@
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 2ee423b..49bbb05 100644
--- a/env/common.c
+++ b/env/common.c
@@ -145,7 +145,7 @@
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 @@
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 @@
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 caefa33..e534008 100644
--- a/env/env.c
+++ b/env/env.c
@@ -335,6 +335,9 @@
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 ec643f2..9f65afb 100644
--- a/env/ext4.c
+++ b/env/ext4.c
@@ -188,6 +188,5 @@
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 653a38f..9d37d26 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 @@
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 @@
return 1;
}
+#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
+ if (gd->env_valid == ENV_VALID)
+ file = CONFIG_ENV_FAT_FILE_REDUND;
+#endif
+
- err = file_fat_write(CONFIG_ENV_FAT_FILE, (void *)&env_new, 0, sizeof(env_t),
- &size);
+ 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 @@
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 @@
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 df4aed2..e3e833c 100644
--- a/env/flags.c
+++ b/env/flags.c
@@ -563,12 +563,13 @@
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 9b226be..09e94f0 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -233,7 +233,6 @@
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 @@
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 @@
.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
};
diff --git a/env/sf.c b/env/sf.c
index 88ec110..e4b7ca9 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -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 @@
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 @@
{
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 @@
}
/* 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 @@
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 @@
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 @@
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 @@
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 @@
goto out;
}
- ret = setup_flash_device();
+ ret = setup_flash_device(&env_flash);
if (ret)
goto out;
@@ -176,7 +188,6 @@
read2_fail, H_EXTERNAL);
spi_flash_free(env_flash);
- env_flash = NULL;
out:
free(tmp_env1);
free(tmp_env2);
@@ -186,18 +197,23 @@
#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 @@
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 @@
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 @@
puts("done\n");
done:
+ spi_flash_free(env_flash);
+
if (saved_buffer)
free(saved_buffer);
@@ -248,6 +266,7 @@
{
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 @@
return -EIO;
}
- ret = setup_flash_device();
+ ret = setup_flash_device(&env_flash);
if (ret)
goto out;
@@ -272,7 +291,6 @@
err_read:
spi_flash_free(env_flash);
- env_flash = NULL;
out:
free(buf);
@@ -280,6 +298,30 @@
}
#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 @@
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 @@
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 @@
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 @@
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 @@
.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 33a4d7b..9e37e99 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 @@
* 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 @@
"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 @@
#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/configs/verdin-imx8mm.h b/include/configs/verdin-imx8mm.h
index 4751bf5..e2a8178 100644
--- a/include/configs/verdin-imx8mm.h
+++ b/include/configs/verdin-imx8mm.h
@@ -117,5 +117,10 @@
#define FEC_QUIRK_ENET_MAC
#define IMX_FEC_BASE 0x30BE0000
+/* USB Configs */
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+#define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW)
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
+
#endif /*_VERDIN_IMX8MM_H */
diff --git a/include/dt-bindings/power/imx8mm-power.h b/include/dt-bindings/power/imx8mm-power.h
new file mode 100644
index 0000000..fc9c2e1
--- /dev/null
+++ b/include/dt-bindings/power/imx8mm-power.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (C) 2020 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ */
+
+#ifndef __DT_BINDINGS_IMX8MM_POWER_H__
+#define __DT_BINDINGS_IMX8MM_POWER_H__
+
+#define IMX8MM_POWER_DOMAIN_HSIOMIX 0
+#define IMX8MM_POWER_DOMAIN_PCIE 1
+#define IMX8MM_POWER_DOMAIN_OTG1 2
+#define IMX8MM_POWER_DOMAIN_OTG2 3
+#define IMX8MM_POWER_DOMAIN_GPUMIX 4
+#define IMX8MM_POWER_DOMAIN_GPU 5
+#define IMX8MM_POWER_DOMAIN_VPUMIX 6
+#define IMX8MM_POWER_DOMAIN_VPUG1 7
+#define IMX8MM_POWER_DOMAIN_VPUG2 8
+#define IMX8MM_POWER_DOMAIN_VPUH1 9
+#define IMX8MM_POWER_DOMAIN_DISPMIX 10
+#define IMX8MM_POWER_DOMAIN_MIPI 11
+
+#endif
diff --git a/include/dt-bindings/power/imx8mn-power.h b/include/dt-bindings/power/imx8mn-power.h
new file mode 100644
index 0000000..102ee85
--- /dev/null
+++ b/include/dt-bindings/power/imx8mn-power.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Copyright (C) 2020 Compass Electronics Group, LLC
+ */
+
+#ifndef __DT_BINDINGS_IMX8MN_POWER_H__
+#define __DT_BINDINGS_IMX8MN_POWER_H__
+
+#define IMX8MN_POWER_DOMAIN_HSIOMIX 0
+#define IMX8MN_POWER_DOMAIN_OTG1 1
+#define IMX8MN_POWER_DOMAIN_GPUMIX 2
+#define IMX8MN_POWER_DOMAIN_DISPMIX 3
+#define IMX8MN_POWER_DOMAIN_MIPI 4
+
+#endif
diff --git a/include/env.h b/include/env.h
index c15339a..b5731e4 100644
--- a/include/env.h
+++ b/include/env.h
@@ -328,8 +328,6 @@
* @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 708c833..b7bddcb 100644
--- a/include/env_internal.h
+++ b/include/env_internal.h
@@ -211,6 +211,7 @@
#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 047184d..265df4c 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 @@
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);