Merge tag 'u-boot-imx-next-20250601' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx into next
CI: https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/26436 - Add i.MX6UL clk driver. - Improve the .MX6UL NAND controller performance. - Add imx6ulz BSH SMM M2B board. - Several improvements for imx8m venice boards.
This commit is contained in:
@@ -98,6 +98,13 @@
|
||||
gpios = <6 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "m2_rst";
|
||||
};
|
||||
|
||||
m2_wdis2 {
|
||||
gpio-hog;
|
||||
output-high;
|
||||
gpios = <14 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "m2_wdis2#";
|
||||
};
|
||||
};
|
||||
|
||||
&gpio4 {
|
||||
@@ -110,11 +117,11 @@
|
||||
line-name = "m2_off#";
|
||||
};
|
||||
|
||||
m2_wdis {
|
||||
m2_wdis1 {
|
||||
gpio-hog;
|
||||
output-high;
|
||||
gpios = <18 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "m2_wdis#";
|
||||
line-name = "m2_wdis1#";
|
||||
};
|
||||
|
||||
rs485_en {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 Gateworks Corporation
|
||||
*/
|
||||
#include "imx8mp-venice-gw702x-u-boot.dtsi"
|
||||
|
||||
&gpio4 {
|
||||
dio_1 {
|
||||
gpio-hog;
|
||||
input;
|
||||
gpios = <8 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "dio1";
|
||||
};
|
||||
|
||||
dio_0 {
|
||||
gpio-hog;
|
||||
input;
|
||||
gpios = <11 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "dio0#";
|
||||
};
|
||||
|
||||
usb1mux {
|
||||
gpio-hog;
|
||||
output-high;
|
||||
gpios = <17 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "usb1_mux";
|
||||
};
|
||||
|
||||
rs485_en {
|
||||
gpio-hog;
|
||||
output-low;
|
||||
gpios = <22 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "rs485_en";
|
||||
};
|
||||
|
||||
rs485_term {
|
||||
gpio-hog;
|
||||
output-low;
|
||||
gpios = <23 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "rs485_term";
|
||||
};
|
||||
|
||||
rs485_half {
|
||||
gpio-hog;
|
||||
output-low;
|
||||
gpios = <27 GPIO_ACTIVE_HIGH>;
|
||||
line-name = "rs485_hd";
|
||||
};
|
||||
};
|
||||
@@ -9,4 +9,25 @@ config SYS_VENDOR
|
||||
config SYS_CONFIG_NAME
|
||||
default "imx6ulz_smm_m2"
|
||||
|
||||
choice
|
||||
prompt "Memory Type (M2/M2B) board"
|
||||
default BSH_M2_MEMORY
|
||||
help
|
||||
Memory type setup.
|
||||
Please choose correct memory model here.
|
||||
|
||||
config BSH_M2_MEMORY
|
||||
bool "Enable for bsh m2 variant"
|
||||
help
|
||||
If this option is enabled, U-Boot will be configured to support
|
||||
imx6ulz bsh m2 revision memories.
|
||||
|
||||
config BSH_M2B_MEMORY
|
||||
bool "Enable for bsh m2b variant"
|
||||
help
|
||||
If this option is enabled, U-Boot will be configured to support
|
||||
imx6ulz bsh m2b revision memories.
|
||||
|
||||
endchoice
|
||||
|
||||
endif
|
||||
|
||||
@@ -4,3 +4,4 @@ S: Maintained
|
||||
F: board/bsh/imx6ulz_smm_m2/
|
||||
F: include/configs/imx6ulz_smm_m2.h
|
||||
F: configs/imx6ulz_smm_m2_defconfig
|
||||
F: configs/imx6ulz_smm_m2b_defconfig
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
# (C) Copyright 2021 Amarula Solutions B.V.
|
||||
|
||||
obj-y := imx6ulz_smm_m2.o
|
||||
obj-$(CONFIG_XPL_BUILD) += spl.o ddr3l_timing_512m.o ddr3l_timing_256m.o ddr3l_timing_128m.o
|
||||
obj-$(CONFIG_XPL_BUILD) += spl.o
|
||||
obj-$(CONFIG_BSH_M2_MEMORY) += ddr3l_timing_512m.o ddr3l_timing_256m.o ddr3l_timing_128m.o
|
||||
obj-$(CONFIG_BSH_M2B_MEMORY) += ddr3l_timing_256m_m2b.o ddr3l_timing_128m_m2b.o
|
||||
|
||||
@@ -166,4 +166,5 @@ static const struct dram_cfg_param ddr_ddrc_cfg_128mb[] = {
|
||||
struct dram_timing_info bsh_dram_timing_128mb = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_128mb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_128mb),
|
||||
.dram_size = SZ_128M,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "spl_mtypes.h"
|
||||
|
||||
static const struct dram_cfg_param ddr_ddrc_cfg_128mb[] = {
|
||||
/* IOMUX */
|
||||
|
||||
/* DDR IO Type: */
|
||||
{0x020e04b4, 0x000C0000}, /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */
|
||||
{0x020e04ac, 0x00000000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */
|
||||
|
||||
/* Clock: */
|
||||
{0x020e027c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 */
|
||||
|
||||
/* Address: */
|
||||
{0x020e0250, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */
|
||||
{0x020e024c, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */
|
||||
{0x020e0490, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */
|
||||
|
||||
/* Control: */
|
||||
{0x020e0288, 0x000C0028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */
|
||||
{0x020e0270, 0x00000000}, /*
|
||||
* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be configured
|
||||
* using Group Control Register IOMUXC_SW_PAD_CTL_GRP_CTLDS
|
||||
*/
|
||||
|
||||
{0x020e0260, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 */
|
||||
{0x020e0264, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 */
|
||||
{0x020e04a0, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */
|
||||
|
||||
/* Data Strobes: */
|
||||
{0x020e0494, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */
|
||||
{0x020e0280, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 */
|
||||
{0x020e0284, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 */
|
||||
|
||||
/* Data: */
|
||||
{0x020e04b0, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */
|
||||
{0x020e0498, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B0DS */
|
||||
{0x020e04a4, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_B1DS */
|
||||
|
||||
{0x020e0244, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */
|
||||
{0x020e0248, 0x00000028}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */
|
||||
|
||||
/*
|
||||
* =============================================================================
|
||||
* DDR Controller Registers
|
||||
* =============================================================================
|
||||
* Manufacturer:WINBOND
|
||||
* Device Part Number:W631GU6RB-11
|
||||
* Clock Freq.: 400MHz
|
||||
* Density per CS in Gb: 1
|
||||
* Chip Selects used:1
|
||||
* Total DRAM density (Gb)1
|
||||
* Number of Banks:8
|
||||
* Row address: 13
|
||||
* Column address: 10
|
||||
* Data bus width16
|
||||
* =============================================================================
|
||||
*/
|
||||
{0x021b001c, 0x00008000}, /*
|
||||
* MMDC0_MDSCR, set the Configuration request bit
|
||||
* during MMDC set up
|
||||
*/
|
||||
|
||||
/*
|
||||
* =============================================================================
|
||||
* Calibration setup.
|
||||
* =============================================================================
|
||||
*/
|
||||
{0x021b0800, 0xA1390003}, /*
|
||||
* DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic
|
||||
* HW ZQ calibration.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For target board, may need to run write leveling calibration to fine tune
|
||||
* these settings.
|
||||
*/
|
||||
{0x021b080c, 0x00060002},
|
||||
|
||||
/* Read DQS Gating calibration */
|
||||
{0x021b083c, 0x414c0150}, /* MPDGCTRL0 PHY0 */
|
||||
|
||||
/* Read calibration */
|
||||
{0x021b0848, 0x4040363e}, /* MPRDDLCTL PHY0 */
|
||||
|
||||
/* Write calibration */
|
||||
{0x021b0850, 0x40402a28}, /* MPWRDLCTL PHY0 */
|
||||
|
||||
/*
|
||||
* Read data bit delay: 3 is the recommended default value, although out of reset
|
||||
* value is 0.
|
||||
*/
|
||||
{0x021b081c, 0x33333333}, /* MMDC_MPRDDQBY0DL */
|
||||
{0x021b0820, 0x33333333}, /* MMDC_MPRDDQBY1DL */
|
||||
|
||||
/* Write data bit delay: */
|
||||
{0x021b082c, 0xf3333333}, /* MMDC_MPWRDQBY0DL */
|
||||
{0x021b0830, 0xf3333333}, /* MMDC_MPWRDQBY1DL */
|
||||
|
||||
/* DQS&CLK Duty Cycle */
|
||||
{0x021b08c0, 0x00944009}, /* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */
|
||||
|
||||
/* Complete calibration by forced measurement: */
|
||||
{0x021b08b8, 0x00000800}, /* DDR_PHY_P0_MPMUR0, frc_msr */
|
||||
|
||||
/* MMDC init: */
|
||||
{0x021b0004, 0x0002002D}, /* MMDC0_MDPDC */
|
||||
{0x021b0008, 0x1B333030}, /* MMDC0_MDOTC */
|
||||
{0x021b000c, 0x2B2F52F3}, /* MMDC0_MDCFG0 */
|
||||
{0x021b0010, 0xB66D0A63}, /* MMDC0_MDCFG1 */
|
||||
{0x021b0014, 0x01FF00DB}, /* MMDC0_MDCFG2 */
|
||||
{0x021b0018, 0x00201740}, /* MMDC0_MDMISC */
|
||||
{0x021b002C, 0x000026D2}, /* MMDC0_MDRWD */
|
||||
{0x021b0030, 0x002F1023}, /* MMDC0_MDOR */
|
||||
{0x021b0040, 0x00000043}, /* CS0_END */
|
||||
{0x021b0000, 0x82180000}, /* MMDC0_MDCTL */
|
||||
|
||||
/* Mode register writes for CS0 */
|
||||
{0x021B001C, 0x02808032}, /* MMDC0_MDSCR, MR2 write, CS0 */
|
||||
{0x021B001C, 0x00008033}, /* MMDC0_MDSCR, MR3 write, CS0 */
|
||||
{0x021B001C, 0x00048031}, /* MMDC0_MDSCR, MR1 write, CS0 */
|
||||
{0x021B001C, 0x15208030}, /* MMDC0_MDSCR, MR0 write, CS0 */
|
||||
{0x021B001C, 0x04008040}, /*
|
||||
* MMDC0_MDSCR, ZQ calibration
|
||||
* command sent to device on CS0
|
||||
*/
|
||||
|
||||
/* final DDR setup, before operation start: */
|
||||
{0x021b0020, 0x00000800}, /* MMDC0_MDREF */
|
||||
|
||||
{0x021b0818, 0x00000227}, /* DDR_PHY_P0_MPODTCTRL */
|
||||
|
||||
{0x021b0004, 0x0002556D}, /* MMDC0_MDPDC now SDCTL power down enabled */
|
||||
|
||||
{0x021b0404, 0x00011006}, /*
|
||||
* MMDC0_MAPSR ADOPT power down enabled,
|
||||
* MMDC will enter automatically to self-refresh
|
||||
* while the number of idle cycle reached.
|
||||
*/
|
||||
|
||||
{0x021b001c, 0x00000000}, /*
|
||||
* MMDC0_MDSCR, clear this register (especially the
|
||||
* configuration bit as initialization is complete)
|
||||
*/
|
||||
};
|
||||
|
||||
struct dram_timing_info bsh_dram_timing_128mb = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_128mb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_128mb),
|
||||
.dram_size = SZ_128M,
|
||||
};
|
||||
@@ -165,4 +165,5 @@ static const struct dram_cfg_param ddr_ddrc_cfg_256mb[] = {
|
||||
struct dram_timing_info bsh_dram_timing_256mb = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_256mb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_256mb),
|
||||
.dram_size = SZ_256M,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "spl_mtypes.h"
|
||||
|
||||
static const struct dram_cfg_param ddr_ddrc_cfg_256mb[] = {
|
||||
/* IOMUX */
|
||||
|
||||
/* DDR IO Type: */
|
||||
{0x020e04b4, 0x000C0000}, /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */
|
||||
{0x020e04ac, 0x00000000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */
|
||||
|
||||
/* Clock: */
|
||||
{0x020e027c, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK0_P */
|
||||
|
||||
/* Address: */
|
||||
{0x020e0250, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */
|
||||
{0x020e024c, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */
|
||||
{0x020e0490, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */
|
||||
|
||||
/* Control: */
|
||||
{0x020e0288, 0x000C0030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */
|
||||
{0x020e0270, 0x00000000}, /*
|
||||
* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be
|
||||
* configured using Group Control Register:
|
||||
* IOMUXC_SW_PAD_CTL_GRP_CTLDS
|
||||
*/
|
||||
|
||||
{0x020e0260, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_ODT0 */
|
||||
{0x020e0264, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_ODT1 */
|
||||
{0x020e04a0, 0x00000028}, /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */
|
||||
|
||||
/* Data Strobes: */
|
||||
{0x020e0494, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */
|
||||
{0x020e0280, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0_P */
|
||||
{0x020e0284, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1_P */
|
||||
|
||||
/* Data: */
|
||||
{0x020e04b0, 0x00020000}, /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */
|
||||
{0x020e0498, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_B0DS */
|
||||
{0x020e04a4, 0x00000030}, /* IOMUXC_SW_PAD_CTL_GRP_B1DS */
|
||||
|
||||
{0x020e0244, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */
|
||||
{0x020e0248, 0x00000030}, /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */
|
||||
|
||||
/*
|
||||
* =============================================================================
|
||||
* DDR Controller Registers
|
||||
* =============================================================================
|
||||
* Manufacturer:WINBOND
|
||||
* Device Part Number:W632GU6RB-11
|
||||
* Clock Freq.: 400MHz
|
||||
* Density per CS in Gb: 2
|
||||
* Chip Selects used:1
|
||||
* Total DRAM density (Gb)2
|
||||
* Number of Banks:8
|
||||
* Row address: 14
|
||||
* Column address: 10
|
||||
* Data bus width16
|
||||
* =============================================================================
|
||||
*/
|
||||
{0x021b001c, 0x00008000}, /*
|
||||
* MMDC0_MDSCR, set the Configuration request bit
|
||||
* during MMDC set up
|
||||
*/
|
||||
|
||||
/*
|
||||
* =============================================================================
|
||||
* Calibration setup.
|
||||
* =============================================================================
|
||||
*/
|
||||
{0x021b0800, 0xA1390003}, /*
|
||||
* DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic
|
||||
* HW ZQ calibration.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For target board, may need to run write leveling calibration to fine tune
|
||||
* these settings.
|
||||
*/
|
||||
{0x021b080c, 0x00070005},
|
||||
|
||||
/* Read DQS Gating calibration */
|
||||
{0x021b083c, 0x414c0150}, /* MPDGCTRL0 PHY0 */
|
||||
|
||||
/* Read calibration */
|
||||
{0x021b0848, 0x4040383e}, /* MMDC_MPRDDLCTL */
|
||||
|
||||
/* Write calibration */
|
||||
{0x021b0850, 0x40402e2a}, /* MMDC_MPWRDLCTL */
|
||||
|
||||
{0x021B081C, 0x33333333}, /* MMDC_MPRDDQBY0DL */
|
||||
{0x021B0820, 0x33333333}, /* MMDC_MPRDDQBY1DL */
|
||||
|
||||
{0x021B082C, 0xf3333333}, /* MMDC_MPWRDQBY0DL */
|
||||
{0x021B0830, 0xf3333333}, /* MMDC_MPWRDQBY1DL */
|
||||
|
||||
{0x021B08C0, 0x00944009}, /* MMDC_MPDCCR */
|
||||
|
||||
/* Complete calibration by forced measurement: */
|
||||
{0x021B08B8, 0x00000800}, /* DDR_PHY_P0_MPMUR0, frc_msr */
|
||||
|
||||
/* MMDC init: */
|
||||
{0x021b0004, 0x00020024}, /* MMDC0_MDPDC */
|
||||
{0x021b0008, 0x1B333030}, /* MMDC0_MDOTC */
|
||||
{0x021b000c, 0x3F4352D3}, /* MMDC0_MDCFG0 */
|
||||
{0x021b0010, 0xB66D0A63}, /* MMDC0_MDCFG1 */
|
||||
{0x021b0014, 0x01FF00DB}, /* MMDC0_MDCFG2 */
|
||||
{0x021b0018, 0x00201740}, /* MMDC0_MDMISC */
|
||||
{0x021b002C, 0x000026D2}, /* MMDC0_MDRWD */
|
||||
{0x021b0030, 0x00431023}, /* MMDC0_MDOR */
|
||||
{0x021b0040, 0x00000047}, /* CS0_END */
|
||||
{0x021b0000, 0x83180000}, /* MMDC0_MDCTL */
|
||||
|
||||
/* Mode register writes for CS0 */
|
||||
{0x021B001C, 0x02808032}, /* MMDC0_MDSCR, MR2 write, CS0 */
|
||||
{0x021B001C, 0x00008033}, /* MMDC0_MDSCR, MR3 write, CS0 */
|
||||
{0x021B001C, 0x00048031}, /* MMDC0_MDSCR, MR1 write, CS0 */
|
||||
{0x021B001C, 0x15208030}, /* MMDC0_MDSCR, MR0 write, CS0 */
|
||||
{0x021B001C, 0x04008040}, /* MMDC0_MDSCR, ZQ calibration */
|
||||
|
||||
/* final DDR setup, before operation start: */
|
||||
{0x021b0020, 0x00000800}, /* MMDC0_MDREF */
|
||||
|
||||
{0x021b0818, 0x00000227}, /* DDR_PHY_P0_MPODTCTRL */
|
||||
{0x021b0004, 0x00025564}, /* MMDC0_MDPDC now SDCTL power down enabled */
|
||||
{0x021b0404, 0x00011006}, /* MMDC0_MAPSR ADOPT power down enabled */
|
||||
{0x021b001c, 0x00000000}, /*
|
||||
* MMDC0_MDSCR, clear this register (especially
|
||||
* the configuration bit as initialization is complete)
|
||||
*/
|
||||
};
|
||||
|
||||
struct dram_timing_info bsh_dram_timing_256mb = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_256mb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_256mb),
|
||||
.dram_size = SZ_256M,
|
||||
};
|
||||
@@ -165,4 +165,5 @@ static const struct dram_cfg_param ddr_ddrc_cfg_512mb[] = {
|
||||
struct dram_timing_info bsh_dram_timing_512mb = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_512mb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_512mb),
|
||||
.dram_size = SZ_512M,
|
||||
};
|
||||
|
||||
@@ -52,28 +52,31 @@ static void ddr_cfg_write(const struct dram_timing_info *dram_timing_info)
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dram_timing_info *board_dram_timing[] = {
|
||||
#if defined(CONFIG_M2_MEMORY)
|
||||
&bsh_dram_timing_512mb,
|
||||
#endif
|
||||
&bsh_dram_timing_256mb,
|
||||
&bsh_dram_timing_128mb,
|
||||
};
|
||||
|
||||
static void spl_dram_init(void)
|
||||
{
|
||||
/* Configure memory to maximum supported size for detection */
|
||||
ddr_cfg_write(&bsh_dram_timing_512mb);
|
||||
ddr_cfg_write(board_dram_timing[0]);
|
||||
|
||||
/* Detect memory physically present */
|
||||
gd->ram_size = get_ram_size((void *)CFG_SYS_SDRAM_BASE, SZ_512M);
|
||||
gd->ram_size = get_ram_size((void *)CFG_SYS_SDRAM_BASE, board_dram_timing[0]->dram_size);
|
||||
|
||||
/* Reconfigure memory for actual detected size */
|
||||
switch (gd->ram_size) {
|
||||
case SZ_512M:
|
||||
/* Already configured, nothing to do */
|
||||
break;
|
||||
case SZ_256M:
|
||||
udelay(1);
|
||||
ddr_cfg_write(&bsh_dram_timing_256mb);
|
||||
break;
|
||||
case SZ_128M:
|
||||
default:
|
||||
udelay(1);
|
||||
ddr_cfg_write(&bsh_dram_timing_128mb);
|
||||
break;
|
||||
if (board_dram_timing[0]->dram_size == gd->ram_size)
|
||||
return;
|
||||
|
||||
for (size_t index = 1; index < ARRAY_SIZE(board_dram_timing); index++) {
|
||||
if (board_dram_timing[index]->dram_size == gd->ram_size) {
|
||||
udelay(1);
|
||||
ddr_cfg_write(board_dram_timing[index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ struct dram_cfg_param {
|
||||
struct dram_timing_info {
|
||||
const struct dram_cfg_param *ddrc_cfg;
|
||||
unsigned int ddrc_cfg_num;
|
||||
size_t dram_size;
|
||||
};
|
||||
|
||||
extern struct dram_timing_info bsh_dram_timing_128mb;
|
||||
|
||||
@@ -0,0 +1,736 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright 2025 Gateworks Corporation
|
||||
*/
|
||||
|
||||
#include <command.h>
|
||||
#include <hexdump.h>
|
||||
#include <i2c.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/device-internal.h> // device_remove/device_unbind
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <fdt_support.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "fsa.h"
|
||||
|
||||
static int fsa;
|
||||
static struct udevice *fsa_gpiodevs[FSA_MAX] = { NULL };
|
||||
|
||||
/* find the ofnode of the FSA i2c bus */
|
||||
static ofnode fsa_get_ofnode(int fsa)
|
||||
{
|
||||
char str[32];
|
||||
|
||||
/* by alias */
|
||||
snprintf(str, sizeof(str), "fsa%d", fsa);
|
||||
return ofnode_get_aliases_node(str);
|
||||
}
|
||||
|
||||
static int fsa_get_dtnode(void *fdt, int fsa)
|
||||
{
|
||||
char str[32];
|
||||
|
||||
/* by alias */
|
||||
snprintf(str, sizeof(str), "fsa%d", fsa);
|
||||
return fdt_path_offset(fdt, fdt_get_alias(fdt, str));
|
||||
}
|
||||
|
||||
static const char * const fsa_gpio_config_names[] = { "NC", "", "input", "output-low",
|
||||
"output-high" };
|
||||
|
||||
static const char *fsa_gpio_config_name(struct fsa_gpio_desc *desc)
|
||||
{
|
||||
if (desc->config < ARRAY_SIZE(fsa_gpio_config_names))
|
||||
return fsa_gpio_config_names[desc->config];
|
||||
return NULL;
|
||||
};
|
||||
|
||||
static char *fsa_get_gpio_desc(struct fsa_gpio_desc *desc, char *str, int sz)
|
||||
{
|
||||
str[0] = 0;
|
||||
if (desc->source == 0xff) {
|
||||
snprintf(str, sz, "fsa_gpio%d : %s %s",
|
||||
desc->offset + 1,
|
||||
desc->name,
|
||||
fsa_gpio_config_name(desc));
|
||||
} else if (desc->config) {
|
||||
snprintf(str, sz, "gpio@%02x_%02d: %s %s",
|
||||
desc->source,
|
||||
desc->offset,
|
||||
desc->name,
|
||||
fsa_gpio_config_name(desc));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static void fsa_show_gpio_descs(const char *prefix, int fsa, struct fsa_board_info *board_info,
|
||||
struct fsa_user_info *user_info)
|
||||
{
|
||||
char str[128];
|
||||
int i;
|
||||
|
||||
/* display slot specific gpios */
|
||||
for (i = 0; i < board_info->sockgpios; i++) {
|
||||
fsa_get_gpio_desc(&user_info->gpios[i], str, sizeof(str));
|
||||
printf("%s%-2d: %s\n", prefix, i, str);
|
||||
}
|
||||
/* display io-expander specific gpios */
|
||||
if (fsa_gpiodevs[fsa]) {
|
||||
for (i = board_info->sockgpios;
|
||||
i < (board_info->sockgpios + board_info->ioexpgpios);
|
||||
i++) {
|
||||
fsa_get_gpio_desc(&user_info->gpios[i], str, sizeof(str));
|
||||
printf("%s%-2d: %s\n", prefix, i, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* detect gpio expander by address and deal with enabling/disabling/adding gpio expander to dt */
|
||||
static int fsa_get_gpiodev(int fsa, int addr, struct udevice **devp)
|
||||
{
|
||||
struct udevice *bus, *dev;
|
||||
char gpio_name[32];
|
||||
int ret;
|
||||
|
||||
ret = device_get_global_by_ofnode(fsa_get_ofnode(fsa), &bus);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sprintf(gpio_name, "gpio@%02x", addr);
|
||||
|
||||
/* probe device on i2c bus */
|
||||
ret = dm_i2c_probe(bus, addr, 0, &dev);
|
||||
switch (ret) {
|
||||
case -EREMOTEIO: /* chip is not present on i2c bus */
|
||||
/* if device is in dt remove/unbind/disable it */
|
||||
ret = device_find_child_by_name(bus, gpio_name, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ofnode_set_enabled(dev_ofnode(dev), false);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = device_unbind(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = device_remove(dev, DM_REMOVE_NORMAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ret;
|
||||
case -ENOSYS: /* chip found but driver invalid */
|
||||
/* if device is in not in dt add/bind it */
|
||||
return ret;
|
||||
case 0: /* chip responded and driver bound */
|
||||
break;
|
||||
}
|
||||
|
||||
if (devp)
|
||||
*devp = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add gpio's to gpio device: GPIO device must be probed before you can manipulate it */
|
||||
static int fsa_config_gpios(int fsa, struct fsa_user_info *info, int gpios, struct udevice *dev)
|
||||
{
|
||||
struct fsa_gpio_desc *desc;
|
||||
struct gpio_desc gdesc;
|
||||
struct udevice *gdev;
|
||||
int i, ret, flags;
|
||||
char name[32];
|
||||
|
||||
/* configure GPIO's */
|
||||
for (i = 0; i < gpios; i++) {
|
||||
desc = &info->gpios[i];
|
||||
if (desc->config < FSA_GPIO_INPUT)
|
||||
continue;
|
||||
memset(&gdesc, 0, sizeof(gdesc));
|
||||
|
||||
if (desc->source == 0xff) {
|
||||
/* Board specific IMX8M GPIO's: find dev of controller by line-name */
|
||||
sprintf(name, "fsa%d_gpio%d", fsa, desc->offset + 1);
|
||||
uclass_foreach_dev_probe(UCLASS_GPIO, gdev) {
|
||||
ret = dev_read_stringlist_search(gdev, "gpio-line-names", name);
|
||||
if (ret >= 0) {
|
||||
gdesc.dev = gdev;
|
||||
gdesc.offset = ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* port expander GPIOs */
|
||||
gdesc.dev = dev;
|
||||
gdesc.offset = desc->offset;
|
||||
}
|
||||
|
||||
if (!gdesc.dev)
|
||||
continue;
|
||||
|
||||
sprintf(name, "fsa%d_%s", fsa, desc->name);
|
||||
switch (desc->config) {
|
||||
case FSA_GPIO_INPUT:
|
||||
flags = GPIOD_IS_IN;
|
||||
break;
|
||||
case FSA_GPIO_OUTPUT_LOW:
|
||||
flags = GPIOD_IS_OUT;
|
||||
break;
|
||||
case FSA_GPIO_OUTPUT_HIGH:
|
||||
flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
|
||||
break;
|
||||
}
|
||||
if (!dm_gpio_request(&gdesc, name))
|
||||
dm_gpio_clrset_flags(&gdesc, GPIOD_MASK_DIR, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsa_read_board_config(int fsa, struct fsa_board_info *info)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int chksum;
|
||||
int i, ret;
|
||||
ofnode node;
|
||||
|
||||
/* find eeprom dev */
|
||||
node = ofnode_find_subnode(fsa_get_ofnode(fsa), "eeprom@54");
|
||||
if (!ofnode_valid(node))
|
||||
return -EINVAL;
|
||||
ret = device_get_global_by_ofnode(node, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read eeprom */
|
||||
ret = dm_i2c_read(dev, 0, (uint8_t *)info, sizeof(*info));
|
||||
if (ret) {
|
||||
dev_err(dev, "read failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* validate checksum */
|
||||
for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++)
|
||||
chksum += ((unsigned char *)info)[i];
|
||||
if ((info->chksum[0] != ((chksum >> 8) & 0xff)) ||
|
||||
(info->chksum[1] != (chksum & 0xff))) {
|
||||
dev_err(dev, "FSA%d EEPROM: Invalid User Config Checksum\n", fsa);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, info, sizeof(*info));
|
||||
memset(info, 0, sizeof(*info));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsa_read_user_config(int fsa, struct fsa_user_info *info)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int chksum;
|
||||
int i, ret;
|
||||
ofnode node;
|
||||
|
||||
/* find eeprom dev */
|
||||
node = ofnode_find_subnode(fsa_get_ofnode(fsa), "eeprom@55");
|
||||
if (!ofnode_valid(node))
|
||||
return -EINVAL;
|
||||
ret = device_get_global_by_ofnode(node, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read eeprom */
|
||||
ret = dm_i2c_read(dev, 0, (uint8_t *)info, sizeof(*info));
|
||||
if (ret) {
|
||||
dev_err(dev, "read failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* validate checksum */
|
||||
for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++)
|
||||
chksum += ((unsigned char *)info)[i];
|
||||
if ((info->chksum[0] != ((chksum >> 8) & 0xff)) ||
|
||||
(info->chksum[1] != (chksum & 0xff))) {
|
||||
dev_err(dev, "FSA%d EEPROM: Invalid User Config Checksum\n", fsa);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, info, sizeof(*info));
|
||||
memset(info, 0, sizeof(*info));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsa_write_user_config(int fsa, struct fsa_user_info *info)
|
||||
{
|
||||
struct udevice *bus, *dev;
|
||||
int i, n, chunk, slave, base, ret;
|
||||
ofnode node;
|
||||
int chksum;
|
||||
|
||||
/* create checksum */
|
||||
for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++)
|
||||
chksum += ((unsigned char *)info)[i];
|
||||
info->chksum[0] = chksum >> 8;
|
||||
info->chksum[1] = chksum & 0xff;
|
||||
|
||||
/* find eeprom dev */
|
||||
node = ofnode_find_subnode(fsa_get_ofnode(fsa), "eeprom@55");
|
||||
ret = device_get_global_by_ofnode(node, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
bus = dev->parent;
|
||||
base = dev_read_addr(dev);
|
||||
|
||||
/* write in 16byte chunks (multi-byte writes fail larger than that) */
|
||||
chunk = 16;
|
||||
slave = -1;
|
||||
for (i = 0; i < sizeof(*info); i += chunk) {
|
||||
/* select device based on offset */
|
||||
if ((base + (i / 256)) != slave) {
|
||||
slave = base + (i / 256);
|
||||
ret = i2c_get_chip(bus, slave, 1, &dev);
|
||||
if (ret) {
|
||||
dev_err(bus, "failed to get eeprom@0x%02x: %d\n", slave, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/* select byte count */
|
||||
n = sizeof(*info) - i;
|
||||
if (n > chunk)
|
||||
n = chunk;
|
||||
ret = dm_i2c_write(dev, i % 256, (uint8_t *)info + i, n);
|
||||
if (ret) {
|
||||
dev_err(dev, "write failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mdelay(11);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsa_detect(int fsa, struct fsa_board_info *board_info, struct fsa_user_info *user_info,
|
||||
bool gpio)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fsa_read_board_config(fsa, board_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (user_info) {
|
||||
ret = fsa_read_user_config(fsa, user_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* detect port expander */
|
||||
if (gpio && !fsa_get_gpiodev(fsa, 0x20, &fsa_gpiodevs[fsa]))
|
||||
fsa_config_gpios(fsa, user_info,
|
||||
board_info->sockgpios + board_info->ioexpgpios,
|
||||
fsa_gpiodevs[fsa]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ft_fixup_stringlist_elem(void *fdt, int offset, const char *prop, int elem,
|
||||
const char *val)
|
||||
{
|
||||
const char *list, *end;
|
||||
char *new, *buf;
|
||||
int length;
|
||||
int sz = 0;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
if (offset < 0 || elem < 0 || !val) {
|
||||
printf("%s -EINVAL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list = fdt_getprop(fdt, offset, prop, &length);
|
||||
|
||||
/* no property or invalid params */
|
||||
if (!list || length < 0) {
|
||||
printf("%s failed - no property\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* create new buffer with enough space */
|
||||
buf = calloc(1, length + strlen(val));
|
||||
new = buf;
|
||||
|
||||
/* iterate over current stringlist and build new list into buf */
|
||||
end = list + length;
|
||||
while (list < end) {
|
||||
length = strnlen(list, end - list) + 1;
|
||||
sz += length;
|
||||
/* insert new value into buf */
|
||||
if (elem == i) {
|
||||
strcpy(new, val);
|
||||
new += strlen(val) + 1;
|
||||
} else {
|
||||
strcpy(new, list);
|
||||
new += length;
|
||||
}
|
||||
list += length;
|
||||
i++;
|
||||
}
|
||||
length = new - buf;
|
||||
ret = fdt_setprop(fdt, offset, prop, buf, length);
|
||||
free(buf);
|
||||
if (ret)
|
||||
printf("%s failed %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ft_fixup_fsa_gpio_name(void *fdt, int offset, int fsa, int gpio, const char *name)
|
||||
{
|
||||
const char *prop = "gpio-line-names";
|
||||
char str[32];
|
||||
|
||||
sprintf(str, "fsa%d_%s", fsa, name);
|
||||
|
||||
if (!fdt_getprop(fdt, offset, prop, NULL)) {
|
||||
char buf[16] = { 0 };
|
||||
|
||||
fdt_setprop(fdt, offset, prop, &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
return ft_fixup_stringlist_elem(fdt, offset, prop, gpio, str);
|
||||
}
|
||||
|
||||
static void fsa_show_details(int fsa, struct fsa_board_info *board, struct fsa_user_info *user)
|
||||
{
|
||||
printf("FSA%d: %s\n", fsa, board->model);
|
||||
printf("description: %s\n", user->desc);
|
||||
printf("overlay: %s\n", user->overlay);
|
||||
fsa_show_gpio_descs("\t", fsa, board, user);
|
||||
}
|
||||
|
||||
int fsa_init(void)
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
struct fsa_user_info user_info;
|
||||
int fsa, ret;
|
||||
|
||||
for (fsa = 1; fsa < FSA_MAX; fsa++) {
|
||||
ret = fsa_detect(fsa, &board_info, &user_info, true);
|
||||
if (!ret)
|
||||
printf("FSA%d: %s %s\n", fsa, board_info.model, user_info.desc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fsa_show(void)
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
int fsa, ret;
|
||||
|
||||
for (fsa = 1; fsa < FSA_MAX; fsa++) {
|
||||
ret = fsa_detect(fsa, &board_info, NULL, false);
|
||||
if (!ret) {
|
||||
printf("FSA%d : %s %d %02x-%02x-%02x%02x\n", fsa,
|
||||
board_info.model, board_info.serial,
|
||||
board_info.mfgdate[0], board_info.mfgdate[1],
|
||||
board_info.mfgdate[2], board_info.mfgdate[3]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fixup gpio line names for fsa gpios */
|
||||
int fsa_ft_fixup(void *fdt)
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
struct fsa_user_info user_info;
|
||||
int fsa, i, ret;
|
||||
char path[128];
|
||||
char str[32];
|
||||
ofnode node;
|
||||
int off;
|
||||
|
||||
/* iterate over FSA's and rename gpio's */
|
||||
for (fsa = 1; fsa < FSA_MAX; fsa++) {
|
||||
/* disable FSA ioexp node if disabled in controlling dt */
|
||||
off = fdt_subnode_offset(fdt, fsa_get_dtnode(fdt, fsa), "gpio@20");
|
||||
if (off >= 0) {
|
||||
if (!fdt_get_path(fdt, off, path, sizeof(path))) {
|
||||
node = ofnode_path(path);
|
||||
if (ofnode_valid(node) && !ofnode_is_enabled(node))
|
||||
fdt_setprop_string(fdt, off, "status", "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
/* detect FSA eeprom */
|
||||
if (fsa_detect(fsa, &board_info, &user_info, false))
|
||||
continue;
|
||||
|
||||
/* configure GPIO's */
|
||||
for (i = 0; i < board_info.sockgpios + board_info.ioexpgpios; i++) {
|
||||
if (user_info.gpios[i].config < FSA_GPIO_INPUT)
|
||||
continue;
|
||||
|
||||
if (user_info.gpios[i].source == 0xff) {
|
||||
/* Board specific IMX8M GPIO's */
|
||||
for (off = fdt_node_offset_by_prop_value(fdt, 0,
|
||||
"gpio-controller", NULL,
|
||||
0);
|
||||
off >= 0;
|
||||
off = fdt_node_offset_by_prop_value(fdt, off,
|
||||
"gpio-controller", NULL,
|
||||
0)
|
||||
) {
|
||||
sprintf(str, "fsa%d_gpio%d", fsa,
|
||||
user_info.gpios[i].offset + 1);
|
||||
ret = fdt_stringlist_search(fdt, off, "gpio-line-names",
|
||||
str);
|
||||
if (ret >= 0) {
|
||||
ft_fixup_fsa_gpio_name(fdt, off, fsa, ret,
|
||||
user_info.gpios[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* port expander GPIOs */
|
||||
off = fdt_subnode_offset(fdt, fsa_get_dtnode(fdt, fsa), "gpio@20");
|
||||
ft_fixup_fsa_gpio_name(fdt, off, fsa, user_info.gpios[i].offset,
|
||||
user_info.gpios[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_fsa_dev(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
struct fsa_user_info user_info;
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
/* list FSAs */
|
||||
printf("detecting FSA Adapters:\n");
|
||||
for (i = 1; i < FSA_MAX; i++) {
|
||||
if (!fsa_read_board_config(i, &board_info) &&
|
||||
!fsa_read_user_config(i, &user_info))
|
||||
printf("FSA%d : %s %s\n", i, board_info.model, user_info.desc);
|
||||
}
|
||||
} else {
|
||||
/* select FSA */
|
||||
fsa = simple_strtoul(argv[1], NULL, 10);
|
||||
}
|
||||
|
||||
if (fsa) {
|
||||
/* read FSA */
|
||||
if (!fsa_read_board_config(fsa, &board_info) &&
|
||||
!fsa_read_user_config(fsa, &user_info)) {
|
||||
printf("selected:\n");
|
||||
fsa_show_details(fsa, &board_info, &user_info);
|
||||
} else {
|
||||
printf("FSA%d not detected\n", fsa);
|
||||
fsa = 0;
|
||||
}
|
||||
} else {
|
||||
printf("no FSA currently selected\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_fsa_desc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
struct fsa_user_info user_info;
|
||||
|
||||
/* strip off leading cmd arg */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (!fsa) {
|
||||
printf("No FSA selected\n");
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (fsa_read_board_config(fsa, &board_info) || fsa_read_user_config(fsa, &user_info)) {
|
||||
printf("can't detect FSA%d\n", fsa);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
/* set */
|
||||
if (argc) {
|
||||
strlcpy(user_info.desc, argv[0], sizeof(user_info.desc));
|
||||
if (fsa_write_user_config(fsa, &user_info))
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
/* show */
|
||||
fsa_show_details(fsa, &board_info, &user_info);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int do_fsa_overlay(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
struct fsa_user_info user_info;
|
||||
|
||||
/* strip off leading cmd arg */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (!fsa) {
|
||||
printf("No FSA selected\n");
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (fsa_read_board_config(fsa, &board_info) || fsa_read_user_config(fsa, &user_info)) {
|
||||
printf("can't detect FSA%d\n", fsa);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
/* set */
|
||||
if (argc) {
|
||||
strlcpy(user_info.overlay, argv[0], sizeof(user_info.overlay));
|
||||
if (fsa_write_user_config(fsa, &user_info))
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
/* show */
|
||||
fsa_show_details(fsa, &board_info, &user_info);
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int do_fsa_gpio(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct fsa_board_info board_info;
|
||||
struct fsa_user_info user_info;
|
||||
struct fsa_gpio_desc desc;
|
||||
char str[64];
|
||||
int i, j;
|
||||
|
||||
/* strip off leading cmd arg */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (!fsa) {
|
||||
printf("No FSA selected\n");
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (fsa_read_board_config(fsa, &board_info) || fsa_read_user_config(fsa, &user_info)) {
|
||||
printf("can't detect FSA%d\n", fsa);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (!argc) {
|
||||
/* show all gpios */
|
||||
fsa_show_gpio_descs("\t", fsa, &board_info, &user_info);
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
if (!isdigit(argv[0][0])) {
|
||||
printf("invalid gpio offset: %s\n", argv[0]);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
i = simple_strtoul(argv[0], NULL, 10);
|
||||
|
||||
if (i >= 0 && i < board_info.sockgpios) {
|
||||
desc.offset = i;
|
||||
desc.source = 0xff;
|
||||
} else if (i >= board_info.sockgpios &&
|
||||
i < (board_info.sockgpios + board_info.ioexpgpios) &&
|
||||
fsa_gpiodevs[fsa]) {
|
||||
desc.offset = i - board_info.sockgpios;
|
||||
desc.source = 0x20;
|
||||
} else {
|
||||
printf("invalid index %d", i);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
if (user_info.gpios[i].config == FSA_GPIO_NC) {
|
||||
printf("can not alter NC gpio\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
strlcpy(desc.name, argv[1], sizeof(desc.name));
|
||||
if (!*desc.name) {
|
||||
printf("FSA%d %s erasing gpio %d\n", fsa, board_info.model, i);
|
||||
memset(&user_info.gpios[i], 0, sizeof(desc));
|
||||
if (fsa_write_user_config(fsa, &user_info))
|
||||
return CMD_RET_FAILURE;
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
}
|
||||
if (argc > 2) {
|
||||
if (user_info.gpios[i].config == FSA_GPIO_NC) {
|
||||
printf("can not alter NC gpio\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
for (j = 1; j < ARRAY_SIZE(fsa_gpio_config_names); j++) {
|
||||
if (!strcasecmp(argv[2], fsa_gpio_config_names[j])) {
|
||||
desc.config = j;
|
||||
break;
|
||||
}
|
||||
};
|
||||
if (j >= ARRAY_SIZE(fsa_gpio_config_names)) {
|
||||
printf("invalid config type '%s\n", argv[2]);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* show a specific gpio */
|
||||
if (argc == 1) {
|
||||
printf("FSA%d %s showing gpio %d\n", fsa, board_info.model, i);
|
||||
printf("%s\n", fsa_get_gpio_desc(&user_info.gpios[i], str, sizeof(str)));
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
/* set a specific gpio */
|
||||
else if (argc == 3) {
|
||||
printf("FSA%d %s updating gpio %d\n", fsa, board_info.model, i);
|
||||
memcpy(&user_info.gpios[i], &desc, sizeof(desc));
|
||||
if (fsa_write_user_config(fsa, &user_info))
|
||||
return CMD_RET_FAILURE;
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
static struct cmd_tbl cmd_fsa_sub[] = {
|
||||
U_BOOT_CMD_MKENT(dev, 1, 1, do_fsa_dev, "", ""),
|
||||
U_BOOT_CMD_MKENT(gpio, 4, 1, do_fsa_gpio, "", ""),
|
||||
U_BOOT_CMD_MKENT(description, 1, 1, do_fsa_desc, "", ""),
|
||||
U_BOOT_CMD_MKENT(overlay, 1, 1, do_fsa_overlay, "", ""),
|
||||
};
|
||||
|
||||
static int do_fsa(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct cmd_tbl *c;
|
||||
|
||||
/* strip off leading fsa arg */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
c = find_cmd_tbl(argv[0], cmd_fsa_sub, ARRAY_SIZE(cmd_fsa_sub));
|
||||
if (c)
|
||||
return c->cmd(cmdtp, flag, argc, argv);
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
U_BOOT_LONGHELP(fsa,
|
||||
"dev [dev] - show or set current FSA adapter\n"
|
||||
"fsa gpio - show current gpio descriptors\n"
|
||||
"fsa gpio [<offset>]|[<offset> <source>] - show a specific gpio descriptor\n"
|
||||
"fsa gpio [<offset> <name> <input|output-low|output-high> [source]] - set a gpio descriptor\n"
|
||||
"fsa description [description] - show or set the FSA user description string\n"
|
||||
"fsa overlay [overlay] - show or set the FSA overlay string\n"
|
||||
);
|
||||
|
||||
U_BOOT_CMD(fsa, 6, 1, do_fsa,
|
||||
"Flexible Socket Adapter",
|
||||
fsa_help_text
|
||||
);
|
||||
@@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2025 Gateworks Corporation
|
||||
*/
|
||||
|
||||
#ifndef _FSA_H_
|
||||
#define _FSA_H_
|
||||
|
||||
#define FSA_MAX 5
|
||||
|
||||
enum fsa_gpio_cfg {
|
||||
FSA_GPIO_NC,
|
||||
FSA_GPIO_UNCONFIGURED,
|
||||
FSA_GPIO_INPUT,
|
||||
FSA_GPIO_OUTPUT_LOW,
|
||||
FSA_GPIO_OUTPUT_HIGH,
|
||||
};
|
||||
|
||||
struct fsa_gpio_desc {
|
||||
u8 offset;
|
||||
u8 config;
|
||||
u8 source;
|
||||
char name[13];
|
||||
};
|
||||
|
||||
struct fsa_board_info {
|
||||
char model[16]; /* 0x00: model string */
|
||||
u8 mac[6]; /* 0x10: MAC base */
|
||||
u8 macno; /* 0x16: number of mac addrs */
|
||||
u8 resv1; /* 0x17: reserved */
|
||||
u32 serial; /* 0x18: Serial Number */
|
||||
u8 mfgdate[4]; /* 0x1c: MFG date */
|
||||
u8 sockgpios; /* 0x20: number of socket gpio descriptors */
|
||||
u8 ioexpgpios; /* 0x21: number of io expander gpio descriptors */
|
||||
u8 resv2[220]; /* 0x22: reserved */
|
||||
u8 chksum[2]; /* 0xfe: */
|
||||
};
|
||||
|
||||
struct fsa_user_info {
|
||||
char desc[32]; /* 0x000: user description */
|
||||
char overlay[16]; /* 0x020: dt-overlay suffice */
|
||||
struct fsa_gpio_desc gpios[20]; /* 0x030: gpio descriptors */
|
||||
u8 reserved[398]; /* 0x170: reserved */
|
||||
u8 chksum[2]; /* 0x2fe: */
|
||||
};
|
||||
|
||||
int fsa_init(void);
|
||||
int fsa_show(void);
|
||||
int fsa_ft_fixup(void *fdt);
|
||||
|
||||
#endif // _FSA_H_
|
||||
@@ -5,6 +5,7 @@
|
||||
#
|
||||
|
||||
obj-y += venice.o eeprom.o
|
||||
obj-y += ../fsa.o
|
||||
|
||||
ifdef CONFIG_XPL_BUILD
|
||||
obj-y += spl.o
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
#include <gsc.h>
|
||||
#include <hexdump.h>
|
||||
#include <i2c.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/uclass.h>
|
||||
|
||||
#include "eeprom.h"
|
||||
#include "../fsa.h"
|
||||
|
||||
/* I2C */
|
||||
#define SOM_EEPROM_BUSNO 0
|
||||
@@ -18,7 +20,8 @@
|
||||
|
||||
struct venice_board_info som_info;
|
||||
struct venice_board_info base_info;
|
||||
char venice_model[32];
|
||||
char venice_model[64];
|
||||
char venice_som_model[32];
|
||||
char venice_baseboard_model[32];
|
||||
u32 venice_serial;
|
||||
|
||||
@@ -107,7 +110,7 @@ static int eeprom_read(int busno, int slave, int alen, struct venice_board_info
|
||||
/* validate checksum */
|
||||
for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++)
|
||||
chksum += buf[i];
|
||||
if ((info->chksum[0] != chksum >> 8) ||
|
||||
if ((info->chksum[0] != ((chksum >> 8) & 0xff)) ||
|
||||
(info->chksum[1] != (chksum & 0xff))) {
|
||||
printf("EEPROM: I2C%d@0x%02x: Invalid Checksum\n", busno, slave);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, sizeof(*info));
|
||||
@@ -126,6 +129,54 @@ static int eeprom_read(int busno, int slave, int alen, struct venice_board_info
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsa_eeprom_read(const char *base, int fsa, struct fsa_board_info *info)
|
||||
{
|
||||
int i;
|
||||
int chksum;
|
||||
unsigned char *buf = (unsigned char *)info;
|
||||
struct udevice *dev, *bus;
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
/* probe mux */
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 2, &bus);
|
||||
if (!ret)
|
||||
ret = dm_i2c_probe(bus, 0x70, 0, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* steer mux */
|
||||
if (!strncmp(base, "GW82", 4)) {
|
||||
if (fsa < 3)
|
||||
reg = (fsa == 1) ? BIT(1) : BIT(0);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
dm_i2c_write(dev, 0x00, ®, 1);
|
||||
|
||||
/* get eeprom */
|
||||
ret = dm_i2c_probe(bus, 0x54, 0, &dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read eeprom config section */
|
||||
ret = dm_i2c_read(dev, 0x00, buf, sizeof(*info));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* validate checksum */
|
||||
for (chksum = 0, i = 0; i < (int)sizeof(*info) - 2; i++)
|
||||
chksum += buf[i];
|
||||
if ((info->chksum[0] != ((chksum >> 8) & 0xff)) ||
|
||||
(info->chksum[1] != (chksum & 0xff))) {
|
||||
printf("FSA%d EEPROM (board): %s: Invalid Checksum\n", fsa, dev->name);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, sizeof(*info));
|
||||
memset(info, 0, sizeof(*info));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* determine BOM revision from model */
|
||||
int get_bom_rev(const char *str)
|
||||
{
|
||||
@@ -299,6 +350,8 @@ static int eeprom_info(bool verbose)
|
||||
base_info.mfgdate[0], base_info.mfgdate[1],
|
||||
base_info.mfgdate[2], base_info.mfgdate[3]);
|
||||
}
|
||||
if (verbose)
|
||||
fsa_show();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -315,6 +368,7 @@ int venice_eeprom_init(int quiet)
|
||||
memset(&som_info, 0, sizeof(som_info));
|
||||
return 0;
|
||||
}
|
||||
strlcpy(venice_som_model, som_info.model, sizeof(venice_som_model));
|
||||
|
||||
/* read optional baseboard EEPROM */
|
||||
eeprom_read(BASEBOARD_EEPROM_BUSNO, BASEBOARD_EEPROM_ADDR, 2, &base_info);
|
||||
@@ -322,7 +376,7 @@ int venice_eeprom_init(int quiet)
|
||||
/* create model strings */
|
||||
if (base_info.model[0]) {
|
||||
sprintf(venice_model, "GW%c%c%c%c-%c%c-",
|
||||
som_info.model[2], /* family */
|
||||
base_info.model[2], /* family */
|
||||
base_info.model[3], /* baseboard */
|
||||
base_info.model[4], base_info.model[5], /* subload of baseboard */
|
||||
som_info.model[4], som_info.model[5]); /* last 2digits of SOM */
|
||||
@@ -347,9 +401,74 @@ int venice_eeprom_init(int quiet)
|
||||
}
|
||||
venice_serial = som_info.serial;
|
||||
|
||||
/* GW8xxx product family naming scheme */
|
||||
if (venice_model[2] == '8') {
|
||||
struct fsa_board_info fsa_info;
|
||||
int i = 0;
|
||||
int fsa;
|
||||
|
||||
/* baseboard */
|
||||
if (base_info.model[0]) {
|
||||
rev_pcb = get_pcb_rev(base_info.model);
|
||||
rev_bom = get_bom_rev(base_info.model);
|
||||
venice_model[i++] = 'G';
|
||||
venice_model[i++] = 'W';
|
||||
venice_model[i++] = base_info.model[2]; /* baseboard */
|
||||
venice_model[i++] = base_info.model[3];
|
||||
venice_model[i++] = base_info.model[4]; /* subload */
|
||||
venice_model[i++] = base_info.model[5];
|
||||
venice_model[i++] = rev_pcb;
|
||||
if (rev_bom)
|
||||
venice_model[i++] = rev_bom;
|
||||
venice_model[i++] = '-';
|
||||
venice_model[i++] = 'S';
|
||||
} else {
|
||||
venice_model[i++] = 'G';
|
||||
venice_model[i++] = 'W';
|
||||
}
|
||||
|
||||
/* som */
|
||||
rev_pcb = get_pcb_rev(som_info.model);
|
||||
rev_bom = get_bom_rev(som_info.model);
|
||||
venice_model[i++] = som_info.model[4];
|
||||
venice_model[i++] = som_info.model[5];
|
||||
venice_model[i++] = rev_pcb;
|
||||
if (rev_bom)
|
||||
venice_model[i++] = rev_bom;
|
||||
|
||||
/* fsa */
|
||||
for (fsa = 1; fsa < FSA_MAX; fsa++) {
|
||||
if (!fsa_eeprom_read(venice_model, fsa, &fsa_info)) {
|
||||
venice_model[i++] = '-';
|
||||
venice_model[i++] = 'F';
|
||||
venice_model[i++] = '0' + fsa;
|
||||
venice_model[i++] = fsa_info.model[5];
|
||||
venice_model[i++] = fsa_info.model[6];
|
||||
venice_model[i++] = fsa_info.model[8];
|
||||
if (fsa_info.model[9])
|
||||
venice_model[i++] = fsa_info.model[9];
|
||||
}
|
||||
}
|
||||
|
||||
/* append extra model info */
|
||||
if (som_info.config[0] >= 32 && som_info.config[0] < 0x7f) {
|
||||
venice_model[i++] = '-';
|
||||
strlcpy(venice_model + i, som_info.config, (sizeof(venice_model) - i) - 1);
|
||||
i += strlen(som_info.config);
|
||||
if (i >= sizeof(venice_model))
|
||||
i = sizeof(venice_model) - 1;
|
||||
}
|
||||
venice_model[i++] = 0;
|
||||
}
|
||||
|
||||
if (!quiet)
|
||||
eeprom_info(false);
|
||||
|
||||
if (!strncmp(venice_model, "GW7901-SP486", 12) &&
|
||||
strcmp(venice_model, "GW7901-SP486-C")) {
|
||||
return 2048;
|
||||
}
|
||||
|
||||
return (16 << som_info.sdram_size);
|
||||
}
|
||||
|
||||
@@ -363,6 +482,11 @@ const char *eeprom_get_model(void)
|
||||
return venice_model;
|
||||
}
|
||||
|
||||
const char *eeprom_get_som_model(void)
|
||||
{
|
||||
return venice_som_model;
|
||||
}
|
||||
|
||||
const char *eeprom_get_baseboard_model(void)
|
||||
{
|
||||
return venice_baseboard_model;
|
||||
|
||||
@@ -20,12 +20,13 @@ struct venice_board_info {
|
||||
u8 sdram_width; /* 0x2D: (8 << n) bit */
|
||||
u8 res3[2]; /* 0x2E */
|
||||
char model[16]; /* 0x30: model string */
|
||||
u8 res4[14]; /* 0x40 */
|
||||
u8 config[14]; /* 0x40: model config */
|
||||
u8 chksum[2]; /* 0x4E */
|
||||
};
|
||||
|
||||
int venice_eeprom_init(int quiet);
|
||||
const char *eeprom_get_model(void);
|
||||
const char *eeprom_get_som_model(void);
|
||||
const char *eeprom_get_baseboard_model(void);
|
||||
const char *eeprom_get_dtb_name(int level, char *buf, int len);
|
||||
int eeprom_getmac(int index, uint8_t *enetaddr);
|
||||
|
||||
@@ -6,18 +6,6 @@
|
||||
#ifndef __LPDDR4_TIMING_H__
|
||||
#define __LPDDR4_TIMING_H__
|
||||
|
||||
#ifdef CONFIG_IMX8MM
|
||||
extern struct dram_timing_info dram_timing_512mb;
|
||||
extern struct dram_timing_info dram_timing_1gb;
|
||||
extern struct dram_timing_info dram_timing_2gb;
|
||||
extern struct dram_timing_info dram_timing_4gb;
|
||||
#elif CONFIG_IMX8MN
|
||||
extern struct dram_timing_info dram_timing_1gb_single_die;
|
||||
extern struct dram_timing_info dram_timing_2gb_single_die;
|
||||
extern struct dram_timing_info dram_timing_2gb_dual_die;
|
||||
#elif CONFIG_IMX8MP
|
||||
extern struct dram_timing_info dram_timing_1gb_single_die;
|
||||
extern struct dram_timing_info dram_timing_4gb_dual_die;
|
||||
#endif
|
||||
extern struct dram_timing_info *spl_dram_init(const char *model, int sizemb);
|
||||
|
||||
#endif /* __LPDDR4_TIMING_H__ */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <string.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
#include <asm/arch/lpddr4_define.h>
|
||||
|
||||
@@ -1333,7 +1334,7 @@ static struct dram_cfg_param ddr_ddrc_cfg_512mb[] = {
|
||||
{ 0x3d400304, 0x1 },
|
||||
{ 0x3d400030, 0x1 },
|
||||
{ 0x3d400000, 0xa1080020 },
|
||||
{ 0x3d400020, 0x203 },
|
||||
{ 0x3d400020, 0x223 },
|
||||
{ 0x3d400024, 0x3a980 },
|
||||
{ 0x3d400064, 0x5b0062 },
|
||||
{ 0x3d4000d0, 0xc00305ba },
|
||||
@@ -1385,7 +1386,7 @@ static struct dram_cfg_param ddr_ddrc_cfg_512mb[] = {
|
||||
{ 0x3d400498, 0x620096 },
|
||||
{ 0x3d40049c, 0x1100e07 },
|
||||
{ 0x3d4004a0, 0xc8012c },
|
||||
{ 0x3d402020, 0x1 },
|
||||
{ 0x3d402020, 0x21 },
|
||||
{ 0x3d402024, 0x7d00 },
|
||||
{ 0x3d402050, 0x20d040 },
|
||||
{ 0x3d402064, 0xc000d },
|
||||
@@ -1410,7 +1411,7 @@ static struct dram_cfg_param ddr_ddrc_cfg_512mb[] = {
|
||||
{ 0x3d402194, 0x80303 },
|
||||
{ 0x3d4021b4, 0x100 },
|
||||
{ 0x3d4020f4, 0xc99 },
|
||||
{ 0x3d403020, 0x1 },
|
||||
{ 0x3d403020, 0x21 },
|
||||
{ 0x3d403024, 0x1f40 },
|
||||
{ 0x3d403050, 0x20d040 },
|
||||
{ 0x3d403064, 0x30004 },
|
||||
@@ -1459,9 +1460,9 @@ static struct dram_cfg_param ddr_ddrphy_cfg_512mb[] = {
|
||||
{ 0x120a0, 0x0 },
|
||||
{ 0x120a1, 0x1 },
|
||||
{ 0x120a2, 0x3 },
|
||||
{ 0x120a3, 0x4 },
|
||||
{ 0x120a3, 0x2 },
|
||||
{ 0x120a4, 0x5 },
|
||||
{ 0x120a5, 0x2 },
|
||||
{ 0x120a5, 0x4 },
|
||||
{ 0x120a6, 0x7 },
|
||||
{ 0x120a7, 0x6 },
|
||||
{ 0x130a0, 0x0 },
|
||||
@@ -1830,7 +1831,7 @@ static struct dram_fsp_msg ddr_dram_fsp_msg_512mb[] = {
|
||||
};
|
||||
|
||||
/* ddr timing config params */
|
||||
struct dram_timing_info dram_timing_512mb = {
|
||||
static struct dram_timing_info dram_timing_512mb = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_512mb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_512mb),
|
||||
.ddrphy_cfg = ddr_ddrphy_cfg_512mb,
|
||||
@@ -2489,7 +2490,7 @@ static struct dram_fsp_msg lpddr4_dram_fsp_msg_1gb[] = {
|
||||
};
|
||||
|
||||
/* lpddr4 timing config params */
|
||||
struct dram_timing_info dram_timing_1gb = {
|
||||
static struct dram_timing_info dram_timing_1gb = {
|
||||
.ddrc_cfg = lpddr4_ddrc_cfg_1gb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg_1gb),
|
||||
.ddrphy_cfg = lpddr4_ddrphy_cfg_1gb,
|
||||
@@ -3005,7 +3006,7 @@ static struct dram_fsp_msg lpddr4_dram_fsp_msg_4gb[] = {
|
||||
};
|
||||
|
||||
/* lpddr4 timing config params */
|
||||
struct dram_timing_info dram_timing_4gb = {
|
||||
static struct dram_timing_info dram_timing_4gb = {
|
||||
.ddrc_cfg = lpddr4_ddrc_cfg_4gb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg_4gb),
|
||||
.ddrphy_cfg = lpddr4_ddrphy_cfg_4gb,
|
||||
@@ -3140,12 +3141,12 @@ static struct dram_cfg_param lpddr4_ddrphy_cfg_2gb[] = {
|
||||
{ 0x100a7, 0x7 },
|
||||
{ 0x110a0, 0x0 },
|
||||
{ 0x110a1, 0x1 },
|
||||
{ 0x110a2, 0x2 },
|
||||
{ 0x110a3, 0x3 },
|
||||
{ 0x110a4, 0x4 },
|
||||
{ 0x110a5, 0x5 },
|
||||
{ 0x110a6, 0x6 },
|
||||
{ 0x110a7, 0x7 },
|
||||
{ 0x110a2, 0x3 },
|
||||
{ 0x110a3, 0x4 },
|
||||
{ 0x110a4, 0x5 },
|
||||
{ 0x110a5, 0x2 },
|
||||
{ 0x110a6, 0x7 },
|
||||
{ 0x110a7, 0x6 },
|
||||
{ 0x120a0, 0x0 },
|
||||
{ 0x120a1, 0x1 },
|
||||
{ 0x120a2, 0x3 },
|
||||
@@ -3156,12 +3157,12 @@ static struct dram_cfg_param lpddr4_ddrphy_cfg_2gb[] = {
|
||||
{ 0x120a7, 0x6 },
|
||||
{ 0x130a0, 0x0 },
|
||||
{ 0x130a1, 0x1 },
|
||||
{ 0x130a2, 0x5 },
|
||||
{ 0x130a3, 0x2 },
|
||||
{ 0x130a4, 0x3 },
|
||||
{ 0x130a5, 0x4 },
|
||||
{ 0x130a6, 0x7 },
|
||||
{ 0x130a7, 0x6 },
|
||||
{ 0x130a2, 0x2 },
|
||||
{ 0x130a3, 0x3 },
|
||||
{ 0x130a4, 0x4 },
|
||||
{ 0x130a5, 0x5 },
|
||||
{ 0x130a6, 0x6 },
|
||||
{ 0x130a7, 0x7 },
|
||||
{ 0x1005f, 0x1ff },
|
||||
{ 0x1015f, 0x1ff },
|
||||
{ 0x1105f, 0x1ff },
|
||||
@@ -3521,7 +3522,7 @@ static struct dram_fsp_msg lpddr4_dram_fsp_msg_2gb[] = {
|
||||
};
|
||||
|
||||
/* lpddr4 timing config params */
|
||||
struct dram_timing_info dram_timing_2gb = {
|
||||
static struct dram_timing_info dram_timing_2gb = {
|
||||
.ddrc_cfg = lpddr4_ddrc_cfg_2gb,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg_2gb),
|
||||
.ddrphy_cfg = lpddr4_ddrphy_cfg_2gb,
|
||||
@@ -3534,3 +3535,63 @@ struct dram_timing_info dram_timing_2gb = {
|
||||
.ddrphy_pie_num = ARRAY_SIZE(lpddr4_phy_pie),
|
||||
.fsp_table = { 3000, 400, 100, },
|
||||
};
|
||||
|
||||
static void apply_cfg_patch(struct dram_cfg_param *cfg, int cfg_sz,
|
||||
struct dram_cfg_param *patch, int patch_sz)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < cfg_sz; i++)
|
||||
for (j = 0; j < patch_sz; j++)
|
||||
if (cfg[i].reg == patch[j].reg)
|
||||
cfg[i].val = patch[j].val;
|
||||
}
|
||||
|
||||
static struct dram_cfg_param ddr_ddrc_cfg_alt_patch[] = {
|
||||
{ 0x3d400020, 0x203},
|
||||
{ 0x3d402020, 0x1},
|
||||
{ 0x3d403020, 0x1}
|
||||
};
|
||||
|
||||
static struct dram_cfg_param ddr_ddrphy_cfg_alt_patch[] = {
|
||||
{ 0x120a3, 0x4 },
|
||||
{ 0x120a5, 0x2 },
|
||||
};
|
||||
|
||||
struct dram_timing_info *spl_dram_init(const char *model, int sizemb)
|
||||
{
|
||||
struct dram_timing_info *dram_timing;
|
||||
|
||||
switch (sizemb) {
|
||||
case 512:
|
||||
dram_timing = &dram_timing_512mb;
|
||||
break;
|
||||
case 1024:
|
||||
dram_timing = &dram_timing_1gb;
|
||||
break;
|
||||
case 2048:
|
||||
dram_timing = &dram_timing_2gb;
|
||||
break;
|
||||
case 4096:
|
||||
dram_timing = &dram_timing_4gb;
|
||||
break;
|
||||
default:
|
||||
printf("unsupported");
|
||||
dram_timing = &dram_timing_1gb;
|
||||
}
|
||||
|
||||
/* apply ddrc/phy register changes for alternate dram bus layout */
|
||||
if (!strncmp(model, "GW7902", 6) ||
|
||||
!strncmp(model, "GW7903", 6) ||
|
||||
!strncmp(model, "GW7904", 6)) {
|
||||
apply_cfg_patch(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num,
|
||||
ddr_ddrc_cfg_alt_patch,
|
||||
ARRAY_SIZE(ddr_ddrc_cfg_alt_patch));
|
||||
|
||||
apply_cfg_patch(dram_timing->ddrphy_cfg, dram_timing->ddrphy_cfg_num,
|
||||
ddr_ddrphy_cfg_alt_patch,
|
||||
ARRAY_SIZE(ddr_ddrphy_cfg_alt_patch));
|
||||
}
|
||||
|
||||
return dram_timing;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <string.h>
|
||||
#include <asm/arch/ddr.h>
|
||||
|
||||
/*
|
||||
@@ -1425,7 +1426,7 @@ static struct dram_fsp_msg ddr_dram_fsp_msg_1gb_single_die[] = {
|
||||
};
|
||||
|
||||
/* ddr timing config params */
|
||||
struct dram_timing_info dram_timing_1gb_single_die = {
|
||||
static struct dram_timing_info dram_timing_1gb_single_die = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_1gb_single_die,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_1gb_single_die),
|
||||
.ddrphy_cfg = ddr_ddrphy_cfg_1gb_single_die,
|
||||
@@ -1890,7 +1891,7 @@ static struct dram_fsp_msg ddr_dram_fsp_msg_2gb_single_die[] = {
|
||||
};
|
||||
|
||||
/* ddr timing config params */
|
||||
struct dram_timing_info dram_timing_2gb_single_die = {
|
||||
static struct dram_timing_info dram_timing_2gb_single_die = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_2gb_single_die,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_2gb_single_die),
|
||||
.ddrphy_cfg = ddr_ddrphy_cfg_2gb_single_die,
|
||||
@@ -2354,7 +2355,7 @@ static struct dram_fsp_msg ddr_dram_fsp_msg_2gb_dual_die[] = {
|
||||
};
|
||||
|
||||
/* ddr timing config params */
|
||||
struct dram_timing_info dram_timing_2gb_dual_die = {
|
||||
static struct dram_timing_info dram_timing_2gb_dual_die = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_2gb_dual_die,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_2gb_dual_die),
|
||||
.ddrphy_cfg = ddr_ddrphy_cfg_2gb_dual_die,
|
||||
@@ -2367,3 +2368,27 @@ struct dram_timing_info dram_timing_2gb_dual_die = {
|
||||
.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
|
||||
.fsp_table = { 3200, 400, 100, },
|
||||
};
|
||||
|
||||
struct dram_timing_info *spl_dram_init(const char *model, int sizemb)
|
||||
{
|
||||
struct dram_timing_info *dram_timing;
|
||||
|
||||
switch (sizemb) {
|
||||
case 1024:
|
||||
dram_timing = &dram_timing_1gb_single_die;
|
||||
break;
|
||||
case 2048:
|
||||
if (!strcmp(model, "GW7902-SP466-A") ||
|
||||
!strcmp(model, "GW7902-SP466-B")) {
|
||||
dram_timing = &dram_timing_2gb_dual_die;
|
||||
} else {
|
||||
dram_timing = &dram_timing_2gb_single_die;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("unsupported");
|
||||
dram_timing = &dram_timing_2gb_dual_die;
|
||||
}
|
||||
|
||||
return dram_timing;
|
||||
}
|
||||
|
||||
@@ -1832,7 +1832,7 @@ struct dram_fsp_msg ddr_dram_fsp_msg_1gb_single_die[] = {
|
||||
};
|
||||
|
||||
/* ddr timing config params */
|
||||
struct dram_timing_info dram_timing_1gb_single_die = {
|
||||
static struct dram_timing_info dram_timing_1gb_single_die = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_1gb_single_die,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_1gb_single_die),
|
||||
.ddrphy_cfg = ddr_ddrphy_cfg_1gb_single_die,
|
||||
@@ -2364,7 +2364,7 @@ static struct dram_fsp_msg ddr_dram_fsp_msg_4gb_dual_die[] = {
|
||||
};
|
||||
|
||||
/* ddr timing config params */
|
||||
struct dram_timing_info dram_timing_4gb_dual_die = {
|
||||
static struct dram_timing_info dram_timing_4gb_dual_die = {
|
||||
.ddrc_cfg = ddr_ddrc_cfg_4gb_dual_die,
|
||||
.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_4gb_dual_die),
|
||||
.ddrphy_cfg = ddr_ddrphy_cfg_4gb_dual_die,
|
||||
@@ -2377,3 +2377,22 @@ struct dram_timing_info dram_timing_4gb_dual_die = {
|
||||
.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
|
||||
.fsp_table = { 4000, 400, 100, },
|
||||
};
|
||||
|
||||
struct dram_timing_info *spl_dram_init(const char *model, int sizemb)
|
||||
{
|
||||
struct dram_timing_info *dram_timing;
|
||||
|
||||
switch (sizemb) {
|
||||
case 1024:
|
||||
dram_timing = &dram_timing_1gb_single_die;
|
||||
break;
|
||||
case 4096:
|
||||
dram_timing = &dram_timing_4gb_dual_die;
|
||||
break;
|
||||
default:
|
||||
printf("unsupported");
|
||||
dram_timing = &dram_timing_4gb_dual_die;
|
||||
}
|
||||
|
||||
return dram_timing;
|
||||
}
|
||||
|
||||
@@ -32,69 +32,6 @@
|
||||
|
||||
#define PCIE_RSTN IMX_GPIO_NR(4, 6)
|
||||
|
||||
static void spl_dram_init(int size)
|
||||
{
|
||||
struct dram_timing_info *dram_timing;
|
||||
|
||||
switch (size) {
|
||||
#ifdef CONFIG_IMX8MM
|
||||
case 512:
|
||||
dram_timing = &dram_timing_512mb;
|
||||
break;
|
||||
case 1024:
|
||||
dram_timing = &dram_timing_1gb;
|
||||
break;
|
||||
case 2048:
|
||||
dram_timing = &dram_timing_2gb;
|
||||
break;
|
||||
case 4096:
|
||||
dram_timing = &dram_timing_4gb;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown DDR configuration: %d MiB\n", size);
|
||||
dram_timing = &dram_timing_1gb;
|
||||
size = 1024;
|
||||
#elif CONFIG_IMX8MN
|
||||
case 1024:
|
||||
dram_timing = &dram_timing_1gb_single_die;
|
||||
break;
|
||||
case 2048:
|
||||
if (!strcmp(eeprom_get_model(), "GW7902-SP466-A") ||
|
||||
!strcmp(eeprom_get_model(), "GW7902-SP466-B")) {
|
||||
dram_timing = &dram_timing_2gb_dual_die;
|
||||
} else {
|
||||
dram_timing = &dram_timing_2gb_single_die;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Unknown DDR configuration: %d MiB\n", size);
|
||||
dram_timing = &dram_timing_2gb_dual_die;
|
||||
size = 2048;
|
||||
#elif CONFIG_IMX8MP
|
||||
case 1024:
|
||||
dram_timing = &dram_timing_1gb_single_die;
|
||||
break;
|
||||
case 4096:
|
||||
dram_timing = &dram_timing_4gb_dual_die;
|
||||
break;
|
||||
default:
|
||||
printf("Unknown DDR configuration: %d GiB\n", size);
|
||||
dram_timing = &dram_timing_4gb_dual_die;
|
||||
size = 4096;
|
||||
#endif
|
||||
}
|
||||
|
||||
printf("DRAM : LPDDR4 ");
|
||||
if (size > 512)
|
||||
printf("%d GiB", size / 1024);
|
||||
else
|
||||
printf("%d MiB", size);
|
||||
printf(" %dMT/s %dMHz\n",
|
||||
dram_timing->fsp_msg[0].drate,
|
||||
dram_timing->fsp_msg[0].drate / 2);
|
||||
ddr_init(dram_timing);
|
||||
}
|
||||
|
||||
/*
|
||||
* Model specific PMIC adjustments necessary prior to DRAM init
|
||||
*
|
||||
@@ -118,21 +55,23 @@ static int dm_i2c_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
|
||||
return dm_i2c_write(dev, reg, &val, 1);
|
||||
}
|
||||
|
||||
static int power_init_board(struct udevice *gsc)
|
||||
static int power_init_board(const char *model, struct udevice *gsc)
|
||||
{
|
||||
const char *model = eeprom_get_model();
|
||||
const char *som = eeprom_get_som_model();
|
||||
struct udevice *bus;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
/* Enable GSC voltage supervisor for new board models */
|
||||
if ((!strncmp(model, "GW7100", 6) && model[10] > 'D') ||
|
||||
(!strncmp(model, "GW7101", 6) && model[10] > 'D') ||
|
||||
(!strncmp(model, "GW7200", 6) && model[10] > 'E') ||
|
||||
(!strncmp(model, "GW7201", 6) && model[10] > 'E') ||
|
||||
(!strncmp(model, "GW7300", 6) && model[10] > 'E') ||
|
||||
(!strncmp(model, "GW7301", 6) && model[10] > 'E') ||
|
||||
(!strncmp(model, "GW740", 5) && model[7] > 'B')) {
|
||||
/* Enable GSC voltage supervisor only for newew board models */
|
||||
if ((!strncmp(model, "GW7100", 6) && model[10] < 'E') ||
|
||||
(!strncmp(model, "GW7101", 6) && model[10] < 'E') ||
|
||||
(!strncmp(model, "GW7200", 6) && model[10] < 'F') ||
|
||||
(!strncmp(model, "GW7201", 6) && model[10] < 'F') ||
|
||||
(!strncmp(model, "GW7300", 6) && model[10] < 'F') ||
|
||||
(!strncmp(model, "GW7301", 6) && model[10] < 'F') ||
|
||||
(!strncmp(model, "GW740", 5) && model[7] < 'C')) {
|
||||
printf("GSC : voltage supervisor disabled\n");
|
||||
} else {
|
||||
u8 ver;
|
||||
|
||||
if (!dm_i2c_read(gsc, 14, &ver, 1) && ver > 62) {
|
||||
@@ -141,10 +80,7 @@ static int power_init_board(struct udevice *gsc)
|
||||
}
|
||||
}
|
||||
|
||||
if ((!strncmp(model, "GW71", 4)) ||
|
||||
(!strncmp(model, "GW72", 4)) ||
|
||||
(!strncmp(model, "GW73", 4)) ||
|
||||
(!strncmp(model, "GW75", 4))) {
|
||||
if (!strncmp(som, "GW70", 4)) {
|
||||
ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &bus);
|
||||
if (ret) {
|
||||
printf("PMIC : failed I2C1 probe: %d\n", ret);
|
||||
@@ -251,9 +187,11 @@ static int power_init_board(struct udevice *gsc)
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
struct dram_timing_info *dram_timing;
|
||||
struct udevice *bus, *dev;
|
||||
const char *model;
|
||||
int dram_szmb;
|
||||
int i, ret;
|
||||
int dram_sz;
|
||||
|
||||
arch_cpu_init();
|
||||
|
||||
@@ -311,13 +249,23 @@ void board_init_f(ulong dummy)
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
dram_sz = venice_eeprom_init(0);
|
||||
dram_szmb = venice_eeprom_init(0);
|
||||
model = eeprom_get_model();
|
||||
|
||||
/* PMIC */
|
||||
power_init_board(dev);
|
||||
power_init_board(model, dev);
|
||||
|
||||
/* DDR initialization */
|
||||
spl_dram_init(dram_sz);
|
||||
printf("DRAM : LPDDR4 ");
|
||||
if (dram_szmb > 512)
|
||||
printf("%d GiB", dram_szmb / 1024);
|
||||
else
|
||||
printf("%d MiB", dram_szmb);
|
||||
dram_timing = spl_dram_init(model, dram_szmb);
|
||||
printf(" %dMT/s %dMHz\n",
|
||||
dram_timing->fsp_msg[0].drate,
|
||||
dram_timing->fsp_msg[0].drate / 2);
|
||||
ddr_init(dram_timing);
|
||||
|
||||
board_init_r(NULL, 0);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <asm/mach-imx/boot_mode.h>
|
||||
|
||||
#include "eeprom.h"
|
||||
#include "../fsa.h"
|
||||
|
||||
int board_phys_sdram_size(phys_size_t *size)
|
||||
{
|
||||
@@ -76,6 +77,9 @@ int board_init(void)
|
||||
{
|
||||
venice_eeprom_init(1);
|
||||
|
||||
/* detect and configure FSA adapters */
|
||||
fsa_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -222,6 +226,9 @@ int ft_board_setup(void *fdt, struct bd_info *bd)
|
||||
/* set board model dt prop */
|
||||
fdt_setprop_string(fdt, 0, "board", eeprom_get_model());
|
||||
|
||||
/* fixups for FSA adapters */
|
||||
fsa_ft_fixup(fdt);
|
||||
|
||||
if (!strncmp(base_model, "GW73", 4)) {
|
||||
pcbrev = get_pcb_rev(base_model);
|
||||
path = fdt_get_alias(fdt, "ethernet1");
|
||||
|
||||
@@ -43,6 +43,8 @@ CONFIG_ENV_IS_IN_NAND=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_NO_NET=y
|
||||
CONFIG_BOUNCE_BUFFER=y
|
||||
CONFIG_CLK_COMPOSITE_CCF=y
|
||||
CONFIG_CLK_IMX6UL=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0x82000000
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_MX6=y
|
||||
CONFIG_TEXT_BASE=0x87800000
|
||||
CONFIG_SYS_MALLOC_LEN=0x1000000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x18000
|
||||
CONFIG_SPL_GPIO=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_NR_DRAM_BANKS=1
|
||||
CONFIG_ENV_SIZE=0x20000
|
||||
CONFIG_ENV_OFFSET=0x400000
|
||||
CONFIG_MX6ULL=y
|
||||
CONFIG_TARGET_MX6ULZ_SMM_M2=y
|
||||
CONFIG_BSH_M2B_MEMORY=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="nxp/imx/imx6ulz-bsh-smm-m2"
|
||||
CONFIG_SPL_SERIAL=y
|
||||
CONFIG_SPL_BSS_START_ADDR=0x84100000
|
||||
CONFIG_SPL=y
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_SIGNATURE=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_LEGACY_IMAGE_FORMAT=y
|
||||
CONFIG_DISTRO_DEFAULTS=y
|
||||
CONFIG_BOOTDELAY=3
|
||||
CONFIG_BOARD_LATE_INIT=y
|
||||
CONFIG_SPL_SYS_MALLOC=y
|
||||
CONFIG_SPL_DMA=y
|
||||
CONFIG_SPL_MTD=y
|
||||
CONFIG_SPL_NAND_SUPPORT=y
|
||||
CONFIG_SPL_WATCHDOG=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_SDP=y
|
||||
CONFIG_CMD_CACHE=y
|
||||
CONFIG_CMD_MTDPARTS=y
|
||||
CONFIG_MTDIDS_DEFAULT="nand0=gpmi-nand"
|
||||
CONFIG_MTDPARTS_DEFAULT="mtdparts=gpmi-nand:4m(nandboot),1m(env),8m(kernel),1m(nanddtb),-(rootfs)"
|
||||
CONFIG_CMD_UBI=y
|
||||
# CONFIG_ISO_PARTITION is not set
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_ENV_OVERWRITE=y
|
||||
CONFIG_ENV_IS_IN_NAND=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_NO_NET=y
|
||||
CONFIG_BOUNCE_BUFFER=y
|
||||
CONFIG_USB_FUNCTION_FASTBOOT=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0x82000000
|
||||
CONFIG_FASTBOOT_FLASH=y
|
||||
CONFIG_FASTBOOT_UUU_SUPPORT=y
|
||||
CONFIG_SYS_I2C_MXC=y
|
||||
# CONFIG_MMC is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_SYS_NAND_USE_FLASH_BBT=y
|
||||
CONFIG_NAND_MXS=y
|
||||
CONFIG_NAND_MXS_DT=y
|
||||
CONFIG_SYS_NAND_ONFI_DETECTION=y
|
||||
CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
|
||||
CONFIG_SYS_NAND_U_BOOT_OFFS=0x111400
|
||||
CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND=0x291400
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_IMX6=y
|
||||
CONFIG_DM_PMIC=y
|
||||
CONFIG_DM_REGULATOR=y
|
||||
CONFIG_DM_REGULATOR_FIXED=y
|
||||
CONFIG_MXC_UART=y
|
||||
CONFIG_IMX_THERMAL=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_SPL_USB_HOST=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_SPL_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="BSH"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
|
||||
CONFIG_CI_UDC=y
|
||||
CONFIG_SDP_LOADADDR=0x877fffc0
|
||||
CONFIG_SPL_USB_SDP_SUPPORT=y
|
||||
@@ -61,11 +61,16 @@ CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_GPT_RENAME=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_CAT=y
|
||||
CONFIG_CMD_SETEXPR_FMT=y
|
||||
CONFIG_CMD_XXD=y
|
||||
CONFIG_CMD_DHCP6=y
|
||||
CONFIG_CMD_TFTPPUT=y
|
||||
CONFIG_SYS_DISABLE_AUTOLOAD=y
|
||||
@@ -81,6 +86,7 @@ CONFIG_CMD_EXT4_WRITE=y
|
||||
# CONFIG_SPL_EFI_PARTITION is not set
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_OF_LIVE=y
|
||||
CONFIG_OF_LIST="freescale/imx8mm-venice-gw71xx-0x freescale/imx8mm-venice-gw72xx-0x freescale/imx8mm-venice-gw73xx-0x freescale/imx8mm-venice-gw7901 freescale/imx8mm-venice-gw7902 freescale/imx8mm-venice-gw7903 freescale/imx8mm-venice-gw7904 freescale/imx8mm-venice-gw75xx-0x"
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
|
||||
@@ -101,10 +107,14 @@ CONFIG_CLK_IMX8MM=y
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_GPIO_LOOKUP_LABEL=y
|
||||
CONFIG_MXC_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_I2C_MUX_PCA954x=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_BLINK=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_I2C_EEPROM=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_SPL_MMC_IO_VOLTAGE=y
|
||||
|
||||
@@ -62,10 +62,15 @@ CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_GPT_RENAME=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_USB_MASS_STORAGE=y
|
||||
CONFIG_CMD_CAT=y
|
||||
CONFIG_CMD_SETEXPR_FMT=y
|
||||
CONFIG_CMD_XXD=y
|
||||
CONFIG_CMD_DHCP6=y
|
||||
CONFIG_CMD_TFTPPUT=y
|
||||
CONFIG_SYS_DISABLE_AUTOLOAD=y
|
||||
@@ -81,6 +86,7 @@ CONFIG_CMD_EXT4_WRITE=y
|
||||
# CONFIG_SPL_EFI_PARTITION is not set
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_OF_LIVE=y
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
|
||||
CONFIG_SYS_MMC_ENV_DEV=2
|
||||
@@ -98,10 +104,14 @@ CONFIG_CLK_IMX8MN=y
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_GPIO_LOOKUP_LABEL=y
|
||||
CONFIG_MXC_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_I2C_MUX_PCA954x=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_BLINK=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_I2C_EEPROM=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_SPL_MMC_IO_VOLTAGE=y
|
||||
|
||||
@@ -64,10 +64,15 @@ CONFIG_CMD_MEMTEST=y
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_FUSE=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_GPT_RENAME=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_PCI=y
|
||||
CONFIG_CMD_USB=y
|
||||
CONFIG_CMD_CAT=y
|
||||
CONFIG_CMD_SETEXPR_FMT=y
|
||||
CONFIG_CMD_XXD=y
|
||||
CONFIG_CMD_DHCP6=y
|
||||
CONFIG_CMD_TFTPPUT=y
|
||||
CONFIG_SYS_DISABLE_AUTOLOAD=y
|
||||
@@ -83,7 +88,8 @@ CONFIG_CMD_EXT4_WRITE=y
|
||||
# CONFIG_SPL_EFI_PARTITION is not set
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_OF_LIST="freescale/imx8mp-venice-gw71xx-2x freescale/imx8mp-venice-gw72xx-2x freescale/imx8mp-venice-gw73xx-2x freescale/imx8mp-venice-gw74xx freescale/imx8mp-venice-gw75xx-2x"
|
||||
CONFIG_OF_LIVE=y
|
||||
CONFIG_OF_LIST="freescale/imx8mp-venice-gw71xx-2x freescale/imx8mp-venice-gw72xx-2x freescale/imx8mp-venice-gw73xx-2x freescale/imx8mp-venice-gw74xx freescale/imx8mp-venice-gw75xx-2x freescale/imx8mp-venice-gw82xx-2x"
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
|
||||
CONFIG_SYS_MMC_ENV_DEV=2
|
||||
@@ -99,10 +105,14 @@ CONFIG_CLK_IMX8MP=y
|
||||
CONFIG_GPIO_HOG=y
|
||||
CONFIG_DM_GPIO_LOOKUP_LABEL=y
|
||||
CONFIG_MXC_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_MUX=y
|
||||
CONFIG_I2C_MUX_PCA954x=y
|
||||
CONFIG_LED=y
|
||||
CONFIG_LED_BLINK=y
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_I2C_EEPROM=y
|
||||
CONFIG_SUPPORT_EMMC_BOOT=y
|
||||
CONFIG_MMC_IO_VOLTAGE=y
|
||||
CONFIG_MMC_UHS_SUPPORT=y
|
||||
|
||||
@@ -14,6 +14,14 @@ config CLK_IMX6Q
|
||||
help
|
||||
This enables DM/DTS support for clock driver in i.MX6Q platforms.
|
||||
|
||||
config CLK_IMX6UL
|
||||
bool "Clock support for i.MX6UL"
|
||||
depends on ARCH_MX6
|
||||
select CLK
|
||||
select CLK_CCF
|
||||
help
|
||||
This enables DM/DTS support for clock driver in i.MX6UL platforms.
|
||||
|
||||
config CLK_IMX8
|
||||
bool "Clock support for i.MX8"
|
||||
depends on ARCH_IMX8
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk-gate2.o clk-pllv3.o clk-pfd.o
|
||||
obj-$(CONFIG_$(PHASE_)CLK_IMX6Q) += clk-imx6q.o
|
||||
obj-$(CONFIG_$(PHASE_)CLK_IMX6UL) += clk-imx6ul.o
|
||||
obj-$(CONFIG_CLK_IMX8) += clk-imx8.o
|
||||
|
||||
ifdef CONFIG_CLK_IMX8
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2025 Amarula Solutions Software Engineering
|
||||
* Michael Trimarchi, Amarula Solutions Software Engineering, michael@amarulasolutions.com
|
||||
*/
|
||||
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <dt-bindings/clock/imx6ul-clock.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
||||
static int imx6ul_clk_request(struct clk *clk)
|
||||
{
|
||||
debug("%s: request clk id %ld\n", __func__, clk->id);
|
||||
|
||||
if (clk->id < IMX6UL_CLK_DUMMY || clk->id >= IMX6UL_CLK_END) {
|
||||
printf("%s: Invalid clk ID #%lu\n", __func__, clk->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_ops imx6ul_clk_ops = {
|
||||
.request = imx6ul_clk_request,
|
||||
.set_rate = ccf_clk_set_rate,
|
||||
.get_rate = ccf_clk_get_rate,
|
||||
.enable = ccf_clk_enable,
|
||||
.disable = ccf_clk_disable,
|
||||
};
|
||||
|
||||
static const char *const pll_bypass_src_sels[] = { "osc", "dummy", };
|
||||
static const char *const pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
|
||||
static const char *const bch_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
static const char *const gpmi_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
|
||||
static const char *const enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m",
|
||||
"pll3_pfd3_454m", "dummy", "dummy", "dummy", };
|
||||
static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
|
||||
static const char *const periph_sels[] = { "periph_pre", "periph_clk2", };
|
||||
static const char *const periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m",
|
||||
"pll4_audio_div", };
|
||||
static const char *const periph_clk2_sels[] = { "pll3_usb_otg", "osc", "pll2_bypass_src", };
|
||||
static const char *const periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
|
||||
static const char *const perclk_sels[] = { "ipg", "osc", };
|
||||
|
||||
static const char *const periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m",
|
||||
"pll2_198m", };
|
||||
static const char *const uart_sels[] = { "pll3_80m", "osc", };
|
||||
static const char *const ecspi_sels[] = { "pll3_60m", "osc", };
|
||||
|
||||
static int imx6ul_clk_probe(struct udevice *dev)
|
||||
{
|
||||
struct clk osc_clk;
|
||||
void *base;
|
||||
int ret;
|
||||
|
||||
/* Anatop clocks */
|
||||
base = (void *)ANATOP_BASE_ADDR;
|
||||
|
||||
clk_dm(IMX6UL_CLK_DUMMY, clk_register_fixed_rate(NULL, "dummy", 0));
|
||||
|
||||
ret = clk_get_by_name(dev, "osc", &osc_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_dm(IMX6UL_CLK_OSC, dev_get_clk_ptr(osc_clk.dev));
|
||||
|
||||
clk_dm(IMX6UL_CLK_PLL2,
|
||||
imx_clk_pllv3(dev, IMX_PLLV3_GENERIC, "pll2_bus", "osc",
|
||||
base + 0x30, 0x1));
|
||||
clk_dm(IMX6UL_CLK_PLL3,
|
||||
imx_clk_pllv3(dev, IMX_PLLV3_USB, "pll3", "osc",
|
||||
base + 0x10, 0x3));
|
||||
clk_dm(IMX6UL_PLL3_BYPASS_SRC,
|
||||
imx_clk_mux(dev, "pll3_bypass_src", base + 0x10, 14, 1,
|
||||
pll_bypass_src_sels,
|
||||
ARRAY_SIZE(pll_bypass_src_sels)));
|
||||
clk_dm(IMX6UL_PLL3_BYPASS,
|
||||
imx_clk_mux_flags(dev, "pll3_bypass", base + 0x10, 16, 1,
|
||||
pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels),
|
||||
CLK_SET_RATE_PARENT));
|
||||
clk_dm(IMX6UL_CLK_PLL3_USB_OTG,
|
||||
imx_clk_gate(dev, "pll3_usb_otg", "pll3_bypass", base + 0x10,
|
||||
13));
|
||||
clk_dm(IMX6UL_CLK_PLL3_80M,
|
||||
imx_clk_fixed_factor(dev, "pll3_80m", "pll3_usb_otg", 1, 6));
|
||||
clk_dm(IMX6UL_CLK_PLL3_60M,
|
||||
imx_clk_fixed_factor(dev, "pll3_60m", "pll3_usb_otg", 1, 8));
|
||||
clk_dm(IMX6UL_CLK_PLL2_PFD0,
|
||||
imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0));
|
||||
clk_dm(IMX6UL_CLK_PLL2_PFD1,
|
||||
imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1));
|
||||
clk_dm(IMX6UL_CLK_PLL2_PFD2,
|
||||
imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2));
|
||||
clk_dm(IMX6UL_CLK_PLL2_PFD3,
|
||||
imx_clk_pfd("pll2_pfd3_396m", "pll2_bus", base + 0x100, 3));
|
||||
clk_dm(IMX6UL_CLK_PLL6,
|
||||
imx_clk_pllv3(dev, IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0,
|
||||
0x3));
|
||||
clk_dm(IMX6UL_CLK_PLL6_ENET,
|
||||
imx_clk_gate(dev, "pll6_enet", "pll6", base + 0xe0, 13));
|
||||
|
||||
/* CCM clocks */
|
||||
base = dev_read_addr_ptr(dev);
|
||||
if (!base)
|
||||
return -EINVAL;
|
||||
|
||||
clk_dm(IMX6UL_CLK_GPMI_SEL,
|
||||
imx_clk_mux(dev, "gpmi_sel", base + 0x1c, 19, 1, gpmi_sels,
|
||||
ARRAY_SIZE(gpmi_sels)));
|
||||
clk_dm(IMX6UL_CLK_BCH_SEL,
|
||||
imx_clk_mux(dev, "bch_sel", base + 0x1c, 18, 1, bch_sels,
|
||||
ARRAY_SIZE(bch_sels)));
|
||||
clk_dm(IMX6UL_CLK_USDHC1_SEL,
|
||||
imx_clk_mux(dev, "usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels,
|
||||
ARRAY_SIZE(usdhc_sels)));
|
||||
clk_dm(IMX6UL_CLK_USDHC2_SEL,
|
||||
imx_clk_mux(dev, "usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels,
|
||||
ARRAY_SIZE(usdhc_sels)));
|
||||
clk_dm(IMX6UL_CLK_ECSPI_SEL,
|
||||
imx_clk_mux(dev, "ecspi_sel", base + 0x38, 18, 1, ecspi_sels,
|
||||
ARRAY_SIZE(ecspi_sels)));
|
||||
clk_dm(IMX6UL_CLK_UART_SEL,
|
||||
imx_clk_mux(dev, "uart_sel", base + 0x24, 6, 1, uart_sels,
|
||||
ARRAY_SIZE(uart_sels)));
|
||||
clk_dm(IMX6UL_CLK_ENFC_SEL,
|
||||
imx_clk_mux(dev, "enfc_sel", base + 0x2c, 15, 3, enfc_sels,
|
||||
ARRAY_SIZE(enfc_sels)));
|
||||
clk_dm(IMX6UL_CLK_PERCLK_SEL,
|
||||
imx_clk_mux(dev, "perclk_sel", base + 0x1c, 6, 1, perclk_sels,
|
||||
ARRAY_SIZE(perclk_sels)));
|
||||
clk_dm(IMX6UL_CLK_PERIPH_PRE,
|
||||
imx_clk_mux(dev, "periph_pre", base + 0x18, 18, 2,
|
||||
periph_pre_sels, ARRAY_SIZE(periph_pre_sels)));
|
||||
clk_dm(IMX6UL_CLK_PERIPH2_PRE,
|
||||
imx_clk_mux(dev, "periph2_pre", base + 0x18, 21, 2,
|
||||
periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels)));
|
||||
clk_dm(IMX6UL_CLK_PERIPH_CLK2_SEL,
|
||||
imx_clk_mux(dev, "periph_clk2_sel", base + 0x18, 12, 2,
|
||||
periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels)));
|
||||
clk_dm(IMX6UL_CLK_PERIPH2_CLK2_SEL,
|
||||
imx_clk_mux(dev, "periph2_clk2_sel", base + 0x18, 20, 1,
|
||||
periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels)));
|
||||
clk_dm(IMX6UL_CLK_PERIPH,
|
||||
imx_clk_busy_mux(dev, "periph", base + 0x14, 25, 1, base + 0x48,
|
||||
5, periph_sels, ARRAY_SIZE(periph_sels)));
|
||||
clk_dm(IMX6UL_CLK_AHB,
|
||||
imx_clk_busy_divider(dev, "ahb", "periph", base + 0x14, 10, 3,
|
||||
base + 0x48, 1));
|
||||
clk_dm(IMX6UL_CLK_PERIPH_CLK2,
|
||||
imx_clk_divider(dev, "periph_clk2", "periph_clk2_sel",
|
||||
base + 0x14, 27, 3));
|
||||
clk_dm(IMX6UL_CLK_PERIPH2_CLK2,
|
||||
imx_clk_divider(dev, "periph2_clk2", "periph2_clk2_sel",
|
||||
base + 0x14, 0, 3));
|
||||
clk_dm(IMX6UL_CLK_IPG,
|
||||
imx_clk_divider(dev, "ipg", "ahb", base + 0x14, 8, 2));
|
||||
clk_dm(IMX6UL_CLK_ENFC_PRED,
|
||||
imx_clk_divider(dev, "enfc_pred", "enfc_sel", base + 0x2c, 18,
|
||||
3));
|
||||
clk_dm(IMX6UL_CLK_ENFC_PODF,
|
||||
imx_clk_divider(dev, "enfc_podf", "enfc_pred", base + 0x2c, 21,
|
||||
6));
|
||||
clk_dm(IMX6UL_CLK_GPMI_PODF,
|
||||
imx_clk_divider(dev, "gpmi_podf", "gpmi_sel", base + 0x24, 22,
|
||||
3));
|
||||
clk_dm(IMX6UL_CLK_BCH_PODF,
|
||||
imx_clk_divider(dev, "bch_podf", "bch_sel", base + 0x24, 19, 3));
|
||||
clk_dm(IMX6UL_CLK_PERCLK,
|
||||
imx_clk_divider(dev, "perclk", "perclk_sel", base + 0x1c, 0, 6));
|
||||
clk_dm(IMX6UL_CLK_UART_PODF,
|
||||
imx_clk_divider(dev, "uart_podf", "uart_sel", base + 0x24, 0,
|
||||
6));
|
||||
clk_dm(IMX6UL_CLK_USDHC1_PODF,
|
||||
imx_clk_divider(dev, "usdhc1_podf", "usdhc1_sel", base + 0x24,
|
||||
11, 3));
|
||||
clk_dm(IMX6UL_CLK_USDHC2_PODF,
|
||||
imx_clk_divider(dev, "usdhc2_podf", "usdhc2_sel", base + 0x24,
|
||||
16, 3));
|
||||
clk_dm(IMX6UL_CLK_ECSPI_PODF,
|
||||
imx_clk_divider(dev, "ecspi_podf", "ecspi_sel", base + 0x38, 19,
|
||||
6));
|
||||
|
||||
clk_dm(IMX6UL_CLK_APBHDMA,
|
||||
imx_clk_gate2(dev, "apbh_dma", "bch_podf", base + 0x68, 4));
|
||||
clk_dm(IMX6UL_CLK_ECSPI1,
|
||||
imx_clk_gate2(dev, "ecspi1", "ecspi_podf", base + 0x6c, 0));
|
||||
clk_dm(IMX6UL_CLK_ECSPI2,
|
||||
imx_clk_gate2(dev, "ecspi2", "ecspi_podf", base + 0x6c, 2));
|
||||
clk_dm(IMX6UL_CLK_ECSPI3,
|
||||
imx_clk_gate2(dev, "ecspi3", "ecspi_podf", base + 0x6c, 4));
|
||||
clk_dm(IMX6UL_CLK_ECSPI4,
|
||||
imx_clk_gate2(dev, "ecspi4", "ecspi_podf", base + 0x6c, 6));
|
||||
|
||||
clk_dm(IMX6UL_CLK_USBOH3,
|
||||
imx_clk_gate2(dev, "usboh3", "ipg", base + 0x80, 0));
|
||||
clk_dm(IMX6UL_CLK_USDHC1,
|
||||
imx_clk_gate2(dev, "usdhc1", "usdhc1_podf", base + 0x80, 2));
|
||||
clk_dm(IMX6UL_CLK_USDHC2,
|
||||
imx_clk_gate2(dev, "usdhc2", "usdhc2_podf", base + 0x80, 4));
|
||||
|
||||
clk_dm(IMX6UL_CLK_UART1_IPG,
|
||||
imx_clk_gate2(dev, "uart1_ipg", "ipg", base + 0x7c, 24));
|
||||
clk_dm(IMX6UL_CLK_UART1_SERIAL,
|
||||
imx_clk_gate2(dev, "uart1_serial", "uart_podf", base + 0x7c, 24));
|
||||
clk_dm(IMX6UL_CLK_UART2_IPG,
|
||||
imx_clk_gate2(dev, "uart2_ipg", "ipg", base + 0x68, 28));
|
||||
clk_dm(IMX6UL_CLK_UART2_SERIAL,
|
||||
imx_clk_gate2(dev, "uart2_serial", "uart_podf", base + 0x68, 28));
|
||||
clk_dm(IMX6UL_CLK_UART3_IPG,
|
||||
imx_clk_gate2(dev, "uart3_ipg", "ipg", base + 0x6c, 10));
|
||||
clk_dm(IMX6UL_CLK_UART3_SERIAL,
|
||||
imx_clk_gate2(dev, "uart3_serial", "uart_podf", base + 0x6c, 10));
|
||||
clk_dm(IMX6UL_CLK_UART4_IPG,
|
||||
imx_clk_gate2(dev, "uart4_ipg", "ipg", base + 0x6c, 24));
|
||||
clk_dm(IMX6UL_CLK_UART4_SERIAL,
|
||||
imx_clk_gate2(dev, "uart4_serial", "uart_podf", base + 0x6c, 24));
|
||||
clk_dm(IMX6UL_CLK_UART5_IPG,
|
||||
imx_clk_gate2(dev, "uart5_ipg", "ipg", base + 0x74, 2));
|
||||
clk_dm(IMX6UL_CLK_UART5_SERIAL,
|
||||
imx_clk_gate2(dev, "uart5_serial", "uart_podf", base + 0x74, 2));
|
||||
clk_dm(IMX6UL_CLK_UART6_IPG,
|
||||
imx_clk_gate2(dev, "uart6_ipg", "ipg", base + 0x74, 6));
|
||||
clk_dm(IMX6UL_CLK_UART6_SERIAL,
|
||||
imx_clk_gate2(dev, "uart6_serial", "uart_podf", base + 0x74, 6));
|
||||
clk_dm(IMX6UL_CLK_UART7_IPG,
|
||||
imx_clk_gate2(dev, "uart7_ipg", "ipg", base + 0x7c, 26));
|
||||
clk_dm(IMX6UL_CLK_UART7_SERIAL,
|
||||
imx_clk_gate2(dev, "uart7_serial", "uart_podf", base + 0x7c, 26));
|
||||
clk_dm(IMX6UL_CLK_UART8_IPG,
|
||||
imx_clk_gate2(dev, "uart8_ipg", "ipg", base + 0x80, 14));
|
||||
clk_dm(IMX6UL_CLK_UART8_SERIAL,
|
||||
imx_clk_gate2(dev, "uart8_serial", "uart_podf", base + 0x80, 14));
|
||||
|
||||
#if CONFIG_IS_ENABLED(NAND_MXS)
|
||||
clk_dm(IMX6UL_CLK_PER_BCH,
|
||||
imx_clk_gate2(dev, "per_bch", "bch_podf", base + 0x78, 12));
|
||||
clk_dm(IMX6UL_CLK_GPMI_BCH_APB,
|
||||
imx_clk_gate2(dev, "gpmi_bch_apb", "bch_podf", base + 0x78, 24));
|
||||
clk_dm(IMX6UL_CLK_GPMI_BCH,
|
||||
imx_clk_gate2(dev, "gpmi_bch", "gpmi_podf", base + 0x78, 26));
|
||||
clk_dm(IMX6UL_CLK_GPMI_IO,
|
||||
imx_clk_gate2(dev, "gpmi_io", "enfc_podf", base + 0x78, 28));
|
||||
clk_dm(IMX6UL_CLK_GPMI_APB,
|
||||
imx_clk_gate2(dev, "gpmi_apb", "bch_podf", base + 0x78, 30));
|
||||
#endif
|
||||
|
||||
clk_dm(IMX6UL_CLK_I2C1,
|
||||
imx_clk_gate2(dev, "i2c1", "perclk", base + 0x70, 6));
|
||||
clk_dm(IMX6UL_CLK_I2C2,
|
||||
imx_clk_gate2(dev, "i2c2", "perclk", base + 0x70, 8));
|
||||
clk_dm(IMX6UL_CLK_I2C3,
|
||||
imx_clk_gate2(dev, "i2c3", "perclk", base + 0x70, 10));
|
||||
clk_dm(IMX6UL_CLK_PWM1,
|
||||
imx_clk_gate2(dev, "pwm1", "perclk", base + 0x78, 16));
|
||||
|
||||
clk_dm(IMX6UL_CLK_ENET,
|
||||
imx_clk_gate2(dev, "enet", "ipg", base + 0x6c, 10));
|
||||
clk_dm(IMX6UL_CLK_ENET_REF,
|
||||
imx_clk_fixed_factor(dev, "enet_ref", "pll6_enet", 1, 1));
|
||||
|
||||
struct clk *clk, *clk1;
|
||||
|
||||
clk_get_by_id(IMX6UL_CLK_ENFC_SEL, &clk);
|
||||
clk_get_by_id(IMX6UL_CLK_PLL2_PFD2, &clk1);
|
||||
|
||||
clk_set_parent(clk, clk1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id imx6ul_clk_ids[] = {
|
||||
{ .compatible = "fsl,imx6ul-ccm" },
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(imx6ul_clk) = {
|
||||
.name = "clk_imx6ul",
|
||||
.id = UCLASS_CLK,
|
||||
.of_match = imx6ul_clk_ids,
|
||||
.ops = &imx6ul_clk_ops,
|
||||
.probe = imx6ul_clk_probe,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
@@ -1507,8 +1507,18 @@ static void mxs_compute_timings(struct nand_chip *chip,
|
||||
writel(GPMI_CTRL1_CLEAR_MASK, &nand_info->gpmi_regs->hw_gpmi_ctrl1_clr);
|
||||
writel(ctrl1n, &nand_info->gpmi_regs->hw_gpmi_ctrl1_set);
|
||||
|
||||
/* Clock dividers do NOT guarantee a clean clock signal on its output
|
||||
* during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8,
|
||||
* all clock dividers provide these guarantee.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_MX6ULL))
|
||||
clk_disable(nand_info->gpmi_clk);
|
||||
|
||||
clk_set_rate(nand_info->gpmi_clk, clk_rate);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MX6ULL))
|
||||
clk_enable(nand_info->gpmi_clk);
|
||||
|
||||
/* Wait 64 clock cycles before using the GPMI after enabling the DLL */
|
||||
dll_wait_time_us = USEC_PER_SEC / clk_rate * 64;
|
||||
if (!dll_wait_time_us)
|
||||
|
||||
@@ -99,10 +99,8 @@ static int mxs_nand_dt_probe(struct udevice *dev)
|
||||
info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
|
||||
|
||||
if (IS_ENABLED(CONFIG_CLK) &&
|
||||
(IS_ENABLED(CONFIG_IMX8) || IS_ENABLED(CONFIG_IMX8M))) {
|
||||
/* Assigned clock already set clock */
|
||||
struct clk gpmi_clk;
|
||||
|
||||
(IS_ENABLED(CONFIG_IMX8) || IS_ENABLED(CONFIG_IMX8M) || IS_ENABLED(CONFIG_MX6ULL))) {
|
||||
struct clk_bulk clk_bulk;
|
||||
info->gpmi_clk = devm_clk_get(dev, "gpmi_io");
|
||||
|
||||
if (IS_ERR(info->gpmi_clk)) {
|
||||
@@ -111,47 +109,11 @@ static int mxs_nand_dt_probe(struct udevice *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(info->gpmi_clk);
|
||||
ret = clk_get_bulk(dev, &clk_bulk);
|
||||
if (!ret)
|
||||
ret = clk_enable_bulk(&clk_bulk);
|
||||
if (ret < 0) {
|
||||
debug("Can't enable gpmi io clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_IMX8)) {
|
||||
ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk);
|
||||
if (ret < 0) {
|
||||
debug("Can't get gpmi_apb clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&gpmi_clk);
|
||||
if (ret < 0) {
|
||||
debug("Can't enable gpmi_apb clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk);
|
||||
if (ret < 0) {
|
||||
debug("Can't get gpmi_bch clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&gpmi_clk);
|
||||
if (ret < 0) {
|
||||
debug("Can't enable gpmi_bch clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "gpmi_bch_apb", &gpmi_clk);
|
||||
if (ret < 0) {
|
||||
debug("Can't get gpmi_bch_apb clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_enable(&gpmi_clk);
|
||||
if (ret < 0) {
|
||||
debug("Can't enable gpmi_bch_apb clk: %d\n", ret);
|
||||
debug("Can't enable gpmi clks: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user