mirror of
https://github.com/smaeul/u-boot.git
synced 2025-10-14 04:46:01 +01:00
- Add emmc hs200 support - Few bug fixes related to serdes, I2C, ethernet, etc
This commit is contained in:
commit
a9fa70b7b7
@ -501,6 +501,10 @@ config SYS_FSL_I2C_CLK_DIV
|
|||||||
config SYS_FSL_IFC_CLK_DIV
|
config SYS_FSL_IFC_CLK_DIV
|
||||||
int "IFC clock divider"
|
int "IFC clock divider"
|
||||||
default 1 if ARCH_LS1043A
|
default 1 if ARCH_LS1043A
|
||||||
|
default 4 if ARCH_LS1012A
|
||||||
|
default 4 if ARCH_LS1028A
|
||||||
|
default 8 if ARCH_LX2160A
|
||||||
|
default 8 if ARCH_LS1088A
|
||||||
default 2
|
default 2
|
||||||
help
|
help
|
||||||
This is the divider that is used to derive IFC clock from Platform
|
This is the divider that is used to derive IFC clock from Platform
|
||||||
|
@ -1154,7 +1154,8 @@ int timer_init(void)
|
|||||||
#ifdef CONFIG_FSL_LSCH3
|
#ifdef CONFIG_FSL_LSCH3
|
||||||
u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
|
u32 __iomem *cltbenr = (u32 *)CONFIG_SYS_FSL_PMU_CLTBENR;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
|
#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) || \
|
||||||
|
defined(CONFIG_ARCH_LS1028A)
|
||||||
u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET;
|
u32 __iomem *pctbenr = (u32 *)FSL_PMU_PCTBENR_OFFSET;
|
||||||
u32 svr_dev_id;
|
u32 svr_dev_id;
|
||||||
#endif
|
#endif
|
||||||
@ -1173,7 +1174,8 @@ int timer_init(void)
|
|||||||
out_le32(cltbenr, 0xf);
|
out_le32(cltbenr, 0xf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A)
|
#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS1088A) || \
|
||||||
|
defined(CONFIG_ARCH_LS1028A)
|
||||||
/*
|
/*
|
||||||
* In certain Layerscape SoCs, the clock for each core's
|
* In certain Layerscape SoCs, the clock for each core's
|
||||||
* has an enable bit in the PMU Physical Core Time Base Enable
|
* has an enable bit in the PMU Physical Core Time Base Enable
|
||||||
|
@ -435,7 +435,7 @@ void ft_cpu_setup(void *blob, bd_t *bd)
|
|||||||
do_fixup_by_path_u32(blob, "/sysclk", "clock-frequency",
|
do_fixup_by_path_u32(blob, "/sysclk", "clock-frequency",
|
||||||
CONFIG_SYS_CLK_FREQ, 1);
|
CONFIG_SYS_CLK_FREQ, 1);
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_LAYERSCAPE
|
#if defined(CONFIG_PCIE_LAYERSCAPE) || defined(CONFIG_PCIE_LAYERSCAPE_GEN4)
|
||||||
ft_pci_setup(blob, bd);
|
ft_pci_setup(blob, bd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -22,10 +22,12 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||||||
void get_sys_info(struct sys_info *sys_info)
|
void get_sys_info(struct sys_info *sys_info)
|
||||||
{
|
{
|
||||||
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
|
||||||
#if (defined(CONFIG_FSL_ESDHC) &&\
|
/* rcw_tmp is needed to get FMAN clock, or to get cluster group A
|
||||||
defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\
|
* mux 2 clock for LS1043A/LS1046A.
|
||||||
defined(CONFIG_SYS_DPAA_FMAN)
|
*/
|
||||||
|
#if defined(CONFIG_SYS_DPAA_FMAN) || \
|
||||||
|
defined(CONFIG_TARGET_LS1046ARDB) || \
|
||||||
|
defined(CONFIG_TARGET_LS1043ARDB)
|
||||||
u32 rcw_tmp;
|
u32 rcw_tmp;
|
||||||
#endif
|
#endif
|
||||||
struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
|
struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
|
||||||
@ -122,32 +124,32 @@ void get_sys_info(struct sys_info *sys_info)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_FSL_ESDHC
|
||||||
#define HWA_CGA_M2_CLK_SEL 0x00000007
|
#define HWA_CGA_M2_CLK_SEL 0x00000007
|
||||||
#define HWA_CGA_M2_CLK_SHIFT 0
|
#define HWA_CGA_M2_CLK_SHIFT 0
|
||||||
#ifdef CONFIG_FSL_ESDHC
|
#if defined(CONFIG_TARGET_LS1046ARDB) || defined(CONFIG_TARGET_LS1043ARDB)
|
||||||
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
|
|
||||||
rcw_tmp = in_be32(&gur->rcwsr[15]);
|
rcw_tmp = in_be32(&gur->rcwsr[15]);
|
||||||
switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
|
switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
|
||||||
case 1:
|
case 1:
|
||||||
sys_info->freq_sdhc = freq_c_pll[1];
|
sys_info->freq_cga_m2 = freq_c_pll[1];
|
||||||
break;
|
break;
|
||||||
|
#if defined(CONFIG_TARGET_LS1046ARDB)
|
||||||
case 2:
|
case 2:
|
||||||
sys_info->freq_sdhc = freq_c_pll[1] / 2;
|
sys_info->freq_cga_m2 = freq_c_pll[1] / 2;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 3:
|
case 3:
|
||||||
sys_info->freq_sdhc = freq_c_pll[1] / 3;
|
sys_info->freq_cga_m2 = freq_c_pll[1] / 3;
|
||||||
break;
|
break;
|
||||||
|
#if defined(CONFIG_TARGET_LS1046ARDB)
|
||||||
case 6:
|
case 6:
|
||||||
sys_info->freq_sdhc = freq_c_pll[0] / 2;
|
sys_info->freq_cga_m2 = freq_c_pll[0] / 2;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
printf("Error: Unknown ESDHC clock select!\n");
|
printf("Error: Unknown peripheral clock select!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
sys_info->freq_sdhc = (sys_info->freq_systembus /
|
|
||||||
CONFIG_SYS_FSL_PCLK_DIV) /
|
|
||||||
CONFIG_SYS_FSL_SDHC_CLK_DIV;
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -183,9 +185,22 @@ int get_clocks(void)
|
|||||||
gd->mem_clk = sys_info.freq_ddrbus;
|
gd->mem_clk = sys_info.freq_ddrbus;
|
||||||
|
|
||||||
#ifdef CONFIG_FSL_ESDHC
|
#ifdef CONFIG_FSL_ESDHC
|
||||||
gd->arch.sdhc_clk = sys_info.freq_sdhc;
|
#if defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)
|
||||||
|
#if defined(CONFIG_TARGET_LS1046ARDB)
|
||||||
|
gd->arch.sdhc_clk = sys_info.freq_cga_m2 / 2;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_TARGET_LS1043ARDB)
|
||||||
|
gd->arch.sdhc_clk = sys_info.freq_cga_m2;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_TARGET_LS1012ARDB)
|
||||||
|
gd->arch.sdhc_clk = sys_info.freq_systembus;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
gd->arch.sdhc_clk = (sys_info.freq_systembus /
|
||||||
|
CONFIG_SYS_FSL_PCLK_DIV) /
|
||||||
|
CONFIG_SYS_FSL_SDHC_CLK_DIV;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (gd->cpu_clk != 0)
|
if (gd->cpu_clk != 0)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
|
@ -64,6 +64,9 @@ void get_sys_info(struct sys_info *sys_info)
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint i, cluster;
|
uint i, cluster;
|
||||||
|
#if defined(CONFIG_TARGET_LS1028ARDB) || defined(CONFIG_TARGET_LS1088ARDB)
|
||||||
|
uint rcw_tmp;
|
||||||
|
#endif
|
||||||
uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
uint freq_c_pll[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
||||||
uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
uint ratio[CONFIG_SYS_FSL_NUM_CC_PLLS];
|
||||||
unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
|
unsigned long sysclk = CONFIG_SYS_CLK_FREQ;
|
||||||
@ -127,8 +130,39 @@ void get_sys_info(struct sys_info *sys_info)
|
|||||||
sys_info->freq_localbus = sys_info->freq_systembus /
|
sys_info->freq_localbus = sys_info->freq_systembus /
|
||||||
CONFIG_SYS_FSL_IFC_CLK_DIV;
|
CONFIG_SYS_FSL_IFC_CLK_DIV;
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
|
#if defined(CONFIG_TARGET_LS1028ARDB) || defined(CONFIG_TARGET_LS1088ARDB)
|
||||||
|
#define HWA_CGA_M2_CLK_SEL 0x00380000
|
||||||
|
#define HWA_CGA_M2_CLK_SHIFT 19
|
||||||
|
rcw_tmp = in_le32(&gur->rcwsr[5]);
|
||||||
|
switch ((rcw_tmp & HWA_CGA_M2_CLK_SEL) >> HWA_CGA_M2_CLK_SHIFT) {
|
||||||
|
case 1:
|
||||||
|
sys_info->freq_cga_m2 = freq_c_pll[1];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sys_info->freq_cga_m2 = freq_c_pll[1] / 2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
sys_info->freq_cga_m2 = freq_c_pll[1] / 3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
sys_info->freq_cga_m2 = freq_c_pll[1] / 4;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
sys_info->freq_cga_m2 = freq_c_pll[0] / 2;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
sys_info->freq_cga_m2 = freq_c_pll[0] / 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Error: Unknown peripheral clock select!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_TARGET_LX2160ARDB) || defined(CONFIG_TARGET_LS2080ARDB)
|
||||||
|
sys_info->freq_cga_m2 = sys_info->freq_systembus;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int get_clocks(void)
|
int get_clocks(void)
|
||||||
{
|
{
|
||||||
@ -141,7 +175,16 @@ int get_clocks(void)
|
|||||||
gd->arch.mem2_clk = sys_info.freq_ddrbus2;
|
gd->arch.mem2_clk = sys_info.freq_ddrbus2;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_FSL_ESDHC)
|
#if defined(CONFIG_FSL_ESDHC)
|
||||||
|
#if defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)
|
||||||
|
#if defined(CONFIG_TARGET_LS1028ARDB) || defined(CONFIG_TARGET_LX2160ARDB)
|
||||||
|
gd->arch.sdhc_clk = sys_info.freq_cga_m2 / 2;
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_TARGET_LS2080ARDB) || defined(CONFIG_TARGET_LS1088ARDB)
|
||||||
|
gd->arch.sdhc_clk = sys_info.freq_cga_m2;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
|
gd->arch.sdhc_clk = gd->bus_clk / CONFIG_SYS_FSL_SDHC_CLK_DIV;
|
||||||
|
#endif
|
||||||
#endif /* defined(CONFIG_FSL_ESDHC) */
|
#endif /* defined(CONFIG_FSL_ESDHC) */
|
||||||
|
|
||||||
if (gd->cpu_clk != 0)
|
if (gd->cpu_clk != 0)
|
||||||
|
@ -24,7 +24,7 @@ static struct serdes_config serdes1_cfg_tbl[] = {
|
|||||||
{0xDDDD, {PCIE1, PCIE1, PCIE1, PCIE1} },
|
{0xDDDD, {PCIE1, PCIE1, PCIE1, PCIE1} },
|
||||||
{0xE031, {SXGMII1, QXGMII2, NONE, SATA1} },
|
{0xE031, {SXGMII1, QXGMII2, NONE, SATA1} },
|
||||||
{0xB991, {SXGMII1, SGMII1, SGMII2, PCIE1} },
|
{0xB991, {SXGMII1, SGMII1, SGMII2, PCIE1} },
|
||||||
{0xBB31, {SXGMII1, QXGMII2, PCIE1, PCIE1} },
|
{0xBB31, {SXGMII1, QXGMII2, PCIE2, PCIE1} },
|
||||||
{0xCC31, {SXGMII1, QXGMII2, PCIE2, PCIE2} },
|
{0xCC31, {SXGMII1, QXGMII2, PCIE2, PCIE2} },
|
||||||
{0xBB51, {SXGMII1, QSGMII_B, PCIE2, PCIE1} },
|
{0xBB51, {SXGMII1, QSGMII_B, PCIE2, PCIE1} },
|
||||||
{0xBB38, {SGMII_T1, QXGMII2, PCIE2, PCIE1} },
|
{0xBB38, {SGMII_T1, QXGMII2, PCIE2, PCIE1} },
|
||||||
|
@ -14,6 +14,10 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&esdhc1 {
|
||||||
|
mmc-hs200-1_8v;
|
||||||
|
};
|
||||||
|
|
||||||
&qspi {
|
&qspi {
|
||||||
bus-num = <0>;
|
bus-num = <0>;
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
@ -33,12 +33,65 @@
|
|||||||
|
|
||||||
&esdhc1 {
|
&esdhc1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
&i2c0 {
|
&i2c0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
|
|
||||||
|
fpga@66 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "simple-mfd";
|
||||||
|
reg = <0x66>;
|
||||||
|
|
||||||
|
mux-mdio@54 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "mdio-mux-i2creg";
|
||||||
|
reg = <0x54>;
|
||||||
|
#mux-control-cells = <1>;
|
||||||
|
mux-reg-masks = <0x54 0xf0>;
|
||||||
|
mdio-parent-bus = <&mdio0>;
|
||||||
|
|
||||||
|
/* on-board MDIO with a single RGMII PHY */
|
||||||
|
mdio@00 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0x00>;
|
||||||
|
|
||||||
|
qds_phy0: phy@5 {
|
||||||
|
reg = <5>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/* slot 1 */
|
||||||
|
slot1: mdio@40 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0x40>;
|
||||||
|
};
|
||||||
|
/* slot 2 */
|
||||||
|
slot2: mdio@50 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0x50>;
|
||||||
|
};
|
||||||
|
/* slot 3 */
|
||||||
|
slot3: mdio@60 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0x60>;
|
||||||
|
};
|
||||||
|
/* slot 4 */
|
||||||
|
slot4: mdio@70 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0x70>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
i2c-mux@77 {
|
i2c-mux@77 {
|
||||||
compatible = "nxp,pca9547";
|
compatible = "nxp,pca9547";
|
||||||
reg = <0x77>;
|
reg = <0x77>;
|
||||||
@ -108,7 +161,4 @@
|
|||||||
|
|
||||||
&mdio0 {
|
&mdio0 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
qds_phy0: phy@5 {
|
|
||||||
reg = <5>;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
&esdhc1 {
|
&esdhc1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
mmc-hs200-1_8v;
|
||||||
};
|
};
|
||||||
|
|
||||||
&i2c0 {
|
&i2c0 {
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
&esdhc1 {
|
&esdhc1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
|
mmc-hs200-1_8v;
|
||||||
};
|
};
|
||||||
|
|
||||||
&i2c0 {
|
&i2c0 {
|
||||||
|
@ -180,7 +180,7 @@ struct sys_info {
|
|||||||
unsigned long freq_systembus;
|
unsigned long freq_systembus;
|
||||||
unsigned long freq_ddrbus;
|
unsigned long freq_ddrbus;
|
||||||
unsigned long freq_localbus;
|
unsigned long freq_localbus;
|
||||||
unsigned long freq_sdhc;
|
unsigned long freq_cga_m2;
|
||||||
#ifdef CONFIG_SYS_DPAA_FMAN
|
#ifdef CONFIG_SYS_DPAA_FMAN
|
||||||
unsigned long freq_fman[CONFIG_SYS_NUM_FMAN];
|
unsigned long freq_fman[CONFIG_SYS_NUM_FMAN];
|
||||||
#endif
|
#endif
|
||||||
|
@ -278,6 +278,7 @@ struct sys_info {
|
|||||||
/* frequency of platform PLL */
|
/* frequency of platform PLL */
|
||||||
unsigned long freq_systembus;
|
unsigned long freq_systembus;
|
||||||
unsigned long freq_ddrbus;
|
unsigned long freq_ddrbus;
|
||||||
|
unsigned long freq_cga_m2;
|
||||||
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
#ifdef CONFIG_SYS_FSL_HAS_DP_DDR
|
||||||
unsigned long freq_ddrbus2;
|
unsigned long freq_ddrbus2;
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,6 +105,8 @@ static const struct serdes_phy_config serdes1_phy_config[] = {
|
|||||||
EMI1, IO_SLOT_1},
|
EMI1, IO_SLOT_1},
|
||||||
{WRIOP1_DPMAC2, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
{WRIOP1_DPMAC2, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
||||||
EMI1, IO_SLOT_2} } },
|
EMI1, IO_SLOT_2} } },
|
||||||
|
{14, {{WRIOP1_DPMAC1, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
||||||
|
EMI1, IO_SLOT_1} } },
|
||||||
{15, {{WRIOP1_DPMAC1, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
{15, {{WRIOP1_DPMAC1, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
||||||
EMI1, IO_SLOT_1},
|
EMI1, IO_SLOT_1},
|
||||||
{WRIOP1_DPMAC2, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
{WRIOP1_DPMAC2, {INPHI_PHY_ADDR1, INPHI_PHY_ADDR2, -1},
|
||||||
@ -686,7 +688,7 @@ int fdt_create_phy_node(void *fdt, int offset, u8 phyaddr, int *subnodeoffset,
|
|||||||
struct phy_device *phy_dev, int phandle)
|
struct phy_device *phy_dev, int phandle)
|
||||||
{
|
{
|
||||||
char phy_node_name[] = "ethernet-phy@00";
|
char phy_node_name[] = "ethernet-phy@00";
|
||||||
char phy_id_compatible_str[] = "ethernet-phy-id0000.0000";
|
char phy_id_compatible_str[] = "ethernet-phy-id0000.0000,";
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sprintf(phy_node_name, "ethernet-phy@%x", phyaddr);
|
sprintf(phy_node_name, "ethernet-phy@%x", phyaddr);
|
||||||
@ -700,7 +702,7 @@ int fdt_create_phy_node(void *fdt, int offset, u8 phyaddr, int *subnodeoffset,
|
|||||||
return *subnodeoffset;
|
return *subnodeoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(phy_id_compatible_str, "ethernet-phy-id%04x.%04x",
|
sprintf(phy_id_compatible_str, "ethernet-phy-id%04x.%04x,",
|
||||||
phy_dev->phy_id >> 16, phy_dev->phy_id & 0xFFFF);
|
phy_dev->phy_id >> 16, phy_dev->phy_id & 0xFFFF);
|
||||||
debug("phy_id_compatible_str %s\n", phy_id_compatible_str);
|
debug("phy_id_compatible_str %s\n", phy_id_compatible_str);
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include <efi_loader.h>
|
#include <efi_loader.h>
|
||||||
#include <asm/arch/mmu.h>
|
#include <asm/arch/mmu.h>
|
||||||
#include <hwconfig.h>
|
#include <hwconfig.h>
|
||||||
|
#include <asm/arch/clock.h>
|
||||||
|
#include <asm/arch/config.h>
|
||||||
#include <asm/arch/fsl_serdes.h>
|
#include <asm/arch/fsl_serdes.h>
|
||||||
#include <asm/arch/soc.h>
|
#include <asm/arch/soc.h>
|
||||||
#include "../common/qixis.h"
|
#include "../common/qixis.h"
|
||||||
@ -116,6 +118,72 @@ int board_early_init_f(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF_BOARD_FIXUP
|
||||||
|
int board_fix_fdt(void *fdt)
|
||||||
|
{
|
||||||
|
char *reg_names, *reg_name;
|
||||||
|
int names_len, old_name_len, new_name_len, remaining_names_len;
|
||||||
|
struct str_map {
|
||||||
|
char *old_str;
|
||||||
|
char *new_str;
|
||||||
|
} reg_names_map[] = {
|
||||||
|
{ "ccsr", "dip" },
|
||||||
|
{ "pf_ctrl", "ctrl" }
|
||||||
|
};
|
||||||
|
int off = -1, i;
|
||||||
|
|
||||||
|
if (IS_SVR_REV(get_svr(), 1, 0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
off = fdt_node_offset_by_compatible(fdt, -1, "fsl,lx2160a-pcie");
|
||||||
|
while (off != -FDT_ERR_NOTFOUND) {
|
||||||
|
fdt_setprop(fdt, off, "compatible", "fsl,ls-pcie",
|
||||||
|
strlen("fsl,ls-pcie") + 1);
|
||||||
|
|
||||||
|
reg_names = (char *)fdt_getprop(fdt, off, "reg-names",
|
||||||
|
&names_len);
|
||||||
|
if (!reg_names)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
reg_name = reg_names;
|
||||||
|
remaining_names_len = names_len - (reg_name - reg_names);
|
||||||
|
for (i = 0; (i < ARRAY_SIZE(reg_names_map)) && names_len; i++) {
|
||||||
|
old_name_len = strlen(reg_names_map[i].old_str);
|
||||||
|
new_name_len = strlen(reg_names_map[i].new_str);
|
||||||
|
if (memcmp(reg_name, reg_names_map[i].old_str,
|
||||||
|
old_name_len) == 0) {
|
||||||
|
/* first only leave required bytes for new_str
|
||||||
|
* and copy rest of the string after it
|
||||||
|
*/
|
||||||
|
memcpy(reg_name + new_name_len,
|
||||||
|
reg_name + old_name_len,
|
||||||
|
remaining_names_len - old_name_len);
|
||||||
|
/* Now copy new_str */
|
||||||
|
memcpy(reg_name, reg_names_map[i].new_str,
|
||||||
|
new_name_len);
|
||||||
|
names_len -= old_name_len;
|
||||||
|
names_len += new_name_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_name = memchr(reg_name, '\0', remaining_names_len);
|
||||||
|
if (!reg_name)
|
||||||
|
break;
|
||||||
|
|
||||||
|
reg_name += 1;
|
||||||
|
|
||||||
|
remaining_names_len = names_len -
|
||||||
|
(reg_name - reg_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
fdt_setprop(fdt, off, "reg-names", reg_names, names_len);
|
||||||
|
off = fdt_node_offset_by_compatible(fdt, off,
|
||||||
|
"fsl,lx2160a-pcie");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_TARGET_LX2160AQDS)
|
#if defined(CONFIG_TARGET_LX2160AQDS)
|
||||||
void esdhc_dspi_status_fixup(void *blob)
|
void esdhc_dspi_status_fixup(void *blob)
|
||||||
{
|
{
|
||||||
@ -283,7 +351,7 @@ int checkboard(void)
|
|||||||
|
|
||||||
puts("SERDES1 Reference: Clock1 = 161.13MHz Clock2 = 161.13MHz\n");
|
puts("SERDES1 Reference: Clock1 = 161.13MHz Clock2 = 161.13MHz\n");
|
||||||
puts("SERDES2 Reference: Clock1 = 100MHz Clock2 = 100MHz\n");
|
puts("SERDES2 Reference: Clock1 = 100MHz Clock2 = 100MHz\n");
|
||||||
puts("SERDES3 Reference: Clock1 = 100MHz Clock2 = 100Hz\n");
|
puts("SERDES3 Reference: Clock1 = 100MHz Clock2 = 100MHz\n");
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -55,4 +55,6 @@ CONFIG_FSL_QSPI=y
|
|||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_DM_USB=y
|
CONFIG_DM_USB=y
|
||||||
CONFIG_USB_XHCI_HCD=y
|
CONFIG_USB_XHCI_HCD=y
|
||||||
|
CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK=y
|
||||||
|
CONFIG_MMC_HS200_SUPPORT=y
|
||||||
CONFIG_USB_XHCI_DWC3=y
|
CONFIG_USB_XHCI_DWC3=y
|
||||||
|
@ -74,4 +74,6 @@ CONFIG_USB_XHCI_HCD=y
|
|||||||
CONFIG_USB_XHCI_DWC3=y
|
CONFIG_USB_XHCI_DWC3=y
|
||||||
CONFIG_WDT=y
|
CONFIG_WDT=y
|
||||||
CONFIG_WDT_SP805=y
|
CONFIG_WDT_SP805=y
|
||||||
|
CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK=y
|
||||||
|
CONFIG_MMC_HS200_SUPPORT=y
|
||||||
CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
|
CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
|
||||||
|
@ -9,6 +9,7 @@ CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
|
|||||||
CONFIG_AHCI=y
|
CONFIG_AHCI=y
|
||||||
CONFIG_FIT_VERBOSE=y
|
CONFIG_FIT_VERBOSE=y
|
||||||
CONFIG_OF_BOARD_SETUP=y
|
CONFIG_OF_BOARD_SETUP=y
|
||||||
|
CONFIG_OF_BOARD_FIXUP=y
|
||||||
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||||
CONFIG_BOOTDELAY=10
|
CONFIG_BOOTDELAY=10
|
||||||
CONFIG_USE_BOOTARGS=y
|
CONFIG_USE_BOOTARGS=y
|
||||||
|
@ -10,6 +10,7 @@ CONFIG_SEC_FIRMWARE_ARMV8_PSCI=y
|
|||||||
CONFIG_AHCI=y
|
CONFIG_AHCI=y
|
||||||
CONFIG_FIT_VERBOSE=y
|
CONFIG_FIT_VERBOSE=y
|
||||||
CONFIG_OF_BOARD_SETUP=y
|
CONFIG_OF_BOARD_SETUP=y
|
||||||
|
CONFIG_OF_BOARD_FIXUP=y
|
||||||
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
CONFIG_OF_STDOUT_VIA_ALIAS=y
|
||||||
CONFIG_BOOTDELAY=10
|
CONFIG_BOOTDELAY=10
|
||||||
CONFIG_USE_BOOTARGS=y
|
CONFIG_USE_BOOTARGS=y
|
||||||
@ -62,4 +63,6 @@ CONFIG_USB=y
|
|||||||
CONFIG_DM_USB=y
|
CONFIG_DM_USB=y
|
||||||
CONFIG_USB_XHCI_HCD=y
|
CONFIG_USB_XHCI_HCD=y
|
||||||
CONFIG_USB_XHCI_DWC3=y
|
CONFIG_USB_XHCI_DWC3=y
|
||||||
|
CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK=y
|
||||||
|
CONFIG_MMC_HS200_SUPPORT=y
|
||||||
CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
|
CONFIG_EFI_LOADER_BOUNCE_BUFFER=y
|
||||||
|
@ -167,7 +167,6 @@ config MMC_HS200_SUPPORT
|
|||||||
The HS200 mode is support by some eMMC. The bus frequency is up to
|
The HS200 mode is support by some eMMC. The bus frequency is up to
|
||||||
200MHz. This mode requires tuning the IO.
|
200MHz. This mode requires tuning the IO.
|
||||||
|
|
||||||
|
|
||||||
config SPL_MMC_HS200_SUPPORT
|
config SPL_MMC_HS200_SUPPORT
|
||||||
bool "enable HS200 support in SPL"
|
bool "enable HS200 support in SPL"
|
||||||
help
|
help
|
||||||
@ -695,10 +694,19 @@ endif
|
|||||||
|
|
||||||
config FSL_ESDHC
|
config FSL_ESDHC
|
||||||
bool "Freescale/NXP eSDHC controller support"
|
bool "Freescale/NXP eSDHC controller support"
|
||||||
|
select FSL_ESDHC_USE_PERIPHERAL_CLK if MMC_HS200_SUPPORT || MMC_UHS_SUPPORT
|
||||||
help
|
help
|
||||||
This selects support for the eSDHC (Enhanced Secure Digital Host
|
This selects support for the eSDHC (Enhanced Secure Digital Host
|
||||||
Controller) found on numerous Freescale/NXP SoCs.
|
Controller) found on numerous Freescale/NXP SoCs.
|
||||||
|
|
||||||
|
config FSL_ESDHC_USE_PERIPHERAL_CLK
|
||||||
|
bool "enable ESDHC peripheral clock support"
|
||||||
|
depends on FSL_ESDHC
|
||||||
|
help
|
||||||
|
eSDHC supports two reference clocks (platform clock and peripheral clock).
|
||||||
|
Peripheral clock which could provide higher clock frequency is required to
|
||||||
|
be used for tuning of SD UHS mode and eMMC HS200/HS400 modes.
|
||||||
|
|
||||||
config FSL_ESDHC_IMX
|
config FSL_ESDHC_IMX
|
||||||
bool "Freescale/NXP i.MX eSDHC controller support"
|
bool "Freescale/NXP i.MX eSDHC controller support"
|
||||||
help
|
help
|
||||||
|
@ -395,10 +395,6 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
|
|||||||
esdhc_write32(®s->cmdarg, cmd->cmdarg);
|
esdhc_write32(®s->cmdarg, cmd->cmdarg);
|
||||||
esdhc_write32(®s->xfertyp, xfertyp);
|
esdhc_write32(®s->xfertyp, xfertyp);
|
||||||
|
|
||||||
if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) ||
|
|
||||||
(cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200))
|
|
||||||
flags = IRQSTAT_BRR;
|
|
||||||
|
|
||||||
/* Wait for the command to complete */
|
/* Wait for the command to complete */
|
||||||
start = get_timer(0);
|
start = get_timer(0);
|
||||||
while (!(esdhc_read32(®s->irqstat) & flags)) {
|
while (!(esdhc_read32(®s->irqstat) & flags)) {
|
||||||
@ -458,12 +454,6 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
|
|||||||
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
|
||||||
esdhc_pio_read_write(priv, data);
|
esdhc_pio_read_write(priv, data);
|
||||||
#else
|
#else
|
||||||
flags = DATA_COMPLETE;
|
|
||||||
if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) ||
|
|
||||||
(cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)) {
|
|
||||||
flags = IRQSTAT_BRR;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
irqstat = esdhc_read32(®s->irqstat);
|
irqstat = esdhc_read32(®s->irqstat);
|
||||||
|
|
||||||
@ -476,7 +466,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
|
|||||||
err = -ECOMM;
|
err = -ECOMM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} while ((irqstat & flags) != flags);
|
} while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Need invalidate the dcache here again to avoid any
|
* Need invalidate the dcache here again to avoid any
|
||||||
@ -517,7 +507,9 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
|
|||||||
int div = 1;
|
int div = 1;
|
||||||
int pre_div = 2;
|
int pre_div = 2;
|
||||||
int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
|
int ddr_pre_div = mmc->ddr_mode ? 2 : 1;
|
||||||
int sdhc_clk = priv->sdhc_clk;
|
unsigned int sdhc_clk = priv->sdhc_clk;
|
||||||
|
u32 time_out;
|
||||||
|
u32 value;
|
||||||
uint clk;
|
uint clk;
|
||||||
|
|
||||||
if (clock < mmc->cfg->f_min)
|
if (clock < mmc->cfg->f_min)
|
||||||
@ -538,11 +530,18 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
|
|||||||
|
|
||||||
esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk);
|
esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk);
|
||||||
|
|
||||||
udelay(10000);
|
time_out = 20;
|
||||||
|
value = PRSSTAT_SDSTB;
|
||||||
|
while (!(esdhc_read32(®s->prsstat) & value)) {
|
||||||
|
if (time_out == 0) {
|
||||||
|
printf("fsl_esdhc: Internal clock never stabilised.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
time_out--;
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
|
||||||
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
|
esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
|
||||||
|
|
||||||
priv->clock = clock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
|
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
|
||||||
@ -1024,6 +1023,8 @@ static int fsl_esdhc_probe(struct udevice *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mmc_of_parse(dev, &plat->cfg);
|
||||||
|
|
||||||
mmc = &plat->mmc;
|
mmc = &plat->mmc;
|
||||||
mmc->cfg = &plat->cfg;
|
mmc->cfg = &plat->cfg;
|
||||||
mmc->dev = dev;
|
mmc->dev = dev;
|
||||||
@ -1081,6 +1082,9 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
|
|||||||
.get_cd = fsl_esdhc_get_cd,
|
.get_cd = fsl_esdhc_get_cd,
|
||||||
.send_cmd = fsl_esdhc_send_cmd,
|
.send_cmd = fsl_esdhc_send_cmd,
|
||||||
.set_ios = fsl_esdhc_set_ios,
|
.set_ios = fsl_esdhc_set_ios,
|
||||||
|
#ifdef MMC_SUPPORTS_TUNING
|
||||||
|
.execute_tuning = fsl_esdhc_execute_tuning,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -87,9 +87,16 @@ static int sp805_wdt_stop(struct udevice *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sp805_wdt_expire_now(struct udevice *dev, ulong flags)
|
||||||
|
{
|
||||||
|
sp805_wdt_start(dev, 0, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int sp805_wdt_probe(struct udevice *dev)
|
static int sp805_wdt_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
debug("%s: Probing wdt%u\n", __func__, dev->seq);
|
debug("%s: Probing wdt%u (sp805-wdt)\n", __func__, dev->seq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -109,6 +116,7 @@ static const struct wdt_ops sp805_wdt_ops = {
|
|||||||
.start = sp805_wdt_start,
|
.start = sp805_wdt_start,
|
||||||
.reset = sp805_wdt_reset,
|
.reset = sp805_wdt_reset,
|
||||||
.stop = sp805_wdt_stop,
|
.stop = sp805_wdt_stop,
|
||||||
|
.expire_now = sp805_wdt_expire_now,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct udevice_id sp805_wdt_ids[] = {
|
static const struct udevice_id sp805_wdt_ids[] = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
/*
|
/*
|
||||||
* Copyright 2018 NXP
|
* Copyright 2018-2019 NXP
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __LX2_COMMON_H
|
#ifndef __LX2_COMMON_H
|
||||||
@ -199,14 +199,14 @@ unsigned long get_board_ddr_clk(void);
|
|||||||
"fsl_mc start mc 0x20a00000 0x20e00000\0"
|
"fsl_mc start mc 0x20a00000 0x20e00000\0"
|
||||||
|
|
||||||
#define SD_MC_INIT_CMD \
|
#define SD_MC_INIT_CMD \
|
||||||
"mmc read 0x80000000 0x5000 0x800;" \
|
"mmc read 0x80a00000 0x5000 0x1200;" \
|
||||||
"mmc read 0x80100000 0x7000 0x800;" \
|
"mmc read 0x80e00000 0x7000 0x800;" \
|
||||||
"env exists secureboot && " \
|
"env exists secureboot && " \
|
||||||
"mmc read 0x80700000 0x3800 0x10 && " \
|
"mmc read 0x80700000 0x3800 0x10 && " \
|
||||||
"mmc read 0x80740000 0x3A00 0x10 && " \
|
"mmc read 0x80740000 0x3A00 0x10 && " \
|
||||||
"esbc_validate 0x80700000 && " \
|
"esbc_validate 0x80700000 && " \
|
||||||
"esbc_validate 0x80740000 ;" \
|
"esbc_validate 0x80740000 ;" \
|
||||||
"fsl_mc start mc 0x80000000 0x80100000\0"
|
"fsl_mc start mc 0x80a00000 0x80e00000\0"
|
||||||
|
|
||||||
#define EXTRA_ENV_SETTINGS \
|
#define EXTRA_ENV_SETTINGS \
|
||||||
"hwconfig=fsl_ddr:bank_intlv=auto\0" \
|
"hwconfig=fsl_ddr:bank_intlv=auto\0" \
|
||||||
@ -265,11 +265,11 @@ unsigned long get_board_ddr_clk(void);
|
|||||||
|
|
||||||
#define SD_BOOTCOMMAND \
|
#define SD_BOOTCOMMAND \
|
||||||
"env exists mcinitcmd && mmcinfo; " \
|
"env exists mcinitcmd && mmcinfo; " \
|
||||||
"mmc read 0x80001000 0x6800 0x800; " \
|
"mmc read 0x80d00000 0x6800 0x800; " \
|
||||||
"env exists mcinitcmd && env exists secureboot " \
|
"env exists mcinitcmd && env exists secureboot " \
|
||||||
" && mmc read 0x80780000 0x3C00 0x10 " \
|
" && mmc read 0x80780000 0x3C00 0x10 " \
|
||||||
"&& esbc_validate 0x80780000;env exists mcinitcmd " \
|
"&& esbc_validate 0x80780000;env exists mcinitcmd " \
|
||||||
"&& fsl_mc lazyapply dpl 0x80001000;" \
|
"&& fsl_mc lazyapply dpl 0x80d00000;" \
|
||||||
"run distro_bootcmd;run sd_bootcmd;" \
|
"run distro_bootcmd;run sd_bootcmd;" \
|
||||||
"env exists secureboot && esbc_halt;"
|
"env exists secureboot && esbc_halt;"
|
||||||
|
|
||||||
|
@ -205,6 +205,10 @@ struct fsl_esdhc_cfg {
|
|||||||
int fsl_esdhc_mmc_init(bd_t *bis);
|
int fsl_esdhc_mmc_init(bd_t *bis);
|
||||||
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg);
|
int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg);
|
||||||
void fdt_fixup_esdhc(void *blob, bd_t *bd);
|
void fdt_fixup_esdhc(void *blob, bd_t *bd);
|
||||||
|
#ifdef MMC_SUPPORTS_TUNING
|
||||||
|
static inline int fsl_esdhc_execute_tuning(struct udevice *dev,
|
||||||
|
uint32_t opcode) {return 0; }
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
static inline int fsl_esdhc_mmc_init(bd_t *bis) { return -ENOSYS; }
|
static inline int fsl_esdhc_mmc_init(bd_t *bis) { return -ENOSYS; }
|
||||||
static inline void fdt_fixup_esdhc(void *blob, bd_t *bd) {}
|
static inline void fdt_fixup_esdhc(void *blob, bd_t *bd) {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user