mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-04 20:26:13 +02:00
Merge tag 'qcom-for-2026.01-rc2' of https://source.denx.de/u-boot/custodians/u-boot-snapdragon
A variety of Qualcomm features/fixes for this cycle, notably with a few
new platforms gaining support:
* Initial support for SDM670 (similar to SDM845), SM6350, and SM7150
platforms is added
* USB and UART issues on MSM8916 are addressed (improving stability/
reliability)
* Firmware loading is implemented for the GENI serial engine, this is
used on some platforms to load firmware for i2c/spi/uart to work
Some additional patches like binman support for building MBN files still
need some additional work.
CI: 8ef6ac07b3/pipelines
This commit is contained in:
commit
08bf42e1fa
@ -9,12 +9,3 @@
|
||||
reg = <0 0x80000000 0 0x40000000>;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* When running as a first-stage bootloader, we need to re-configure the UART pins
|
||||
* because SBL de-initialises them. Indicate that the UART pins should be configured
|
||||
* during all boot stages.
|
||||
*/
|
||||
&blsp_uart2_console_default {
|
||||
bootph-all;
|
||||
};
|
||||
|
||||
5
board/qualcomm/debug-msm8953.config
Normal file
5
board/qualcomm/debug-msm8953.config
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
CONFIG_DEBUG_UART_BASE=0x78af000
|
||||
CONFIG_DEBUG_UART_MSM=y
|
||||
CONFIG_DEBUG_UART_CLOCK=7372800
|
||||
5
board/qualcomm/debug-qcm6490.config
Normal file
5
board/qualcomm/debug-qcm6490.config
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
CONFIG_DEBUG_UART_BASE=0x994000
|
||||
CONFIG_DEBUG_UART_MSM_GENI=y
|
||||
CONFIG_DEBUG_UART_CLOCK=14745600
|
||||
5
board/qualcomm/debug-qcs9100.config
Normal file
5
board/qualcomm/debug-qcs9100.config
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
CONFIG_DEBUG_UART_BASE=0xA8C000
|
||||
CONFIG_DEBUG_UART_MSM_GENI=y
|
||||
CONFIG_DEBUG_UART_CLOCK=14745600
|
||||
5
board/qualcomm/debug-sm6350.config
Normal file
5
board/qualcomm/debug-sm6350.config
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
CONFIG_DEBUG_UART_BASE=0x98c000
|
||||
CONFIG_DEBUG_UART_MSM_GENI=y
|
||||
CONFIG_DEBUG_UART_CLOCK=14745600
|
||||
@ -8,12 +8,6 @@
|
||||
# Otherwise buildman thinks this isn't an ARM platform
|
||||
CONFIG_ARM=y
|
||||
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
CONFIG_DEBUG_UART_BASE=0x994000
|
||||
CONFIG_DEBUG_UART_MSM_GENI=y
|
||||
CONFIG_DEBUG_UART_CLOCK=14745600
|
||||
|
||||
# Address where U-Boot will be loaded
|
||||
CONFIG_TEXT_BASE=0x9fc00000
|
||||
CONFIG_REMAKE_ELF=y
|
||||
|
||||
@ -29,6 +29,8 @@ CONFIG_CMD_EEPROM=y
|
||||
CONFIG_SYS_I2C_EEPROM_BUS=2
|
||||
CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2
|
||||
CONFIG_SYS_EEPROM_PAGE_WRITE_BITS=5
|
||||
CONFIG_CMD_MEMINFO=y
|
||||
CONFIG_CMD_MEMINFO_MAP=y
|
||||
# CONFIG_CMD_BIND is not set
|
||||
CONFIG_CMD_CLK=y
|
||||
CONFIG_CMD_DFU=y
|
||||
@ -44,6 +46,7 @@ CONFIG_CMD_EFIDEBUG=y
|
||||
CONFIG_CMD_RNG=y
|
||||
CONFIG_CMD_REGULATOR=y
|
||||
CONFIG_CMD_LOG=y
|
||||
CONFIG_CMD_WDT=y
|
||||
CONFIG_OF_LIVE=y
|
||||
CONFIG_OF_UPSTREAM_BUILD_VENDOR=y
|
||||
CONFIG_ENV_USE_DEFAULT_ENV_TEXT_FILE=y
|
||||
@ -60,6 +63,8 @@ CONFIG_CLK_QCOM_QCS8300=y
|
||||
CONFIG_CLK_QCOM_SA8775P=y
|
||||
CONFIG_CLK_QCOM_SDM845=y
|
||||
CONFIG_CLK_QCOM_SM6115=y
|
||||
CONFIG_CLK_QCOM_SM6350=y
|
||||
CONFIG_CLK_QCOM_SM7150=y
|
||||
CONFIG_CLK_QCOM_SM8150=y
|
||||
CONFIG_CLK_QCOM_SM8250=y
|
||||
CONFIG_CLK_QCOM_SM8550=y
|
||||
@ -86,6 +91,7 @@ CONFIG_IOMMU=y
|
||||
CONFIG_QCOM_HYP_SMMU=y
|
||||
CONFIG_MISC=y
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_QCOM_GENI=y
|
||||
CONFIG_I2C_EEPROM=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ADMA=y
|
||||
@ -110,8 +116,12 @@ CONFIG_PINCTRL_QCOM_QCM2290=y
|
||||
CONFIG_PINCTRL_QCOM_QCS404=y
|
||||
CONFIG_PINCTRL_QCOM_SA8775P=y
|
||||
CONFIG_PINCTRL_QCOM_SC7280=y
|
||||
CONFIG_PINCTRL_QCOM_SDM660=y
|
||||
CONFIG_PINCTRL_QCOM_SDM670=y
|
||||
CONFIG_PINCTRL_QCOM_SDM845=y
|
||||
CONFIG_PINCTRL_QCOM_SM6115=y
|
||||
CONFIG_PINCTRL_QCOM_SM6350=y
|
||||
CONFIG_PINCTRL_QCOM_SM7150=y
|
||||
CONFIG_PINCTRL_QCOM_SM8150=y
|
||||
CONFIG_PINCTRL_QCOM_SM8250=y
|
||||
CONFIG_PINCTRL_QCOM_SM8550=y
|
||||
|
||||
@ -33,6 +33,8 @@ CONFIG_CLK_QCOM_IPQ5424=y
|
||||
CONFIG_MSM_GPIO=y
|
||||
# CONFIG_I2C is not set
|
||||
# CONFIG_INPUT is not set
|
||||
CONFIG_MISC=y
|
||||
CONFIG_QCOM_GENI=y
|
||||
CONFIG_MMC_HS200_SUPPORT=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ADMA=y
|
||||
|
||||
@ -33,6 +33,8 @@ CONFIG_CLK_QCOM_IPQ9574=y
|
||||
CONFIG_MSM_GPIO=y
|
||||
# CONFIG_I2C is not set
|
||||
# CONFIG_INPUT is not set
|
||||
CONFIG_MISC=y
|
||||
CONFIG_QCOM_GENI=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ADMA=y
|
||||
CONFIG_MMC_SDHCI_MSM=y
|
||||
|
||||
@ -5,12 +5,6 @@
|
||||
|
||||
#include "qcom_defconfig"
|
||||
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
CONFIG_DEBUG_UART_BASE=0xA8C000
|
||||
CONFIG_DEBUG_UART_MSM_GENI=y
|
||||
CONFIG_DEBUG_UART_CLOCK=14745600
|
||||
|
||||
# Address where U-Boot will be loaded
|
||||
CONFIG_TEXT_BASE=0xaf000000
|
||||
CONFIG_REMAKE_ELF=y
|
||||
|
||||
@ -42,7 +42,6 @@ Older boards (db410c and db820c)
|
||||
|
||||
Open ``configs/dragonboard<BOARD>_defconfig``
|
||||
|
||||
CONFIG_BAUDRATE=115200
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||
# db410c - 0x78b0000
|
||||
@ -50,7 +49,6 @@ Open ``configs/dragonboard<BOARD>_defconfig``
|
||||
CONFIG_DEBUG_UART_BASE=0x75b0000
|
||||
CONFIG_DEBUG_UART_MSM=y
|
||||
CONFIG_DEBUG_UART_CLOCK=7372800
|
||||
#CONFIG_DEBUG_UART_SKIP_INIT=y
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_HEXDUMP=y
|
||||
|
||||
@ -50,8 +50,11 @@ static struct clk_ops stub_clk_ops = {
|
||||
|
||||
static const struct udevice_id stub_clk_ids[] = {
|
||||
{ .compatible = "qcom,rpmcc" },
|
||||
{ .compatible = "qcom,sdm670-rpmh-clk" },
|
||||
{ .compatible = "qcom,sdm845-rpmh-clk" },
|
||||
{ .compatible = "qcom,sc7180-rpmh-clk" },
|
||||
{ .compatible = "qcom,sc7280-rpmh-clk" },
|
||||
{ .compatible = "qcom,sm6350-rpmh-clk" },
|
||||
{ .compatible = "qcom,sm8150-rpmh-clk" },
|
||||
{ .compatible = "qcom,sm8250-rpmh-clk" },
|
||||
{ .compatible = "qcom,sm8550-rpmh-clk" },
|
||||
|
||||
@ -103,6 +103,21 @@ config CLK_QCOM_SM6115
|
||||
on the Snapdragon SM6115 SoC. This driver supports the clocks
|
||||
and resets exposed by the GCC hardware block.
|
||||
|
||||
config CLK_QCOM_SM6350
|
||||
bool "Qualcomm SM6350 GCC"
|
||||
select CLK_QCOM
|
||||
help
|
||||
Say Y here to enable support for the Global Clock Controller
|
||||
on the Snapdragon SM6350 SoC. This driver supports the clocks
|
||||
|
||||
config CLK_QCOM_SM7150
|
||||
bool "Qualcomm SM7150 GCC"
|
||||
select CLK_QCOM
|
||||
help
|
||||
Say Y here to enable support for the Global Clock Controller
|
||||
on the Snapdragon SM7150 SoC. This driver supports the clocks
|
||||
and resets exposed by the GCC hardware block.
|
||||
|
||||
config CLK_QCOM_SM8150
|
||||
bool "Qualcomm SM8150 GCC"
|
||||
select CLK_QCOM
|
||||
|
||||
@ -16,6 +16,8 @@ obj-$(CONFIG_CLK_QCOM_QCS615) += clock-qcs615.o
|
||||
obj-$(CONFIG_CLK_QCOM_SA8775P) += clock-sa8775p.o
|
||||
obj-$(CONFIG_CLK_QCOM_SC7280) += clock-sc7280.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM6115) += clock-sm6115.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM6350) += clock-sm6350.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM7150) += clock-sm7150.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM8150) += clock-sm8150.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM8250) += clock-sm8250.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM8550) += clock-sm8550.o
|
||||
|
||||
@ -38,6 +38,22 @@ static const struct freq_tbl ftbl_gcc_usb30_sec_master_clk_src[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s2_clk_src[] = {
|
||||
F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625),
|
||||
F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625),
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625),
|
||||
F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75),
|
||||
F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25),
|
||||
F(52174000, CFG_CLK_SRC_GPLL0, 1, 2, 23),
|
||||
F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75),
|
||||
F(75000000, CFG_CLK_SRC_GPLL0_EVEN, 4, 0, 0),
|
||||
F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15),
|
||||
F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25),
|
||||
F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static ulong sc7280_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
@ -47,6 +63,16 @@ static ulong sc7280_set_rate(struct clk *clk, ulong rate)
|
||||
debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_QUPV3_WRAP0_S5_CLK: /* UART5 */
|
||||
freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s2_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, 0x17600,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 16);
|
||||
return freq->freq;
|
||||
case GCC_QUPV3_WRAP0_S7_CLK: /* UART7 */
|
||||
freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s2_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, 0x17860,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 16);
|
||||
return freq->freq;
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
|
||||
@ -107,6 +133,8 @@ static const struct gate_clk sc7280_clks[] = {
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x52008, BIT(10)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x52008, BIT(11)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x52008, BIT(13)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x52008, BIT(15)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x52008, BIT(17)),
|
||||
GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x77010, BIT(0)),
|
||||
GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x770cc, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77018, BIT(0)),
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf018
|
||||
#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf030
|
||||
#define USB3_PRIM_PHY_AUX_CMD_RCGR 0xf05c
|
||||
#define SDCC1_APPS_CLK_CMD_RCGR 0x26028
|
||||
#define SDCC2_APPS_CLK_CMD_RCGR 0x1400c
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
|
||||
@ -44,6 +45,18 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = {
|
||||
F(144000, CFG_CLK_SRC_CXO, 16, 3, 25),
|
||||
F(400000, CFG_CLK_SRC_CXO, 12, 1, 4),
|
||||
F(20000000, CFG_CLK_SRC_GPLL0_EVEN, 5, 1, 3),
|
||||
F(25000000, CFG_CLK_SRC_GPLL0_EVEN, 6, 1, 2),
|
||||
F(50000000, CFG_CLK_SRC_GPLL0_EVEN, 6, 0, 0),
|
||||
F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0),
|
||||
F(192000000, CFG_CLK_SRC_GPLL6, 2, 0, 0),
|
||||
F(384000000, CFG_CLK_SRC_GPLL6, 1, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
|
||||
F(400000, CFG_CLK_SRC_CXO, 12, 1, 4),
|
||||
F(9600000, CFG_CLK_SRC_CXO, 2, 0, 0),
|
||||
@ -55,6 +68,22 @@ static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static ulong sdm670_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
const struct freq_tbl *freq;
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_SDCC1_APPS_CLK:
|
||||
freq = qcom_find_freq(ftbl_gcc_sdcc1_apps_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, SDCC1_APPS_CLK_CMD_RCGR,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 8);
|
||||
return freq->freq;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
@ -76,6 +105,54 @@ static ulong sdm845_clk_set_rate(struct clk *clk, ulong rate)
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gate_clk sdm670_clks[] = {
|
||||
GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, 0x00000001),
|
||||
GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x0502c, 0x00000001),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, 0x00000400),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, 0x00000800),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S2_CLK, 0x5200c, 0x00001000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x5200c, 0x00002000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x5200c, 0x00004000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x5200c, 0x00008000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S6_CLK, 0x5200c, 0x00010000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x5200c, 0x00020000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S0_CLK, 0x5200c, 0x00400000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x5200c, 0x00800000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x5200c, 0x02000000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S4_CLK, 0x5200c, 0x04000000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S5_CLK, 0x5200c, 0x08000000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S6_CLK, 0x5200c, 0x10000000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S7_CLK, 0x5200c, 0x20000000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_0_M_AHB_CLK, 0x5200c, 0x00000040),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_0_S_AHB_CLK, 0x5200c, 0x00000080),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_1_M_AHB_CLK, 0x5200c, 0x00100000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_1_S_AHB_CLK, 0x5200c, 0x00200000),
|
||||
GATE_CLK(GCC_SDCC1_AHB_CLK, 0x26008, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC1_APPS_CLK, 0x26004, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC1_ICE_CORE_CLK, 0x2600c, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC2_AHB_CLK, 0x14008, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC2_APPS_CLK, 0x14004, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC4_AHB_CLK, 0x16008, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC4_APPS_CLK, 0x16004, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001),
|
||||
GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x82024, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77010, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x7700c, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77058, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x7708c, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x77018, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x77014, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x77054, 0x00000001),
|
||||
GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x0f00c, 0x00000001),
|
||||
GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x0f014, 0x00000001),
|
||||
GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x0f010, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_CLKREF_CLK, 0x8c008, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x0f04c, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x0f050, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x0f054, 0x00000001),
|
||||
GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, 0x00000001),
|
||||
};
|
||||
|
||||
static const struct gate_clk sdm845_clks[] = {
|
||||
GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, 0x00000001),
|
||||
GATE_CLK(GCC_AGGRE_USB3_SEC_AXI_CLK, 0x82020, 0x00000001),
|
||||
@ -140,6 +217,28 @@ static const struct gate_clk sdm845_clks[] = {
|
||||
GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, 0x00000001),
|
||||
};
|
||||
|
||||
static int sdm670_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
debug("%s: clk %s\n", __func__, sdm670_clks[clk->id].name);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
qcom_gate_clk_en(priv, GCC_USB_PHY_CFG_AHB2PHY_CLK);
|
||||
/* These numbers are just pulled from the frequency tables in the Linux driver */
|
||||
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
|
||||
(4.5 * 2) - 1, 0, 0, 1 << 8, 8);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR,
|
||||
1, 0, 0, 0, 8);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB3_PRIM_PHY_AUX_CMD_RCGR,
|
||||
1, 0, 0, 0, 8);
|
||||
break;
|
||||
}
|
||||
|
||||
return qcom_gate_clk_en(priv, clk->id);
|
||||
}
|
||||
|
||||
static int sdm845_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
@ -188,6 +287,17 @@ static const struct qcom_reset_map sdm845_gcc_resets[] = {
|
||||
[GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
|
||||
};
|
||||
|
||||
static const struct qcom_power_map sdm670_gdscs[] = {
|
||||
[UFS_PHY_GDSC] = { 0x77004 },
|
||||
[USB30_PRIM_GDSC] = { 0xf004 },
|
||||
[HLOS1_VOTE_AGGRE_NOC_MMU_AUDIO_TBU_GDSC] = { 0x7d030 },
|
||||
[HLOS1_VOTE_AGGRE_NOC_MMU_TBU1_GDSC] = { 0x7d034 },
|
||||
[HLOS1_VOTE_AGGRE_NOC_MMU_TBU2_GDSC] = { 0x7d038 },
|
||||
[HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = { 0x7d040 },
|
||||
[HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC] = { 0x7d048 },
|
||||
[HLOS1_VOTE_MMNOC_MMU_TBU_SF_GDSC] = { 0x7d044 },
|
||||
};
|
||||
|
||||
static const struct qcom_power_map sdm845_gdscs[] = {
|
||||
[PCIE_0_GDSC] = { 0x6b004 },
|
||||
[PCIE_1_GDSC] = { 0x8d004 },
|
||||
@ -292,6 +402,19 @@ static const char *const sdm845_rcg_names[] = {
|
||||
"GCC_UFS_PHY_PHY_AUX",
|
||||
};
|
||||
|
||||
static struct msm_clk_data sdm670_clk_data = {
|
||||
/* Snapdragon 670 can function without its own exclusive resets. */
|
||||
.resets = sdm845_gcc_resets,
|
||||
.num_resets = ARRAY_SIZE(sdm845_gcc_resets),
|
||||
.clks = sdm670_clks,
|
||||
.num_clks = ARRAY_SIZE(sdm670_clks),
|
||||
.power_domains = sdm670_gdscs,
|
||||
.num_power_domains = ARRAY_SIZE(sdm670_gdscs),
|
||||
|
||||
.enable = sdm670_clk_enable,
|
||||
.set_rate = sdm670_clk_set_rate,
|
||||
};
|
||||
|
||||
static struct msm_clk_data sdm845_clk_data = {
|
||||
.resets = sdm845_gcc_resets,
|
||||
.num_resets = ARRAY_SIZE(sdm845_gcc_resets),
|
||||
@ -310,6 +433,10 @@ static struct msm_clk_data sdm845_clk_data = {
|
||||
};
|
||||
|
||||
static const struct udevice_id gcc_sdm845_of_match[] = {
|
||||
{
|
||||
.compatible = "qcom,gcc-sdm670",
|
||||
.data = (ulong)&sdm670_clk_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,gcc-sdm845",
|
||||
.data = (ulong)&sdm845_clk_data,
|
||||
|
||||
193
drivers/clk/qcom/clock-sm6350.c
Normal file
193
drivers/clk/qcom/clock-sm6350.c
Normal file
@ -0,0 +1,193 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Clock drivers for Qualcomm sm6350
|
||||
*
|
||||
* (C) Copyright 2024 Linaro Ltd.
|
||||
* (C) Copyright 2025 Luca Weiss <luca.weiss@fairphone.com>
|
||||
*/
|
||||
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sm6350.h>
|
||||
|
||||
#include "clock-qcom.h"
|
||||
|
||||
#undef CFG_CLK_SRC_GPLL0_ODD
|
||||
#define CFG_CLK_SRC_GPLL0_ODD (2 << 8)
|
||||
#define CFG_CLK_SRC_GPLL6_EVEN (2 << 8)
|
||||
|
||||
#define GCC_SE12_UART_RCG_REG 0x223a8
|
||||
#define GCC_SDCC2_APPS_CLK_SRC_REG 0x2000c
|
||||
|
||||
#define APCS_GPLL7_STATUS 0x7000
|
||||
#define APCS_GPLLX_ENA_REG 0x52010
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_qupv3_wrap1_s3_clk_src[] = {
|
||||
F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625),
|
||||
F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625),
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625),
|
||||
F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75),
|
||||
F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25),
|
||||
F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75),
|
||||
F(75000000, CFG_CLK_SRC_GPLL0_EVEN, 4, 0, 0),
|
||||
F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15),
|
||||
F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25),
|
||||
F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0),
|
||||
F(102400000, CFG_CLK_SRC_GPLL0_EVEN, 1, 128, 375),
|
||||
F(112000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 28, 75),
|
||||
F(117964800, CFG_CLK_SRC_GPLL0_EVEN, 1, 6144, 15625),
|
||||
F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0),
|
||||
F(128000000, CFG_CLK_SRC_GPLL6_EVEN, 3, 0, 0),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
|
||||
F(400000, CFG_CLK_SRC_CXO, 12, 1, 4),
|
||||
F(9600000, CFG_CLK_SRC_CXO, 2, 0, 0),
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
F(25000000, CFG_CLK_SRC_GPLL0_ODD, 8, 0, 0),
|
||||
F(50000000, CFG_CLK_SRC_GPLL0_ODD, 4, 0, 0),
|
||||
F(100000000, CFG_CLK_SRC_GPLL0_ODD, 2, 0, 0),
|
||||
F(202000000, CFG_CLK_SRC_GPLL7, 4, 0, 0),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct pll_vote_clk gpll7_vote_clk = {
|
||||
.status = APCS_GPLL7_STATUS,
|
||||
.status_bit = BIT(31),
|
||||
.ena_vote = APCS_GPLLX_ENA_REG,
|
||||
.vote_bit = BIT(7),
|
||||
};
|
||||
|
||||
static ulong sm6350_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
const struct freq_tbl *freq;
|
||||
|
||||
if (clk->id < priv->data->num_clks)
|
||||
debug("%s: %s, requested rate=%ld\n", __func__,
|
||||
priv->data->clks[clk->id].name, rate);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_QUPV3_WRAP1_S3_CLK: /*UART9*/
|
||||
freq = qcom_find_freq(ftbl_gcc_qupv3_wrap1_s3_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, GCC_SE12_UART_RCG_REG,
|
||||
freq->pre_div, freq->m, freq->n, freq->src,
|
||||
16);
|
||||
|
||||
return freq->freq;
|
||||
case GCC_SDCC2_APPS_CLK:
|
||||
/* Enable GPLL7 so that we can point SDCC2_APPS_CLK_SRC at it */
|
||||
clk_enable_gpll0(priv->base, &gpll7_vote_clk);
|
||||
freq = qcom_find_freq(ftbl_gcc_sdcc2_apps_clk_src, rate);
|
||||
WARN(freq->src != CFG_CLK_SRC_GPLL7,
|
||||
"SDCC2_APPS_CLK_SRC not set to GPLL7, requested rate %lu\n",
|
||||
rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, GCC_SDCC2_APPS_CLK_SRC_REG,
|
||||
freq->pre_div, freq->m, freq->n,
|
||||
CFG_CLK_SRC_GPLL7, 8);
|
||||
|
||||
return rate;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gate_clk sm6350_clks[] = {
|
||||
GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x3e014, 0x00000001),
|
||||
GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x3e010, 0x00000001),
|
||||
GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x1101c, 0x00000001),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x52000, 0x00800000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_1_M_AHB_CLK, 0x52000, 0x00040000),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_1_S_AHB_CLK, 0x52000, 0x00080000),
|
||||
GATE_CLK(GCC_SDCC2_AHB_CLK, 0x20008, 0x00000001),
|
||||
GATE_CLK(GCC_SDCC2_APPS_CLK, 0x20004, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x3a00c, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x3a034, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x3a0a4, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x3a0ac, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x3a014, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_1_CLK, 0x3a018, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x3a010, 0x00000001),
|
||||
GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x3a09c, 0x00000001),
|
||||
GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x1a00c, 0x00000001),
|
||||
GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x1a018, 0x00000001),
|
||||
GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x1a014, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_CLKREF_CLK, 0x8c010, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x1a050, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x1a054, 0x00000001),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x1a058, 0x00000001),
|
||||
};
|
||||
|
||||
static int sm6350_enable(struct clk *clk)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
if (priv->data->num_clks < clk->id) {
|
||||
debug("%s: unknown clk id %lu\n", __func__, clk->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("%s: clk %s\n", __func__, sm6350_clks[clk->id].name);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
|
||||
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
|
||||
break;
|
||||
}
|
||||
|
||||
return qcom_gate_clk_en(priv, clk->id);
|
||||
}
|
||||
|
||||
static const struct qcom_reset_map sm6350_gcc_resets[] = {
|
||||
[GCC_QUSB2PHY_PRIM_BCR] = { 0x1d000 },
|
||||
[GCC_QUSB2PHY_SEC_BCR] = { 0x1e000 },
|
||||
[GCC_SDCC1_BCR] = { 0x4b000 },
|
||||
[GCC_SDCC2_BCR] = { 0x20000 },
|
||||
[GCC_UFS_PHY_BCR] = { 0x3a000 },
|
||||
[GCC_USB30_PRIM_BCR] = { 0x1a000 },
|
||||
[GCC_USB3_PHY_PRIM_BCR] = { 0x1c000 },
|
||||
[GCC_USB3_DP_PHY_PRIM_BCR] = { 0x1c008 },
|
||||
};
|
||||
|
||||
static const struct qcom_power_map sm6350_gdscs[] = {
|
||||
[USB30_PRIM_GDSC] = { 0x1a004 },
|
||||
[UFS_PHY_GDSC] = { 0x3a004 },
|
||||
[HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = { 0xb7040 },
|
||||
[HLOS1_VOTE_MMNOC_MMU_TBU_HF1_GDSC] = { 0xb7044 },
|
||||
};
|
||||
|
||||
static struct msm_clk_data sm6350_gcc_data = {
|
||||
.resets = sm6350_gcc_resets,
|
||||
.num_resets = ARRAY_SIZE(sm6350_gcc_resets),
|
||||
.clks = sm6350_clks,
|
||||
.num_clks = ARRAY_SIZE(sm6350_clks),
|
||||
.power_domains = sm6350_gdscs,
|
||||
.num_power_domains = ARRAY_SIZE(sm6350_gdscs),
|
||||
|
||||
.enable = sm6350_enable,
|
||||
.set_rate = sm6350_set_rate,
|
||||
};
|
||||
|
||||
static const struct udevice_id gcc_sm6350_of_match[] = {
|
||||
{
|
||||
.compatible = "qcom,gcc-sm6350",
|
||||
.data = (ulong)&sm6350_gcc_data,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(gcc_sm6350) = {
|
||||
.name = "gcc_sm6350",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = gcc_sm6350_of_match,
|
||||
.bind = qcom_cc_bind,
|
||||
.flags = DM_FLAG_PRE_RELOC,
|
||||
};
|
||||
250
drivers/clk/qcom/clock-sm7150.c
Normal file
250
drivers/clk/qcom/clock-sm7150.c
Normal file
@ -0,0 +1,250 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Clock drivers for Qualcomm SM7150
|
||||
*
|
||||
* (C) Copyright 2025 Danila Tikhonov <danila@jiaxyga.com>
|
||||
* (C) Copyright 2025 Jens Reidel <adrian@mainlining.org>
|
||||
*
|
||||
* Based on Linux Kernel driver
|
||||
*/
|
||||
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <dt-bindings/clock/qcom,sm7150-gcc.h>
|
||||
|
||||
#include "clock-qcom.h"
|
||||
|
||||
#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf01c
|
||||
#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf034
|
||||
#define USB3_PRIM_PHY_AUX_CLK_CMD_RCGR 0xf060
|
||||
|
||||
#define SE8_UART_APPS_CMD_RCGR 0x18278
|
||||
#define GCC_SDCC2_APPS_CLK_SRC_REG 0x1400c
|
||||
|
||||
#define APCS_GPLL7_STATUS 0x27000
|
||||
#define APCS_GPLLX_ENA_REG 0x52000
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = {
|
||||
F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625),
|
||||
F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625),
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625),
|
||||
F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75),
|
||||
F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25),
|
||||
F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75),
|
||||
F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15),
|
||||
F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25),
|
||||
F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0),
|
||||
F(102400000, CFG_CLK_SRC_GPLL0_EVEN, 1, 128, 375),
|
||||
F(112000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 28, 75),
|
||||
F(117964800, CFG_CLK_SRC_GPLL0_EVEN, 1, 6144, 15625),
|
||||
F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0),
|
||||
F(128000000, CFG_CLK_SRC_GPLL0, 1, 16, 75),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
|
||||
F(400000, CFG_CLK_SRC_CXO, 12, 1, 4),
|
||||
F(9600000, CFG_CLK_SRC_CXO, 2, 0, 0),
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
F(25000000, CFG_CLK_SRC_GPLL0_EVEN, 12, 0, 0),
|
||||
F(50000000, CFG_CLK_SRC_GPLL0_EVEN, 6, 0, 0),
|
||||
F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0),
|
||||
F(208000000, CFG_CLK_SRC_GPLL7, 4, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
|
||||
F(66666667, CFG_CLK_SRC_GPLL0, 4.5, 0, 0),
|
||||
F(133333333, CFG_CLK_SRC_GPLL0_EVEN, 4.5, 0, 0),
|
||||
F(200000000, CFG_CLK_SRC_GPLL0, 3, 0, 0),
|
||||
F(240000000, CFG_CLK_SRC_GPLL0, 2.5, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = {
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
F(20000000, CFG_CLK_SRC_GPLL0_EVEN, 15, 0, 0),
|
||||
F(40000000, CFG_CLK_SRC_GPLL0_EVEN, 7.5, 0, 0),
|
||||
F(60000000, CFG_CLK_SRC_GPLL0, 10, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_usb3_prim_phy_aux_clk_src[] = {
|
||||
F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0),
|
||||
{ }
|
||||
};
|
||||
|
||||
static ulong sm7150_clk_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
const struct freq_tbl *freq;
|
||||
|
||||
if (clk->id < priv->data->num_clks)
|
||||
debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_QUPV3_WRAP1_S2_CLK: /* UART8 */
|
||||
freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, SE8_UART_APPS_CMD_RCGR,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 16);
|
||||
return freq->freq;
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 8);
|
||||
return freq->freq;
|
||||
case GCC_USB30_PRIM_MOCK_UTMI_CLK:
|
||||
freq = qcom_find_freq(ftbl_gcc_usb30_prim_mock_utmi_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 0);
|
||||
return freq->freq;
|
||||
case GCC_USB3_PRIM_PHY_AUX_CLK_SRC:
|
||||
freq = qcom_find_freq(ftbl_gcc_usb3_prim_phy_aux_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB3_PRIM_PHY_AUX_CLK_CMD_RCGR,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 0);
|
||||
return freq->freq;
|
||||
case GCC_SDCC2_APPS_CLK:
|
||||
freq = qcom_find_freq(ftbl_gcc_sdcc2_apps_clk_src, rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, GCC_SDCC2_APPS_CLK_SRC_REG,
|
||||
freq->pre_div, freq->m, freq->n, freq->src, 8);
|
||||
return freq->freq;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gate_clk sm7150_clks[] = {
|
||||
GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x82024, BIT(0)),
|
||||
GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x8201c, BIT(0)),
|
||||
GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x502c, BIT(0)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S0_CLK, 0x5200c, BIT(10)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S1_CLK, 0x5200c, BIT(11)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S2_CLK, 0x5200c, BIT(12)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S3_CLK, 0x5200c, BIT(13)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S4_CLK, 0x5200c, BIT(14)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S5_CLK, 0x5200c, BIT(15)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S6_CLK, 0x5200c, BIT(16)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP0_S7_CLK, 0x5200c, BIT(17)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S0_CLK, 0x5200c, BIT(22)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S1_CLK, 0x5200c, BIT(23)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S2_CLK, 0x5200c, BIT(24)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S3_CLK, 0x5200c, BIT(25)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S4_CLK, 0x5200c, BIT(26)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S5_CLK, 0x5200c, BIT(27)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S6_CLK, 0x5200c, BIT(28)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP1_S7_CLK, 0x5200c, BIT(29)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_0_M_AHB_CLK, 0x5200c, BIT(6)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_0_S_AHB_CLK, 0x5200c, BIT(7)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_1_M_AHB_CLK, 0x5200c, BIT(20)),
|
||||
GATE_CLK(GCC_QUPV3_WRAP_1_S_AHB_CLK, 0x5200c, BIT(21)),
|
||||
GATE_CLK(GCC_SDCC1_AHB_CLK, 0x12008, BIT(0)),
|
||||
GATE_CLK(GCC_SDCC1_APPS_CLK, 0x1200c, BIT(0)),
|
||||
GATE_CLK(GCC_SDCC1_ICE_CORE_CLK, 0x12040, BIT(0)),
|
||||
GATE_CLK(GCC_SDCC2_AHB_CLK, 0x14008, BIT(0)),
|
||||
GATE_CLK(GCC_SDCC2_APPS_CLK, 0x14004, BIT(0)),
|
||||
GATE_CLK(GCC_SDCC4_AHB_CLK, 0x16008, BIT(0)),
|
||||
GATE_CLK(GCC_SDCC4_APPS_CLK, 0x16004, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_MEM_CLKREF_CLK, 0x8c000, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_AHB_CLK, 0x77014, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_AXI_CLK, 0x77038, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_ICE_CORE_CLK, 0x77090, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_PHY_AUX_CLK, 0x77094, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_RX_SYMBOL_0_CLK, 0x7701c, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_TX_SYMBOL_0_CLK, 0x77018, BIT(0)),
|
||||
GATE_CLK(GCC_UFS_PHY_UNIPRO_CORE_CLK, 0x7708c, BIT(0)),
|
||||
GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x0f010, BIT(0)),
|
||||
GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x0f018, BIT(0)),
|
||||
GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x0f014, BIT(0)),
|
||||
GATE_CLK(GCC_USB3_PRIM_CLKREF_CLK, 0x8c010, BIT(0)),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x0f050, BIT(0)),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x0f054, BIT(0)),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x0f058, BIT(0)),
|
||||
GATE_CLK(GCC_USB_PHY_CFG_AHB2PHY_CLK, 0x6a004, BIT(0)),
|
||||
};
|
||||
|
||||
static int sm7150_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
if (priv->data->num_clks < clk->id) {
|
||||
debug("%s: unknown clk id %lu\n", __func__, clk->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("%s: clk %s\n", __func__, sm7150_clks[clk->id].name);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_AGGRE_USB3_PRIM_AXI_CLK:
|
||||
qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK);
|
||||
fallthrough;
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
|
||||
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
|
||||
break;
|
||||
}
|
||||
|
||||
return qcom_gate_clk_en(priv, clk->id);
|
||||
}
|
||||
|
||||
static const struct qcom_reset_map sm7150_gcc_resets[] = {
|
||||
[GCC_UFS_PHY_BCR] = { 0x77000 },
|
||||
[GCC_USB30_PRIM_BCR] = { 0xf000 },
|
||||
[GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 },
|
||||
[GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 },
|
||||
[GCC_USB3_PHY_PRIM_BCR] = { 0x50000 },
|
||||
[GCC_USB3_PHY_SEC_BCR] = { 0x5000c },
|
||||
[GCC_QUSB2PHY_PRIM_BCR] = { 0x26000 },
|
||||
};
|
||||
|
||||
static const struct qcom_power_map sm7150_gdscs[] = {
|
||||
[PCIE_0_GDSC] = { 0x6b004 },
|
||||
[UFS_PHY_GDSC] = { 0x77004 },
|
||||
[USB30_PRIM_GDSC] = { 0xf004 },
|
||||
};
|
||||
|
||||
static const phys_addr_t sm7150_rcg_addrs[] = {
|
||||
0x10f01c, // USB30_PRIM_MASTER_CLK_CMD_RCGR
|
||||
0x10f034, // USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR
|
||||
0x10f060, // USB3_PRIM_PHY_AUX_CLK_CMD_RCGR,
|
||||
};
|
||||
|
||||
static const char *const sm7150_rcg_names[] = {
|
||||
"USB30_PRIM_MASTER_CLK",
|
||||
"USB30_PRIM_MOCK_UTMI_CLK",
|
||||
"USB3_PRIM_PHY_AUX_CLK",
|
||||
};
|
||||
|
||||
static struct msm_clk_data sm7150_gcc_data = {
|
||||
.resets = sm7150_gcc_resets,
|
||||
.num_resets = ARRAY_SIZE(sm7150_gcc_resets),
|
||||
.clks = sm7150_clks,
|
||||
.num_clks = ARRAY_SIZE(sm7150_clks),
|
||||
|
||||
.power_domains = sm7150_gdscs,
|
||||
.num_power_domains = ARRAY_SIZE(sm7150_gdscs),
|
||||
|
||||
.enable = sm7150_clk_enable,
|
||||
.set_rate = sm7150_clk_set_rate,
|
||||
|
||||
.dbg_rcg_addrs = sm7150_rcg_addrs,
|
||||
.num_rcgs = ARRAY_SIZE(sm7150_rcg_addrs),
|
||||
.dbg_rcg_names = sm7150_rcg_names,
|
||||
};
|
||||
|
||||
static const struct udevice_id gcc_sm7150_of_match[] = {
|
||||
{ .compatible = "qcom,sm7150-gcc", .data = (ulong)&sm7150_gcc_data, },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(gcc_sm7150) = {
|
||||
.name = "gcc_sm7150",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = gcc_sm7150_of_match,
|
||||
.bind = qcom_cc_bind,
|
||||
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
@ -18,14 +18,9 @@
|
||||
#define GCC_SE12_UART_RCG_REG 0x184D0
|
||||
#define GCC_SDCC2_APPS_CLK_SRC_REG 0x1400c
|
||||
|
||||
#define APCS_GPLL0_ENA_VOTE 0x79000
|
||||
#define APCS_GPLL9_STATUS 0x1c000
|
||||
#define APCS_GPLLX_ENA_REG 0x52018
|
||||
|
||||
#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020
|
||||
#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038
|
||||
#define USB3_PRIM_PHY_AUX_CMD_RCGR 0xf064
|
||||
|
||||
static const struct freq_tbl ftbl_gcc_qupv3_wrap1_s4_clk_src[] = {
|
||||
F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625),
|
||||
F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625),
|
||||
|
||||
@ -743,6 +743,10 @@ static int qcom_spmi_pmic_gpio_probe(struct udevice *dev)
|
||||
}
|
||||
|
||||
static const struct udevice_id qcom_spmi_pmic_gpio_ids[] = {
|
||||
{ .compatible = "qcom,pm6150l-gpio" },
|
||||
{ .compatible = "qcom,pm6350-gpio" },
|
||||
{ .compatible = "qcom,pm660l-gpio" },
|
||||
{ .compatible = "qcom,pm7325-gpio" },
|
||||
{ .compatible = "qcom,pm8550-gpio" },
|
||||
{ .compatible = "qcom,pm8550b-gpio" },
|
||||
{ .compatible = "qcom,pm8550ve-gpio" },
|
||||
|
||||
@ -668,7 +668,7 @@ config SYS_I2C_QUP
|
||||
|
||||
config SYS_I2C_GENI
|
||||
bool "Qualcomm Generic Interface (GENI) I2C controller"
|
||||
depends on ARCH_SNAPDRAGON
|
||||
depends on ARCH_SNAPDRAGON && QCOM_GENI
|
||||
help
|
||||
Support for the Qualcomm Generic Interface (GENI) I2C interface.
|
||||
The Generic Interface (GENI) is a firmware based Qualcomm Universal
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <reset.h>
|
||||
#include <time.h>
|
||||
#include <soc/qcom/geni-se.h>
|
||||
#include <soc/qcom/qup-fw-load.h>
|
||||
|
||||
#define SE_I2C_TX_TRANS_LEN 0x26c
|
||||
#define SE_I2C_RX_TRANS_LEN 0x270
|
||||
@ -331,15 +332,13 @@ static int geni_i2c_disable_clocks(struct udevice *dev, struct geni_i2c_priv *ge
|
||||
if (geni->is_master_hub) {
|
||||
ret = clk_disable(&geni->core);
|
||||
if (ret) {
|
||||
dev_err(dev, "clk_enable core failed %d\n", ret);
|
||||
return ret;
|
||||
dev_err(dev, "clk_disable core failed %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_disable(&geni->se);
|
||||
if (ret) {
|
||||
dev_err(dev, "clk_enable se failed %d\n", ret);
|
||||
return ret;
|
||||
dev_err(dev, "clk_disable se failed %d\n", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -501,6 +500,13 @@ static int geni_i2c_probe(struct udevice *dev)
|
||||
proto &= FW_REV_PROTOCOL_MSK;
|
||||
proto >>= FW_REV_PROTOCOL_SHFT;
|
||||
|
||||
if (proto == GENI_SE_INVALID_PROTO) {
|
||||
qcom_geni_load_firmware(geni->base, dev);
|
||||
proto = readl(geni->base + GENI_FW_REVISION_RO);
|
||||
proto &= FW_REV_PROTOCOL_MSK;
|
||||
proto >>= FW_REV_PROTOCOL_SHFT;
|
||||
}
|
||||
|
||||
if (proto != GENI_SE_I2C) {
|
||||
dev_err(dev, "Invalid proto %d\n", proto);
|
||||
geni_i2c_disable_clocks(dev, geni);
|
||||
|
||||
@ -388,8 +388,10 @@ static struct iommu_ops qcom_smmu_ops = {
|
||||
};
|
||||
|
||||
static const struct udevice_id qcom_smmu500_ids[] = {
|
||||
{ .compatible = "qcom,sdm845-smmu-500" },
|
||||
{ .compatible = "qcom,sc7180-smmu-500" },
|
||||
{ .compatible = "qcom,sc7280-smmu-500" },
|
||||
{ .compatible = "qcom,sdm845-smmu-500" },
|
||||
{ .compatible = "qcom,sm6350-smmu-500" },
|
||||
{ .compatible = "qcom,smmu-500", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@ -83,6 +83,15 @@ config GATEWORKS_SC
|
||||
boards to provide a boot watchdog, power control, temperature monitor,
|
||||
voltage ADCs, and EEPROM.
|
||||
|
||||
config QCOM_GENI
|
||||
bool "Qualcomm Generic Interface (GENI) driver"
|
||||
depends on MISC
|
||||
select PARTITION_TYPE_GUID
|
||||
help
|
||||
Enable support for Qualcomm GENI and it's peripherals. GENI is responseible
|
||||
for providing a common interface for various peripherals like UART, I2C, SPI,
|
||||
etc.
|
||||
|
||||
config ROCKCHIP_EFUSE
|
||||
bool "Rockchip e-fuse support"
|
||||
depends on MISC
|
||||
|
||||
@ -67,6 +67,7 @@ obj-$(CONFIG_QFW_MMIO) += qfw_mmio.o
|
||||
obj-$(CONFIG_QFW_SMBIOS) += qfw_smbios.o
|
||||
obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
|
||||
endif
|
||||
obj-$(CONFIG_QCOM_GENI) += qcom_geni.o
|
||||
obj-$(CONFIG_$(PHASE_)ROCKCHIP_EFUSE) += rockchip-efuse.o
|
||||
obj-$(CONFIG_$(PHASE_)ROCKCHIP_OTP) += rockchip-otp.o
|
||||
obj-$(CONFIG_$(PHASE_)ROCKCHIP_IODOMAIN) += rockchip-io-domain.o
|
||||
|
||||
580
drivers/misc/qcom_geni.c
Normal file
580
drivers/misc/qcom_geni.c
Normal file
@ -0,0 +1,580 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2025, Linaro Ltd.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "GENI-SE: " fmt
|
||||
|
||||
#include <blk.h>
|
||||
#include <part.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/read.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/lists.h>
|
||||
#include <elf.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <misc.h>
|
||||
#include <linux/printk.h>
|
||||
#include <soc/qcom/geni-se.h>
|
||||
#include <soc/qcom/qup-fw-load.h>
|
||||
#include <dm/device_compat.h>
|
||||
|
||||
struct qup_se_rsc {
|
||||
phys_addr_t base;
|
||||
phys_addr_t wrapper_base;
|
||||
struct udevice *dev;
|
||||
|
||||
enum geni_se_xfer_mode mode;
|
||||
enum geni_se_protocol_type protocol;
|
||||
};
|
||||
|
||||
struct geni_se_plat {
|
||||
bool need_firmware_load;
|
||||
};
|
||||
|
||||
/**
|
||||
* geni_enable_interrupts() Enable interrupts.
|
||||
* @rsc: Pointer to a structure representing SE-related resources.
|
||||
*
|
||||
* Enable the required interrupts during the firmware load process.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void geni_enable_interrupts(struct qup_se_rsc *rsc)
|
||||
{
|
||||
u32 reg_value;
|
||||
|
||||
/* Enable required interrupts. */
|
||||
writel_relaxed(M_COMMON_GENI_M_IRQ_EN, rsc->base + GENI_M_IRQ_ENABLE);
|
||||
|
||||
reg_value = S_CMD_OVERRUN_EN | S_ILLEGAL_CMD_EN |
|
||||
S_CMD_CANCEL_EN | S_CMD_ABORT_EN |
|
||||
S_GP_IRQ_0_EN | S_GP_IRQ_1_EN |
|
||||
S_GP_IRQ_2_EN | S_GP_IRQ_3_EN |
|
||||
S_RX_FIFO_WR_ERR_EN | S_RX_FIFO_RD_ERR_EN;
|
||||
writel_relaxed(reg_value, rsc->base + GENI_S_IRQ_ENABLE);
|
||||
|
||||
/* DMA mode configuration. */
|
||||
reg_value = DMA_TX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK |
|
||||
DMA_TX_IRQ_EN_SET_SBE_EN_SET_BMSK |
|
||||
DMA_TX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK;
|
||||
writel_relaxed(reg_value, rsc->base + DMA_TX_IRQ_EN_SET);
|
||||
reg_value = DMA_RX_IRQ_EN_SET_FLUSH_DONE_EN_SET_BMSK |
|
||||
DMA_RX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK |
|
||||
DMA_RX_IRQ_EN_SET_SBE_EN_SET_BMSK |
|
||||
DMA_RX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK;
|
||||
writel_relaxed(reg_value, rsc->base + DMA_RX_IRQ_EN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* geni_flash_fw_revision() - Flash the firmware revision.
|
||||
* @rsc: Pointer to a structure representing SE-related resources.
|
||||
* @hdr: Pointer to the ELF header of the Serial Engine.
|
||||
*
|
||||
* Flash the firmware revision and protocol into the respective register.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void geni_flash_fw_revision(struct qup_se_rsc *rsc, struct elf_se_hdr *hdr)
|
||||
{
|
||||
u32 reg_value;
|
||||
|
||||
/* Flash firmware revision register. */
|
||||
reg_value = (hdr->serial_protocol << FW_REV_PROTOCOL_SHFT) |
|
||||
(hdr->fw_version & 0xFF << FW_REV_VERSION_SHFT);
|
||||
writel_relaxed(reg_value, rsc->base + SE_GENI_FW_REVISION);
|
||||
|
||||
reg_value = (hdr->serial_protocol << FW_REV_PROTOCOL_SHFT) |
|
||||
(hdr->fw_version & 0xFF << FW_REV_VERSION_SHFT);
|
||||
|
||||
writel_relaxed(reg_value, rsc->base + SE_S_FW_REVISION);
|
||||
}
|
||||
|
||||
/**
|
||||
* geni_configure_xfer_mode() - Set the transfer mode.
|
||||
* @rsc: Pointer to a structure representing SE-related resources.
|
||||
*
|
||||
* Set the transfer mode to either FIFO or DMA according to the mode specified by the protocol
|
||||
* driver.
|
||||
*
|
||||
* Return: 0 if successful, otherwise return an error value.
|
||||
*/
|
||||
static int geni_configure_xfer_mode(struct qup_se_rsc *rsc)
|
||||
{
|
||||
/* Configure SE FIFO, DMA or GSI mode. */
|
||||
switch (rsc->mode) {
|
||||
case GENI_GPI_DMA:
|
||||
geni_setbits32(rsc->base + QUPV3_SE_GENI_DMA_MODE_EN,
|
||||
GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK);
|
||||
writel_relaxed(0x0, rsc->base + SE_IRQ_EN);
|
||||
writel_relaxed(SE_GSI_EVENT_EN_BMSK, rsc->base + SE_GSI_EVENT_EN);
|
||||
break;
|
||||
|
||||
case GENI_SE_FIFO:
|
||||
geni_clrbits32(rsc->base + QUPV3_SE_GENI_DMA_MODE_EN,
|
||||
GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK);
|
||||
writel_relaxed(SE_IRQ_EN_RMSK, rsc->base + SE_IRQ_EN);
|
||||
writel_relaxed(0x0, rsc->base + SE_GSI_EVENT_EN);
|
||||
break;
|
||||
|
||||
case GENI_SE_DMA:
|
||||
geni_setbits32(rsc->base + QUPV3_SE_GENI_DMA_MODE_EN,
|
||||
GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK);
|
||||
writel_relaxed(SE_IRQ_EN_RMSK, rsc->base + SE_IRQ_EN);
|
||||
writel_relaxed(0x0, rsc->base + SE_GSI_EVENT_EN);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(rsc->dev, "invalid se mode: %d\n", rsc->mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* geni_config_common_control() - Configure common CGC and disable high priority interrupt.
|
||||
* @rsc: Pointer to a structure representing SE-related resources.
|
||||
*
|
||||
* Configure the common CGC and disable high priority interrupts until the current low priority
|
||||
* interrupts are handled.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void geni_config_common_control(struct qup_se_rsc *rsc)
|
||||
{
|
||||
/*
|
||||
* Disable high priority interrupt until current low priority interrupts are handled.
|
||||
*/
|
||||
geni_setbits32(rsc->wrapper_base + QUPV3_COMMON_CFG,
|
||||
FAST_SWITCH_TO_HIGH_DISABLE_BMASK);
|
||||
|
||||
/*
|
||||
* Set AHB_M_CLK_CGC_ON to indicate hardware controls se-wrapper cgc clock.
|
||||
*/
|
||||
geni_setbits32(rsc->wrapper_base + QUPV3_SE_AHB_M_CFG,
|
||||
AHB_M_CLK_CGC_ON_BMASK);
|
||||
|
||||
/* Let hardware to control common cgc. */
|
||||
geni_setbits32(rsc->wrapper_base + QUPV3_COMMON_CGC_CTRL,
|
||||
COMMON_CSR_SLV_CLK_CGC_ON_BMASK);
|
||||
}
|
||||
|
||||
static int load_se_firmware(struct qup_se_rsc *rsc, struct elf_se_hdr *hdr)
|
||||
{
|
||||
const u32 *fw_val_arr, *cfg_val_arr;
|
||||
const u8 *cfg_idx_arr;
|
||||
u32 i, reg_value, mask, ramn_cnt;
|
||||
int ret;
|
||||
|
||||
fw_val_arr = (const u32 *)((u8 *)hdr + hdr->fw_offset);
|
||||
cfg_idx_arr = (const u8 *)hdr + hdr->cfg_idx_offset;
|
||||
cfg_val_arr = (const u32 *)((u8 *)hdr + hdr->cfg_val_offset);
|
||||
|
||||
geni_config_common_control(rsc);
|
||||
|
||||
/* Allows to drive corresponding data according to hardware value. */
|
||||
writel_relaxed(0x0, rsc->base + GENI_OUTPUT_CTRL);
|
||||
|
||||
/* Set SCLK and HCLK to program RAM */
|
||||
geni_setbits32(rsc->base + GENI_CGC_CTRL, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
|
||||
GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK);
|
||||
writel_relaxed(0x0, rsc->base + SE_GENI_CLK_CTRL);
|
||||
geni_clrbits32(rsc->base + GENI_CGC_CTRL, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
|
||||
GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK);
|
||||
|
||||
/* Enable required clocks for DMA CSR, TX and RX. */
|
||||
reg_value = DMA_GENERAL_CFG_AHB_SEC_SLV_CLK_CGC_ON_BMSK |
|
||||
DMA_GENERAL_CFG_DMA_AHB_SLV_CLK_CGC_ON_BMSK |
|
||||
DMA_GENERAL_CFG_DMA_TX_CLK_CGC_ON_BMSK |
|
||||
DMA_GENERAL_CFG_DMA_RX_CLK_CGC_ON_BMSK;
|
||||
|
||||
geni_setbits32(rsc->base + DMA_GENERAL_CFG, reg_value);
|
||||
|
||||
/* Let hardware control CGC by default. */
|
||||
writel_relaxed(DEFAULT_CGC_EN, rsc->base + GENI_CGC_CTRL);
|
||||
|
||||
/* Set version of the configuration register part of firmware. */
|
||||
writel_relaxed(hdr->cfg_version, rsc->base + GENI_INIT_CFG_REVISION);
|
||||
writel_relaxed(hdr->cfg_version, rsc->base + GENI_S_INIT_CFG_REVISION);
|
||||
|
||||
/* Configure GENI primitive table. */
|
||||
for (i = 0; i < hdr->cfg_size_in_items; i++)
|
||||
writel_relaxed(cfg_val_arr[i],
|
||||
rsc->base + GENI_CFG_REG0 + (cfg_idx_arr[i] * sizeof(u32)));
|
||||
|
||||
/* Configure condition for assertion of RX_RFR_WATERMARK condition. */
|
||||
reg_value = readl_relaxed(rsc->base + QUPV3_SE_HW_PARAM_1);
|
||||
mask = (reg_value >> RX_FIFO_WIDTH_BIT) & RX_FIFO_WIDTH_MASK;
|
||||
writel_relaxed(mask - 2, rsc->base + GENI_RX_RFR_WATERMARK_REG);
|
||||
|
||||
/* Let hardware control CGC */
|
||||
geni_setbits32(rsc->base + GENI_OUTPUT_CTRL, DEFAULT_IO_OUTPUT_CTRL_MSK);
|
||||
|
||||
ret = geni_configure_xfer_mode(rsc);
|
||||
if (ret) {
|
||||
dev_err(rsc->dev, "failed to configure xfer mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
geni_enable_interrupts(rsc);
|
||||
|
||||
geni_flash_fw_revision(rsc, hdr);
|
||||
|
||||
ramn_cnt = hdr->fw_size_in_items;
|
||||
if (hdr->fw_size_in_items % 2 != 0)
|
||||
ramn_cnt++;
|
||||
|
||||
if (ramn_cnt >= MAX_GENI_CFG_RAMn_CNT) {
|
||||
dev_err(rsc->dev, "firmware size is too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Program RAM address space. */
|
||||
for (i = 0; i < hdr->fw_size_in_items; i++)
|
||||
writel_relaxed(fw_val_arr[i], rsc->base + SE_GENI_CFG_RAMN + i * sizeof(u32));
|
||||
|
||||
/* Put default values on GENI's output pads. */
|
||||
writel_relaxed(0x1, rsc->base + GENI_FORCE_DEFAULT_REG);
|
||||
|
||||
/* High to low SCLK and HCLK to finish RAM. */
|
||||
geni_setbits32(rsc->base + GENI_CGC_CTRL, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
|
||||
GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK);
|
||||
geni_setbits32(rsc->base + SE_GENI_CLK_CTRL, GENI_CLK_CTRL_SER_CLK_SEL_BMSK);
|
||||
geni_clrbits32(rsc->base + GENI_CGC_CTRL, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
|
||||
GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK);
|
||||
|
||||
/* Serial engine DMA interface is enabled. */
|
||||
geni_setbits32(rsc->base + SE_DMA_IF_EN, DMA_IF_EN_DMA_IF_EN_BMSK);
|
||||
|
||||
/* Enable or disable FIFO interface of the serial engine. */
|
||||
if (rsc->mode == GENI_SE_FIFO)
|
||||
geni_clrbits32(rsc->base + SE_FIFO_IF_DISABLE, FIFO_IF_DISABLE);
|
||||
else
|
||||
geni_setbits32(rsc->base + SE_FIFO_IF_DISABLE, FIFO_IF_DISABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_phdr_valid() - Validate an ELF header.
|
||||
* @phdr: Pointer to the ELF header.
|
||||
*
|
||||
* Validate the ELF header by comparing the fields stored in p_flags and the payload type.
|
||||
*
|
||||
* Return: true if the validation is successful, false otherwise.
|
||||
*/
|
||||
static bool elf_phdr_valid(const Elf32_Phdr *phdr)
|
||||
{
|
||||
if (phdr->p_type != PT_LOAD || !phdr->p_memsz)
|
||||
return false;
|
||||
|
||||
if (MI_PBT_PAGE_MODE_VALUE(phdr->p_flags) == MI_PBT_NON_PAGED_SEGMENT &&
|
||||
MI_PBT_SEGMENT_TYPE_VALUE(phdr->p_flags) != MI_PBT_HASH_SEGMENT &&
|
||||
MI_PBT_ACCESS_TYPE_VALUE(phdr->p_flags) != MI_PBT_NOTUSED_SEGMENT &&
|
||||
MI_PBT_ACCESS_TYPE_VALUE(phdr->p_flags) != MI_PBT_SHARED_SEGMENT)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* valid_seg_size() - Validate the segment size.
|
||||
* @pelfseg: Pointer to the ELF header.
|
||||
* @p_filesz: Pointer to the file size.
|
||||
*
|
||||
* Validate the ELF segment size by comparing the file size.
|
||||
*
|
||||
* Return: true if the segment is valid, false if the segment is invalid.
|
||||
*/
|
||||
static bool valid_seg_size(struct elf_se_hdr *pelfseg, Elf32_Word p_filesz)
|
||||
{
|
||||
if (p_filesz >= pelfseg->fw_offset + pelfseg->fw_size_in_items * sizeof(u32) &&
|
||||
p_filesz >= pelfseg->cfg_idx_offset + pelfseg->cfg_size_in_items * sizeof(u8) &&
|
||||
p_filesz >= pelfseg->cfg_val_offset + pelfseg->cfg_size_in_items * sizeof(u32))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_elf() - Read an ELF file.
|
||||
* @rsc: Pointer to the SE resources structure.
|
||||
* @fw: Pointer to the firmware buffer.
|
||||
* @pelfseg: Pointer to the SE-specific ELF header.
|
||||
* @phdr: Pointer to one of the valid headers from the list in the firmware buffer.
|
||||
*
|
||||
* Read the ELF file and output a pointer to the header data, which contains the firmware data and
|
||||
* any other details.
|
||||
*
|
||||
* Return: 0 if successful, otherwise return an error value.
|
||||
*/
|
||||
static int read_elf(struct qup_se_rsc *rsc, const void *fw,
|
||||
struct elf_se_hdr **pelfseg)
|
||||
{
|
||||
Elf32_Phdr *phdr;
|
||||
const Elf32_Ehdr *ehdr = (const Elf32_Ehdr *)fw;
|
||||
Elf32_Phdr *phdrs = (Elf32_Phdr *)(ehdr + 1);
|
||||
const u8 *addr;
|
||||
int i;
|
||||
|
||||
ehdr = (Elf32_Ehdr *)fw;
|
||||
|
||||
if (ehdr->e_phnum < 2)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
phdr = &phdrs[i];
|
||||
if (!elf_phdr_valid(phdr))
|
||||
continue;
|
||||
|
||||
if (phdr->p_filesz >= sizeof(struct elf_se_hdr)) {
|
||||
addr = fw + phdr->p_offset;
|
||||
*pelfseg = (struct elf_se_hdr *)addr;
|
||||
|
||||
if ((*pelfseg)->magic == MAGIC_NUM_SE &&
|
||||
(*pelfseg)->version == 1 &&
|
||||
valid_seg_size(*pelfseg, phdr->p_filesz) &&
|
||||
(*pelfseg)->serial_protocol == rsc->protocol &&
|
||||
(*pelfseg)->serial_protocol != GENI_SE_NONE)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int qcom_geni_load_firmware(phys_addr_t qup_base,
|
||||
struct udevice *dev)
|
||||
{
|
||||
struct qup_se_rsc rsc;
|
||||
struct elf_se_hdr *hdr;
|
||||
int ret;
|
||||
void *fw;
|
||||
|
||||
rsc.dev = dev;
|
||||
rsc.base = qup_base;
|
||||
rsc.wrapper_base = dev_read_addr(dev->parent);
|
||||
|
||||
/* FIXME: GSI DMA mode if device has property qcom,gsi-dma-allowed */
|
||||
rsc.mode = GENI_SE_FIFO;
|
||||
|
||||
switch (device_get_uclass_id(dev)) {
|
||||
case UCLASS_I2C:
|
||||
rsc.protocol = GENI_SE_I2C;
|
||||
break;
|
||||
case UCLASS_SPI:
|
||||
rsc.protocol = GENI_SE_SPI;
|
||||
break;
|
||||
case UCLASS_SERIAL:
|
||||
rsc.protocol = GENI_SE_UART;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The firmware blob is the private data of the GENI wrapper (parent) */
|
||||
fw = dev_get_priv(dev->parent);
|
||||
|
||||
ret = read_elf(&rsc, fw, &hdr);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to read ELF: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "Loading QUP firmware...\n");
|
||||
|
||||
return load_se_firmware(&rsc, hdr);
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to determine if firmware loading is necessary. Best way to do that is to check the FW
|
||||
* revision of each QUP and see if it has already been loaded.
|
||||
*/
|
||||
static int geni_se_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
ofnode child;
|
||||
struct resource res;
|
||||
u32 proto;
|
||||
struct geni_se_plat *plat = dev_get_plat(dev);
|
||||
|
||||
plat->need_firmware_load = false;
|
||||
|
||||
dev_for_each_subnode(child, dev) {
|
||||
if (!ofnode_is_enabled(child))
|
||||
continue;
|
||||
|
||||
if (ofnode_read_resource(child, 0, &res))
|
||||
continue;
|
||||
|
||||
proto = readl(res.start + GENI_FW_REVISION_RO);
|
||||
proto &= FW_REV_PROTOCOL_MSK;
|
||||
proto >>= FW_REV_PROTOCOL_SHFT;
|
||||
|
||||
if (proto == GENI_SE_INVALID_PROTO)
|
||||
plat->need_firmware_load = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define QUPFW_PART_TYPE_GUID "21d1219f-2ed1-4ab4-930a-41a16ae75f7f"
|
||||
|
||||
static int find_qupfw_part(struct udevice **blk_dev, struct disk_partition *part_info)
|
||||
{
|
||||
struct blk_desc *desc;
|
||||
int ret, partnum;
|
||||
|
||||
uclass_foreach_dev_probe(UCLASS_BLK, *blk_dev) {
|
||||
if (device_get_uclass_id(*blk_dev) != UCLASS_BLK)
|
||||
continue;
|
||||
|
||||
desc = dev_get_uclass_plat(*blk_dev);
|
||||
if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
|
||||
continue;
|
||||
for (partnum = 1;; partnum++) {
|
||||
ret = part_get_info(desc, partnum, part_info);
|
||||
if (ret)
|
||||
break;
|
||||
if (!strcmp(part_info->type_guid, QUPFW_PART_TYPE_GUID))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int probe_children_load_firmware(struct udevice *dev)
|
||||
{
|
||||
struct geni_se_plat *plat;
|
||||
ofnode child;
|
||||
struct udevice *child_dev;
|
||||
struct resource res;
|
||||
u32 proto;
|
||||
int ret;
|
||||
|
||||
plat = dev_get_plat(dev);
|
||||
|
||||
dev_for_each_subnode(child, dev) {
|
||||
if (!ofnode_is_enabled(child))
|
||||
continue;
|
||||
|
||||
if (ofnode_read_resource(child, 0, &res))
|
||||
continue;
|
||||
|
||||
proto = readl(res.start + GENI_FW_REVISION_RO);
|
||||
proto &= FW_REV_PROTOCOL_MSK;
|
||||
proto >>= FW_REV_PROTOCOL_SHFT;
|
||||
|
||||
if (proto != GENI_SE_INVALID_PROTO)
|
||||
continue;
|
||||
|
||||
ret = 0;
|
||||
/* Find the device for this ofnode, or bind it */
|
||||
if (device_find_global_by_ofnode(child, &child_dev))
|
||||
ret = lists_bind_fdt(dev, child, &child_dev, NULL, false);
|
||||
if (ret) {
|
||||
/* Skip nodes that don't have drivers */
|
||||
debug("Failed to probe child %s: %d\n", ofnode_get_name(child), ret);
|
||||
continue;
|
||||
}
|
||||
debug("Probing child %s for fw loading\n", child_dev->name);
|
||||
device_probe(child_dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_FW_BUF_SIZE (128 * 1024)
|
||||
|
||||
/*
|
||||
* Load firmware for QCOM GENI peripherals from the dedicated partition on storage and bind/probe
|
||||
* all the peripheral devices that need firmware to be loaded.
|
||||
*/
|
||||
static int qcom_geni_fw_initialise(void)
|
||||
{
|
||||
debug("Loading firmware for QCOM GENI SE\n");
|
||||
struct udevice *geni_wrapper, *blk_dev;
|
||||
struct disk_partition part_info;
|
||||
int ret;
|
||||
void *fw_buf;
|
||||
size_t fw_size = MAX_FW_BUF_SIZE;
|
||||
struct geni_se_plat *plat;
|
||||
|
||||
/* Find the first GENI SE wrapper that needs fw loading */
|
||||
for (uclass_first_device(UCLASS_MISC, &geni_wrapper);
|
||||
geni_wrapper;
|
||||
uclass_next_device(&geni_wrapper)) {
|
||||
if (device_get_uclass_id(geni_wrapper) == UCLASS_MISC &&
|
||||
!strcmp(geni_wrapper->driver->name, "geni-se-qup")) {
|
||||
plat = dev_get_plat(geni_wrapper);
|
||||
if (plat->need_firmware_load)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!geni_wrapper) {
|
||||
pr_err("GENI SE wrapper not found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = find_qupfw_part(&blk_dev, &part_info);
|
||||
if (ret) {
|
||||
pr_err("QUP firmware partition not found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (part_info.size * part_info.blksz > MAX_FW_BUF_SIZE) {
|
||||
pr_err("Firmware partition too large\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
fw_size = part_info.size * part_info.blksz;
|
||||
|
||||
fw_buf = malloc(fw_size);
|
||||
if (!fw_buf) {
|
||||
pr_err("Failed to allocate buffer for firmware\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(fw_buf, 0, fw_size);
|
||||
|
||||
ret = blk_read(blk_dev, part_info.start, part_info.size, fw_buf);
|
||||
if (ret < 0) {
|
||||
pr_err("Failed to read firmware from partition\n");
|
||||
free(fw_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK! Firmware is loaded, now bind and probe remaining children. They will attempt to load
|
||||
* firmware during probe. Do this for each GENI SE wrapper that needs firmware loading.
|
||||
*/
|
||||
for (; geni_wrapper;
|
||||
uclass_next_device(&geni_wrapper)) {
|
||||
if (device_get_uclass_id(geni_wrapper) == UCLASS_MISC &&
|
||||
!strcmp(geni_wrapper->driver->name, "geni-se-qup")) {
|
||||
plat = dev_get_plat(geni_wrapper);
|
||||
if (plat->need_firmware_load) {
|
||||
dev_set_priv(geni_wrapper, fw_buf);
|
||||
probe_children_load_firmware(geni_wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qcom_geni_fw_initialise);
|
||||
|
||||
static const struct udevice_id geni_ids[] = {
|
||||
{ .compatible = "qcom,geni-se-qup" },
|
||||
{}
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(geni_se_qup) = {
|
||||
.name = "geni-se-qup",
|
||||
.id = UCLASS_MISC,
|
||||
.of_match = geni_ids,
|
||||
.of_to_plat = geni_se_of_to_plat,
|
||||
.plat_auto = sizeof(struct geni_se_plat),
|
||||
.flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
@ -1,8 +1,8 @@
|
||||
config MSM8916_USB_PHY
|
||||
bool "Qualcomm MSM8916 USB PHY support"
|
||||
depends on PHY
|
||||
bool
|
||||
select PHY
|
||||
help
|
||||
Support the USB PHY in msm8916
|
||||
Support the Qualcomm MSM8916 USB PHY
|
||||
|
||||
This PHY is found on qualcomm dragonboard410c development board.
|
||||
|
||||
|
||||
@ -221,6 +221,36 @@ static const struct qmp_ufs_init_tbl sm8150_ufsphy_hs_g4_rx[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x3c),
|
||||
};
|
||||
|
||||
static const struct qmp_ufs_init_tbl sm7150_ufsphy_rx[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5b),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59),
|
||||
};
|
||||
|
||||
static const struct qmp_ufs_init_tbl sm7150_ufsphy_pcs[] = {
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_SIGDET_CTRL2, 0x6f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_SYM_RESYNC_CTRL, 0x03),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_SIGDET_CTRL1, 0x0f),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff),
|
||||
QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
|
||||
};
|
||||
|
||||
static const struct qmp_ufs_init_tbl sm8150_ufsphy_serdes[] = {
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9),
|
||||
QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11),
|
||||
@ -1018,6 +1048,36 @@ static const struct qmp_ufs_cfg sm8150_ufsphy_cfg = {
|
||||
.no_pcs_sw_reset = false,
|
||||
};
|
||||
|
||||
static const struct qmp_ufs_cfg sm7150_ufsphy_cfg = {
|
||||
.lanes = 1,
|
||||
|
||||
.offsets = &qmp_ufs_offsets,
|
||||
|
||||
.tbls = {
|
||||
.serdes = sdm845_ufsphy_serdes,
|
||||
.serdes_num = ARRAY_SIZE(sdm845_ufsphy_serdes),
|
||||
.tx = sdm845_ufsphy_tx,
|
||||
.tx_num = ARRAY_SIZE(sdm845_ufsphy_tx),
|
||||
.rx = sm7150_ufsphy_rx,
|
||||
.rx_num = ARRAY_SIZE(sm7150_ufsphy_rx),
|
||||
.pcs = sm7150_ufsphy_pcs,
|
||||
.pcs_num = ARRAY_SIZE(sm7150_ufsphy_pcs),
|
||||
},
|
||||
.tbls_hs_b = {
|
||||
.serdes = sdm845_ufsphy_hs_b_serdes,
|
||||
.serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
|
||||
},
|
||||
.clk_list = sdm845_ufs_phy_clk_l,
|
||||
.num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
|
||||
.vreg_list = qmp_ufs_vreg_l,
|
||||
.num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
|
||||
.reset_list = qmp_ufs_reset_l,
|
||||
.num_resets = ARRAY_SIZE(qmp_ufs_reset_l),
|
||||
.regs = ufsphy_v3_regs_layout,
|
||||
|
||||
.no_pcs_sw_reset = true,
|
||||
};
|
||||
|
||||
static const struct qmp_ufs_cfg sm8250_ufsphy_cfg = {
|
||||
.lanes = 2,
|
||||
|
||||
@ -1593,6 +1653,8 @@ static struct phy_ops qmp_ufs_ops = {
|
||||
static const struct udevice_id qmp_ufs_ids[] = {
|
||||
{ .compatible = "qcom,sa8775p-qmp-ufs-phy", .data = (ulong)&sa8775p_ufsphy_cfg, },
|
||||
{ .compatible = "qcom,sdm845-qmp-ufs-phy", .data = (ulong)&sdm845_ufsphy_cfg },
|
||||
{ .compatible = "qcom,sm6350-qmp-ufs-phy", .data = (ulong)&sdm845_ufsphy_cfg },
|
||||
{ .compatible = "qcom,sm7150-qmp-ufs-phy", .data = (ulong)&sm7150_ufsphy_cfg },
|
||||
{ .compatible = "qcom,sm8150-qmp-ufs-phy", .data = (ulong)&sm8150_ufsphy_cfg },
|
||||
{ .compatible = "qcom,sm8250-qmp-ufs-phy", .data = (ulong)&sm8250_ufsphy_cfg },
|
||||
{ .compatible = "qcom,qcs8300-qmp-ufs-phy", .data = (ulong)&sa8775p_ufsphy_cfg },
|
||||
|
||||
@ -68,6 +68,13 @@ config PINCTRL_QCOM_SC7280
|
||||
help
|
||||
Say Y here to enable support for pinctrl on the Snapdragon SC7280 SoC,
|
||||
|
||||
config PINCTRL_QCOM_SDM670
|
||||
bool "Qualcomm SDM670 Pinctrl"
|
||||
select PINCTRL_QCOM
|
||||
help
|
||||
Say Y here to enable support for pinctrl on the Snapdragon SDM670 SoC,
|
||||
as well as the associated GPIO driver.
|
||||
|
||||
config PINCTRL_QCOM_SDM660
|
||||
bool "Qualcomm SDM630/660 Pinctrl"
|
||||
select PINCTRL_QCOM
|
||||
@ -89,6 +96,19 @@ config PINCTRL_QCOM_SM6115
|
||||
Say Y here to enable support for pinctrl on the Snapdragon SM6115 SoC,
|
||||
as well as the associated GPIO driver.
|
||||
|
||||
config PINCTRL_QCOM_SM6350
|
||||
bool "Qualcomm SM6350 Pinctrl"
|
||||
select PINCTRL_QCOM
|
||||
help
|
||||
Say Y here to enable support for pinctrl on the Snapdragon SM6350 SoC,
|
||||
|
||||
config PINCTRL_QCOM_SM7150
|
||||
bool "Qualcomm SM7150 GCC"
|
||||
select PINCTRL_QCOM
|
||||
help
|
||||
Say Y here to enable support for pinctrl on the Snapdragon SM7150 SoC,
|
||||
as well as the associated GPIO driver.
|
||||
|
||||
config PINCTRL_QCOM_SM8150
|
||||
bool "Qualcomm SM8150 Pinctrl"
|
||||
select PINCTRL_QCOM
|
||||
|
||||
@ -13,8 +13,11 @@ obj-$(CONFIG_PINCTRL_QCOM_QCS404) += pinctrl-qcs404.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SA8775P) += pinctrl-sa8775p.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SC7280) += pinctrl-sc7280.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SDM660) += pinctrl-sdm660.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SDM670) += pinctrl-sdm670.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SDM845) += pinctrl-sdm845.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SM6350) += pinctrl-sm6350.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SM7150) += pinctrl-sm7150.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SM8250) += pinctrl-sm8250.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SM8550) += pinctrl-sm8550.o
|
||||
|
||||
@ -10,10 +10,6 @@
|
||||
|
||||
#include "pinctrl-qcom.h"
|
||||
|
||||
#define WEST 0x00000000
|
||||
#define SOUTH 0x00400000
|
||||
#define NORTH 0x00800000
|
||||
|
||||
#define MAX_PIN_NAME_LEN 32
|
||||
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
|
||||
|
||||
@ -47,7 +43,7 @@ static const struct pinctrl_function msm_pinctrl_functions[] = {
|
||||
}
|
||||
|
||||
static const struct msm_special_pin_data sc7280_special_pins_data[] = {
|
||||
[0] = UFS_RESET("ufs_reset", SOUTH + 0xbe000),
|
||||
[0] = UFS_RESET("ufs_reset", 0xbe000),
|
||||
[1] = SDC_PINGROUP("sdc1_rclk", 0xb3004, 0, 6),
|
||||
[2] = SDC_PINGROUP("sdc1_clk", 0xb3000, 13, 6),
|
||||
[3] = SDC_PINGROUP("sdc1_cmd", 0xb3000, 11, 3),
|
||||
|
||||
247
drivers/pinctrl/qcom/pinctrl-sdm670.c
Normal file
247
drivers/pinctrl/qcom/pinctrl-sdm670.c
Normal file
@ -0,0 +1,247 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Qualcomm SDM670 pinctrl
|
||||
*
|
||||
* (C) Copyright 2025 David Wronek <david.wronek@mainlining.org>
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include "pinctrl-qcom.h"
|
||||
|
||||
#define NORTH 0x00500000
|
||||
#define SOUTH 0x00900000
|
||||
#define WEST 0x00100000
|
||||
|
||||
#define MAX_PIN_NAME_LEN 32
|
||||
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
|
||||
|
||||
static const struct pinctrl_function sdm670_pinctrl_functions[] = {
|
||||
{ "gpio", 0 },
|
||||
{ "blsp_uart2", 3 }, /* gpio 4 and 5, used for debug uart */
|
||||
};
|
||||
|
||||
static const unsigned int sdm670_pin_offsets[] = {
|
||||
[0] = SOUTH,
|
||||
[1] = SOUTH,
|
||||
[2] = SOUTH,
|
||||
[3] = SOUTH,
|
||||
[4] = NORTH,
|
||||
[5] = NORTH,
|
||||
[6] = NORTH,
|
||||
[7] = NORTH,
|
||||
[8] = WEST,
|
||||
[9] = WEST,
|
||||
[10] = NORTH,
|
||||
[11] = NORTH,
|
||||
[12] = SOUTH,
|
||||
[13] = WEST,
|
||||
[14] = WEST,
|
||||
[15] = WEST,
|
||||
[16] = WEST,
|
||||
[17] = WEST,
|
||||
[18] = WEST,
|
||||
[19] = WEST,
|
||||
[20] = WEST,
|
||||
[21] = WEST,
|
||||
[22] = WEST,
|
||||
[23] = WEST,
|
||||
[24] = WEST,
|
||||
[25] = WEST,
|
||||
[26] = WEST,
|
||||
[27] = WEST,
|
||||
[28] = WEST,
|
||||
[29] = WEST,
|
||||
[30] = WEST,
|
||||
[31] = WEST,
|
||||
[32] = WEST,
|
||||
[33] = WEST,
|
||||
[34] = WEST,
|
||||
[35] = NORTH,
|
||||
[36] = NORTH,
|
||||
[37] = NORTH,
|
||||
[38] = NORTH,
|
||||
[39] = NORTH,
|
||||
[40] = NORTH,
|
||||
[41] = SOUTH,
|
||||
[42] = SOUTH,
|
||||
[43] = SOUTH,
|
||||
[44] = SOUTH,
|
||||
[45] = SOUTH,
|
||||
[46] = SOUTH,
|
||||
[47] = SOUTH,
|
||||
[48] = SOUTH,
|
||||
[49] = NORTH,
|
||||
[50] = NORTH,
|
||||
[51] = NORTH,
|
||||
[52] = NORTH,
|
||||
[53] = NORTH,
|
||||
[54] = NORTH,
|
||||
[55] = NORTH,
|
||||
[56] = NORTH,
|
||||
[57] = NORTH,
|
||||
[65] = NORTH,
|
||||
[66] = NORTH,
|
||||
[67] = NORTH,
|
||||
[68] = NORTH,
|
||||
[75] = NORTH,
|
||||
[76] = NORTH,
|
||||
[77] = NORTH,
|
||||
[78] = NORTH,
|
||||
[79] = NORTH,
|
||||
[80] = NORTH,
|
||||
[81] = NORTH,
|
||||
[82] = NORTH,
|
||||
[83] = NORTH,
|
||||
[84] = NORTH,
|
||||
[85] = SOUTH,
|
||||
[86] = SOUTH,
|
||||
[87] = SOUTH,
|
||||
[88] = SOUTH,
|
||||
[89] = SOUTH,
|
||||
[90] = SOUTH,
|
||||
[91] = SOUTH,
|
||||
[92] = SOUTH,
|
||||
[93] = SOUTH,
|
||||
[94] = SOUTH,
|
||||
[95] = SOUTH,
|
||||
[96] = SOUTH,
|
||||
[97] = WEST,
|
||||
[98] = WEST,
|
||||
[99] = NORTH,
|
||||
[100] = WEST,
|
||||
[101] = WEST,
|
||||
[102] = WEST,
|
||||
[103] = WEST,
|
||||
[105] = NORTH,
|
||||
[106] = NORTH,
|
||||
[107] = NORTH,
|
||||
[108] = NORTH,
|
||||
[109] = NORTH,
|
||||
[110] = NORTH,
|
||||
[111] = NORTH,
|
||||
[112] = NORTH,
|
||||
[113] = NORTH,
|
||||
[114] = WEST,
|
||||
[115] = WEST,
|
||||
[116] = SOUTH,
|
||||
[117] = NORTH,
|
||||
[118] = NORTH,
|
||||
[119] = NORTH,
|
||||
[120] = NORTH,
|
||||
[121] = NORTH,
|
||||
[122] = NORTH,
|
||||
[123] = NORTH,
|
||||
[124] = NORTH,
|
||||
[125] = NORTH,
|
||||
[126] = NORTH,
|
||||
[127] = WEST,
|
||||
[128] = WEST,
|
||||
[129] = WEST,
|
||||
[130] = WEST,
|
||||
[131] = WEST,
|
||||
[132] = WEST,
|
||||
[133] = NORTH,
|
||||
[134] = NORTH,
|
||||
[135] = WEST,
|
||||
[136] = WEST,
|
||||
[137] = WEST,
|
||||
[138] = WEST,
|
||||
[139] = WEST,
|
||||
[140] = WEST,
|
||||
[141] = WEST,
|
||||
[142] = WEST,
|
||||
[143] = WEST,
|
||||
[144] = SOUTH,
|
||||
[145] = SOUTH,
|
||||
[146] = WEST,
|
||||
[147] = WEST,
|
||||
[148] = WEST,
|
||||
[149] = WEST,
|
||||
};
|
||||
|
||||
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
|
||||
{ \
|
||||
.name = pg_name, \
|
||||
.ctl_reg = ctl, \
|
||||
.io_reg = 0, \
|
||||
.pull_bit = pull, \
|
||||
.drv_bit = drv, \
|
||||
.oe_bit = -1, \
|
||||
.in_bit = -1, \
|
||||
.out_bit = -1, \
|
||||
}
|
||||
|
||||
#define UFS_RESET(pg_name, offset) \
|
||||
{ \
|
||||
.name = pg_name, \
|
||||
.ctl_reg = offset, \
|
||||
.io_reg = offset + 0x4, \
|
||||
.pull_bit = 3, \
|
||||
.drv_bit = 0, \
|
||||
.oe_bit = -1, \
|
||||
.in_bit = -1, \
|
||||
.out_bit = 0, \
|
||||
}
|
||||
|
||||
static const struct msm_special_pin_data sdm670_special_pins_data[] = {
|
||||
UFS_RESET("ufs_reset", 0x99d000),
|
||||
SDC_QDSD_PINGROUP("sdc1_rclk", NORTH + 0x99000, 15, 0),
|
||||
SDC_QDSD_PINGROUP("sdc1_clk", NORTH + 0x99000, 13, 6),
|
||||
SDC_QDSD_PINGROUP("sdc1_cmd", NORTH + 0x99000, 11, 3),
|
||||
SDC_QDSD_PINGROUP("sdc1_data", NORTH + 0x99000, 9, 0),
|
||||
SDC_QDSD_PINGROUP("sdc2_clk", NORTH + 0x9a000, 14, 6),
|
||||
SDC_QDSD_PINGROUP("sdc2_cmd", NORTH + 0x9a000, 11, 3),
|
||||
SDC_QDSD_PINGROUP("sdc2_data", NORTH + 0x9a000, 9, 0),
|
||||
};
|
||||
|
||||
static const char *sdm670_get_function_name(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
return sdm670_pinctrl_functions[selector].name;
|
||||
}
|
||||
|
||||
static const char *sdm670_get_pin_name(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
if (selector >= 150 && selector <= 157)
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN,
|
||||
sdm670_special_pins_data[selector - 150].name);
|
||||
else
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
|
||||
|
||||
return pin_name;
|
||||
}
|
||||
|
||||
static int sdm670_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
|
||||
{
|
||||
if (selector >= 0 && selector < ARRAY_SIZE(sdm670_pinctrl_functions))
|
||||
return sdm670_pinctrl_functions[selector].val;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct msm_pinctrl_data sdm670_data = {
|
||||
.pin_data = {
|
||||
.pin_offsets = sdm670_pin_offsets,
|
||||
.pin_count = ARRAY_SIZE(sdm670_pin_offsets) + ARRAY_SIZE(sdm670_special_pins_data),
|
||||
.special_pins_start = 150,
|
||||
.special_pins_data = sdm670_special_pins_data,
|
||||
},
|
||||
.functions_count = ARRAY_SIZE(sdm670_pinctrl_functions),
|
||||
.get_function_name = sdm670_get_function_name,
|
||||
.get_function_mux = sdm670_get_function_mux,
|
||||
.get_pin_name = sdm670_get_pin_name,
|
||||
};
|
||||
|
||||
static const struct udevice_id msm_pinctrl_ids[] = {
|
||||
{
|
||||
.compatible = "qcom,sdm670-tlmm",
|
||||
.data = (ulong)&sdm670_data
|
||||
},
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pinctrl_ssdm670) = {
|
||||
.name = "pinctrl_sdm670",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = msm_pinctrl_ids,
|
||||
.ops = &msm_pinctrl_ops,
|
||||
.bind = msm_pinctrl_bind,
|
||||
};
|
||||
104
drivers/pinctrl/qcom/pinctrl-sm6350.c
Normal file
104
drivers/pinctrl/qcom/pinctrl-sm6350.c
Normal file
@ -0,0 +1,104 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Qualcomm sm6350 pinctrl
|
||||
*
|
||||
* (C) Copyright 2024 Linaro Ltd.
|
||||
* (C) Copyright 2025 Luca Weiss <luca.weiss@fairphone.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
|
||||
#include "pinctrl-qcom.h"
|
||||
|
||||
#define MAX_PIN_NAME_LEN 32
|
||||
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
|
||||
|
||||
static const struct pinctrl_function msm_pinctrl_functions[] = {
|
||||
{"qup13_f2", 1},
|
||||
{"gpio", 0},
|
||||
};
|
||||
|
||||
#define SDC_PINGROUP(pg_name, ctl, pull, drv) \
|
||||
{ \
|
||||
.name = pg_name, \
|
||||
.ctl_reg = ctl, \
|
||||
.io_reg = 0, \
|
||||
.pull_bit = pull, \
|
||||
.drv_bit = drv, \
|
||||
.oe_bit = -1, \
|
||||
.in_bit = -1, \
|
||||
.out_bit = -1, \
|
||||
}
|
||||
|
||||
#define UFS_RESET(pg_name, offset) \
|
||||
{ \
|
||||
.name = pg_name, \
|
||||
.ctl_reg = offset, \
|
||||
.io_reg = offset + 0x4, \
|
||||
.pull_bit = 3, \
|
||||
.drv_bit = 0, \
|
||||
.oe_bit = -1, \
|
||||
.in_bit = -1, \
|
||||
.out_bit = 0, \
|
||||
}
|
||||
|
||||
static const struct msm_special_pin_data sm6350_special_pins_data[] = {
|
||||
[0] = UFS_RESET("ufs_reset", 0xae000),
|
||||
[1] = SDC_PINGROUP("sdc1_rclk", 0xa1000, 15, 0),
|
||||
[2] = SDC_PINGROUP("sdc1_clk", 0xa0000, 13, 6),
|
||||
[3] = SDC_PINGROUP("sdc1_cmd", 0xa0000, 11, 3),
|
||||
[4] = SDC_PINGROUP("sdc1_data", 0xa0000, 9, 0),
|
||||
[5] = SDC_PINGROUP("sdc2_clk", 0xa2000, 14, 6),
|
||||
[6] = SDC_PINGROUP("sdc2_cmd", 0xa2000, 11, 3),
|
||||
[7] = SDC_PINGROUP("sdc2_data", 0xa2000, 9, 0),
|
||||
};
|
||||
|
||||
static const char *sm6350_get_function_name(struct udevice *dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
return msm_pinctrl_functions[selector].name;
|
||||
}
|
||||
|
||||
static const char *sm6350_get_pin_name(struct udevice *dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector >= 156 && selector <= 163)
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN,
|
||||
sm6350_special_pins_data[selector - 156].name);
|
||||
else
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
|
||||
|
||||
return pin_name;
|
||||
}
|
||||
|
||||
static int sm6350_get_function_mux(__maybe_unused unsigned int pin,
|
||||
unsigned int selector)
|
||||
{
|
||||
return msm_pinctrl_functions[selector].val;
|
||||
}
|
||||
|
||||
static struct msm_pinctrl_data sm6350_data = {
|
||||
.pin_data = {
|
||||
.pin_count = 164,
|
||||
.special_pins_start = 156,
|
||||
.special_pins_data = sm6350_special_pins_data,
|
||||
},
|
||||
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
|
||||
.get_function_name = sm6350_get_function_name,
|
||||
.get_function_mux = sm6350_get_function_mux,
|
||||
.get_pin_name = sm6350_get_pin_name,
|
||||
};
|
||||
|
||||
static const struct udevice_id msm_pinctrl_ids[] = {
|
||||
{ .compatible = "qcom,sm6350-tlmm", .data = (ulong)&sm6350_data },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pinctrl_sm6350) = {
|
||||
.name = "pinctrl_sm6350",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = msm_pinctrl_ids,
|
||||
.ops = &msm_pinctrl_ops,
|
||||
.bind = msm_pinctrl_bind,
|
||||
};
|
||||
142
drivers/pinctrl/qcom/pinctrl-sm7150.c
Normal file
142
drivers/pinctrl/qcom/pinctrl-sm7150.c
Normal file
@ -0,0 +1,142 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Pinctrl driver for Qualcomm SM7150
|
||||
*
|
||||
* (C) Copyright 2025 Danila Tikhonov <danila@jiaxyga.com>
|
||||
* (C) Copyright 2025 Jens Reidel <adrian@mainlining.org>
|
||||
*
|
||||
* Based on Linux Kernel driver
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
|
||||
#include "pinctrl-qcom.h"
|
||||
|
||||
#define WEST 0x00000000
|
||||
#define NORTH 0x00400000
|
||||
#define SOUTH 0x00800000
|
||||
|
||||
#define MAX_PIN_NAME_LEN 32
|
||||
static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
|
||||
|
||||
static const struct pinctrl_function msm_pinctrl_functions[] = {
|
||||
{ "qup12", 1 },
|
||||
{ "gpio", 0 },
|
||||
{ "sdc2_clk", 0 } /* special pin GPIO124 */
|
||||
};
|
||||
|
||||
#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
|
||||
{ \
|
||||
.name = pg_name, \
|
||||
.ctl_reg = ctl, \
|
||||
.io_reg = 0, \
|
||||
.pull_bit = pull, \
|
||||
.drv_bit = drv, \
|
||||
.oe_bit = -1, \
|
||||
.in_bit = -1, \
|
||||
.out_bit = -1, \
|
||||
}
|
||||
|
||||
#define UFS_RESET(pg_name, offset) \
|
||||
{ \
|
||||
.name = pg_name, \
|
||||
.ctl_reg = offset, \
|
||||
.io_reg = offset + 0x4, \
|
||||
.pull_bit = 3, \
|
||||
.drv_bit = 0, \
|
||||
.oe_bit = -1, \
|
||||
.in_bit = -1, \
|
||||
.out_bit = 0, \
|
||||
}
|
||||
|
||||
static const struct msm_special_pin_data msm_special_pins_data[] = {
|
||||
[0] = UFS_RESET("ufs_reset", 0x9f000),
|
||||
[1] = SDC_QDSD_PINGROUP("sdc1_rclk", WEST + 0x9a000, 15, 0),
|
||||
[2] = SDC_QDSD_PINGROUP("sdc1_clk", WEST + 0x9a000, 13, 6),
|
||||
[3] = SDC_QDSD_PINGROUP("sdc1_cmd", WEST + 0x9a000, 11, 3),
|
||||
[4] = SDC_QDSD_PINGROUP("sdc1_data", WEST + 0x9a000, 9, 0),
|
||||
[5] = SDC_QDSD_PINGROUP("sdc2_clk", SOUTH + 0x98000, 14, 6),
|
||||
[6] = SDC_QDSD_PINGROUP("sdc2_cmd", SOUTH + 0x98000, 11, 3),
|
||||
[7] = SDC_QDSD_PINGROUP("sdc2_data", SOUTH + 0x98000, 9, 0),
|
||||
};
|
||||
|
||||
static const unsigned int sm7150_pin_offsets[] = {
|
||||
[0] = SOUTH, [1] = SOUTH, [2] = SOUTH, [3] = SOUTH,
|
||||
[4] = NORTH, [5] = NORTH, [6] = NORTH, [7] = NORTH,
|
||||
[8] = NORTH, [9] = NORTH, [10] = NORTH, [11] = NORTH,
|
||||
[12] = SOUTH, [13] = SOUTH, [14] = SOUTH, [15] = SOUTH,
|
||||
[16] = SOUTH, [17] = SOUTH, [18] = SOUTH, [19] = SOUTH,
|
||||
[20] = SOUTH, [21] = SOUTH, [22] = SOUTH, [23] = SOUTH,
|
||||
[24] = SOUTH, [25] = SOUTH, [26] = SOUTH, [27] = SOUTH,
|
||||
[28] = SOUTH, [29] = NORTH, [30] = SOUTH, [31] = WEST,
|
||||
[32] = NORTH, [33] = NORTH, [34] = SOUTH, [35] = SOUTH,
|
||||
[36] = SOUTH, [37] = SOUTH, [38] = SOUTH, [39] = SOUTH,
|
||||
[40] = SOUTH, [41] = SOUTH, [42] = NORTH, [43] = NORTH,
|
||||
[44] = NORTH, [45] = NORTH, [46] = NORTH, [47] = NORTH,
|
||||
[48] = WEST, [49] = WEST, [50] = WEST, [51] = WEST,
|
||||
[52] = WEST, [53] = WEST, [54] = WEST, [55] = WEST,
|
||||
[56] = WEST, [57] = WEST, [58] = WEST, [59] = NORTH,
|
||||
[60] = NORTH, [61] = NORTH, [62] = NORTH, [63] = NORTH,
|
||||
[64] = NORTH, [65] = NORTH, [66] = NORTH, [67] = NORTH,
|
||||
[68] = NORTH, [69] = NORTH, [70] = NORTH, [71] = NORTH,
|
||||
[72] = NORTH, [73] = NORTH, [74] = WEST, [75] = WEST,
|
||||
[76] = WEST, [77] = WEST, [78] = WEST, [79] = WEST,
|
||||
[80] = WEST, [81] = WEST, [82] = WEST, [83] = WEST,
|
||||
[84] = WEST, [85] = WEST, [86] = NORTH, [87] = NORTH,
|
||||
[88] = NORTH, [89] = NORTH, [90] = NORTH, [91] = NORTH,
|
||||
[92] = NORTH, [93] = NORTH, [94] = SOUTH, [95] = WEST,
|
||||
[96] = WEST, [97] = WEST, [98] = WEST, [99] = WEST,
|
||||
[100] = WEST, [101] = NORTH, [102] = NORTH, [103] = NORTH,
|
||||
[104] = WEST, [105] = NORTH, [106] = NORTH, [107] = WEST,
|
||||
[108] = SOUTH, [109] = SOUTH, [110] = NORTH, [111] = NORTH,
|
||||
[112] = NORTH, [113] = NORTH, [114] = NORTH, [115] = NORTH,
|
||||
[116] = NORTH, [117] = NORTH, [118] = NORTH,
|
||||
};
|
||||
|
||||
static const char *sm7150_get_function_name(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
return msm_pinctrl_functions[selector].name;
|
||||
}
|
||||
|
||||
static const char *sm7150_get_pin_name(struct udevice *dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector >= 119 && selector <= 126)
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN,
|
||||
msm_special_pins_data[selector - 119].name);
|
||||
else
|
||||
snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
|
||||
|
||||
return pin_name;
|
||||
}
|
||||
|
||||
static int sm7150_get_function_mux(__maybe_unused unsigned int pin, unsigned int selector)
|
||||
{
|
||||
return msm_pinctrl_functions[selector].val;
|
||||
}
|
||||
|
||||
static struct msm_pinctrl_data sm7150_data = {
|
||||
.pin_data = {
|
||||
.pin_offsets = sm7150_pin_offsets,
|
||||
.pin_count = 126,
|
||||
.special_pins_start = 119,
|
||||
.special_pins_data = msm_special_pins_data,
|
||||
},
|
||||
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
|
||||
.get_function_name = sm7150_get_function_name,
|
||||
.get_function_mux = sm7150_get_function_mux,
|
||||
.get_pin_name = sm7150_get_pin_name,
|
||||
};
|
||||
|
||||
static const struct udevice_id msm_pinctrl_ids[] = {
|
||||
{ .compatible = "qcom,sm7150-tlmm", .data = (ulong)&sm7150_data },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pinctrl_sm7150) = {
|
||||
.name = "pinctrl_sm7150",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = msm_pinctrl_ids,
|
||||
.ops = &msm_pinctrl_ops,
|
||||
.bind = msm_pinctrl_bind,
|
||||
};
|
||||
@ -456,6 +456,16 @@ static const struct rpmh_vreg_hw_data pmic5_pldo_lv = {
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_hw_data pmic5_nldo = {
|
||||
.regulator_type = VRM,
|
||||
.ops = &rpmh_regulator_vrm_drms_ops,
|
||||
.voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 123, 8000),
|
||||
.n_voltages = 124,
|
||||
.hpm_min_load_uA = 30000,
|
||||
.pmic_mode_map = pmic_mode_map_pmic5_ldo,
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_hw_data pmic5_nldo515 = {
|
||||
.regulator_type = VRM,
|
||||
.ops = &rpmh_regulator_vrm_drms_ops,
|
||||
@ -493,6 +503,23 @@ static const struct rpmh_vreg_hw_data pmic5_pldo515_mv = {
|
||||
.supply_name = _supply_name, \
|
||||
}
|
||||
|
||||
static const struct rpmh_vreg_init_data pm6150l_vreg_data[] = {
|
||||
/* smps1 - smps8 are not added to u-boot yet */
|
||||
RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"),
|
||||
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"),
|
||||
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"),
|
||||
RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"),
|
||||
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"),
|
||||
RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"),
|
||||
RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"),
|
||||
RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo, "vdd-l1-l8"),
|
||||
RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"),
|
||||
RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"),
|
||||
RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"),
|
||||
RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_init_data pm8150_vreg_data[] = {
|
||||
RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l13-l16-l17"),
|
||||
{}
|
||||
@ -705,6 +732,10 @@ static int rpmh_regulators_bind(struct udevice *dev)
|
||||
}
|
||||
|
||||
static const struct udevice_id rpmh_regulator_ids[] = {
|
||||
{
|
||||
.compatible = "qcom,pm6150l-rpmh-regulators",
|
||||
.data = (ulong)pm6150l_vreg_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm8150-rpmh-regulators",
|
||||
.data = (ulong)pm8150_vreg_data,
|
||||
|
||||
@ -328,7 +328,7 @@ config DEBUG_UART_MSM
|
||||
be available until the real driver-model serial is running.
|
||||
|
||||
config DEBUG_UART_MSM_GENI
|
||||
bool "Qualcomm snapdragon"
|
||||
bool "Qualcomm GENI UART debug"
|
||||
depends on ARCH_SNAPDRAGON
|
||||
help
|
||||
Select this to enable a debug UART using the serial_msm driver. You
|
||||
@ -1001,6 +1001,7 @@ config MSM_SERIAL
|
||||
|
||||
config MSM_GENI_SERIAL
|
||||
bool "Qualcomm on-chip GENI UART"
|
||||
depends on QCOM_GENI
|
||||
help
|
||||
Support UART based on Generic Interface (GENI) Serial Engine (SE),
|
||||
used on Qualcomm Snapdragon SoCs. Should support all qualcomm SOCs
|
||||
|
||||
@ -17,20 +17,17 @@
|
||||
#include <asm/global_data.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/delay.h>
|
||||
#include <dm/pinctrl.h>
|
||||
|
||||
/* Serial registers - this driver works in uartdm mode*/
|
||||
|
||||
#define UARTDM_DMRX 0x34 /* Max RX transfer length */
|
||||
#define UARTDM_DMEN 0x3C /* DMA/data-packing mode */
|
||||
#define UARTDM_NCF_TX 0x40 /* Number of chars to TX */
|
||||
#define UARTDM_DMEN 0x3C /* DMA/data-packing mode */
|
||||
#define UARTDM_DMEN_TXRX_SC_ENABLE (BIT(4) | BIT(5))
|
||||
|
||||
#define UARTDM_RXFS 0x50 /* RX channel status register */
|
||||
#define UARTDM_RXFS_BUF_SHIFT 0x7 /* Number of bytes in the packing buffer */
|
||||
#define UARTDM_RXFS_BUF_MASK 0x7
|
||||
#define UARTDM_MR1 0x00
|
||||
#define UARTDM_MR1_RX_RDY_CTL BIT(7)
|
||||
#define UARTDM_MR2 0x04
|
||||
#define UARTDM_MR2_8_N_1_MODE 0x34
|
||||
/*
|
||||
* This is documented on page 1817 of the apq8016e technical reference manual.
|
||||
* section 6.2.5.3.26
|
||||
@ -44,119 +41,56 @@
|
||||
#define UARTDM_CSR 0xA0
|
||||
|
||||
#define UARTDM_SR 0xA4 /* Status register */
|
||||
#define UARTDM_SR_RX_READY (1 << 0) /* Word is the receiver FIFO */
|
||||
#define UARTDM_SR_RX_READY (1 << 0) /* Receiver FIFO has data */
|
||||
#define UARTDM_SR_TX_READY (1 << 2) /* Transmitter FIFO has space */
|
||||
#define UARTDM_SR_TX_EMPTY (1 << 3) /* Transmitter underrun */
|
||||
#define UARTDM_SR_UART_OVERRUN (1 << 4) /* Receive overrun */
|
||||
|
||||
#define UARTDM_CR 0xA8 /* Command register */
|
||||
#define UARTDM_CR_CMD_RESET_ERR (3 << 4) /* Clear overrun error */
|
||||
#define UARTDM_CR_CMD_RESET_STALE_INT (8 << 4) /* Clears stale irq */
|
||||
#define UARTDM_CR_CMD_RESET_TX_READY (3 << 8) /* Clears TX Ready irq*/
|
||||
#define UARTDM_CR_CMD_FORCE_STALE (4 << 8) /* Causes stale event */
|
||||
#define UARTDM_CR_CMD_STALE_EVENT_DISABLE (6 << 8) /* Disable stale event */
|
||||
|
||||
#define UARTDM_IMR 0xB0 /* Interrupt mask register */
|
||||
#define UARTDM_ISR 0xB4 /* Interrupt status register */
|
||||
#define UARTDM_ISR_TX_READY 0x80 /* TX FIFO empty */
|
||||
#define UARTDM_CR_RX_ENABLE (1 << 0) /* Enable receiver */
|
||||
#define UARTDM_CR_TX_ENABLE (1 << 2) /* Enable transmitter */
|
||||
#define UARTDM_CR_CMD_RESET_RX (1 << 4) /* Reset receiver */
|
||||
#define UARTDM_CR_CMD_RESET_TX (2 << 4) /* Reset transmitter */
|
||||
|
||||
#define UARTDM_TF 0x100 /* UART Transmit FIFO register */
|
||||
#define UARTDM_RF 0x140 /* UART Receive FIFO register */
|
||||
|
||||
#define MSM_BOOT_UART_DM_8_N_1_MODE 0x34
|
||||
#define MSM_BOOT_UART_DM_CMD_RESET_RX 0x10
|
||||
#define MSM_BOOT_UART_DM_CMD_RESET_TX 0x20
|
||||
#define MSM_UART_MR1_RX_RDY_CTL BIT(7)
|
||||
#define UARTDM_RF_CHAR 0xff /* higher bits contain error information */
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct msm_serial_data {
|
||||
phys_addr_t base;
|
||||
unsigned chars_cnt; /* number of buffered chars */
|
||||
uint32_t chars_buf; /* buffered chars */
|
||||
uint32_t clk_rate; /* core clock rate */
|
||||
};
|
||||
|
||||
static int msm_serial_fetch(struct udevice *dev)
|
||||
{
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
unsigned sr;
|
||||
|
||||
if (priv->chars_cnt)
|
||||
return priv->chars_cnt;
|
||||
|
||||
/* Clear error in case of buffer overrun */
|
||||
if (readl(priv->base + UARTDM_SR) & UARTDM_SR_UART_OVERRUN)
|
||||
writel(UARTDM_CR_CMD_RESET_ERR, priv->base + UARTDM_CR);
|
||||
|
||||
/* We need to fetch new character */
|
||||
sr = readl(priv->base + UARTDM_SR);
|
||||
|
||||
if (sr & UARTDM_SR_RX_READY) {
|
||||
/* There are at least 4 bytes in fifo */
|
||||
priv->chars_buf = readl(priv->base + UARTDM_RF);
|
||||
priv->chars_cnt = 4;
|
||||
} else {
|
||||
/* Check if there is anything in fifo */
|
||||
priv->chars_cnt = readl(priv->base + UARTDM_RXFS);
|
||||
/* Extract number of characters in UART packing buffer*/
|
||||
priv->chars_cnt = (priv->chars_cnt >>
|
||||
UARTDM_RXFS_BUF_SHIFT) &
|
||||
UARTDM_RXFS_BUF_MASK;
|
||||
if (!priv->chars_cnt)
|
||||
return 0;
|
||||
|
||||
/* There is at least one charcter, move it to fifo */
|
||||
writel(UARTDM_CR_CMD_FORCE_STALE,
|
||||
priv->base + UARTDM_CR);
|
||||
|
||||
priv->chars_buf = readl(priv->base + UARTDM_RF);
|
||||
writel(UARTDM_CR_CMD_RESET_STALE_INT,
|
||||
priv->base + UARTDM_CR);
|
||||
writel(0x7, priv->base + UARTDM_DMRX);
|
||||
}
|
||||
|
||||
return priv->chars_cnt;
|
||||
}
|
||||
|
||||
static int msm_serial_getc(struct udevice *dev)
|
||||
{
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
char c;
|
||||
|
||||
if (!msm_serial_fetch(dev))
|
||||
if (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_RX_READY))
|
||||
return -EAGAIN;
|
||||
|
||||
c = priv->chars_buf & 0xFF;
|
||||
priv->chars_buf >>= 8;
|
||||
priv->chars_cnt--;
|
||||
|
||||
return c;
|
||||
return readl(priv->base + UARTDM_RF) & UARTDM_RF_CHAR;
|
||||
}
|
||||
|
||||
static int msm_serial_putc(struct udevice *dev, const char ch)
|
||||
{
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
|
||||
if (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) &&
|
||||
!(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY))
|
||||
if (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_READY))
|
||||
return -EAGAIN;
|
||||
|
||||
writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR);
|
||||
|
||||
writel(1, priv->base + UARTDM_NCF_TX);
|
||||
writel(ch, priv->base + UARTDM_TF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_serial_pending(struct udevice *dev, bool input)
|
||||
{
|
||||
if (input) {
|
||||
if (msm_serial_fetch(dev))
|
||||
return 1;
|
||||
}
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
|
||||
return 0;
|
||||
if (input)
|
||||
return !!(readl(priv->base + UARTDM_SR) & UARTDM_SR_RX_READY);
|
||||
else
|
||||
return !(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY);
|
||||
}
|
||||
|
||||
static const struct dm_serial_ops msm_serial_ops = {
|
||||
@ -207,8 +141,6 @@ static int calc_csr_bitrate(struct msm_serial_data *priv)
|
||||
|
||||
static void uart_dm_init(struct msm_serial_data *priv)
|
||||
{
|
||||
/* Delay initialization for a bit to let pins stabilize if necessary */
|
||||
mdelay(5);
|
||||
int bitrate = calc_csr_bitrate(priv);
|
||||
if (bitrate < 0) {
|
||||
log_warning("Couldn't calculate bit clock divider! Using default\n");
|
||||
@ -221,13 +153,16 @@ static void uart_dm_init(struct msm_serial_data *priv)
|
||||
|
||||
writel(bitrate, priv->base + UARTDM_CSR);
|
||||
/* Enable RS232 flow control to support RS232 db9 connector */
|
||||
writel(MSM_UART_MR1_RX_RDY_CTL, priv->base + UARTDM_MR1);
|
||||
writel(MSM_BOOT_UART_DM_8_N_1_MODE, priv->base + UARTDM_MR2);
|
||||
writel(MSM_BOOT_UART_DM_CMD_RESET_RX, priv->base + UARTDM_CR);
|
||||
writel(MSM_BOOT_UART_DM_CMD_RESET_TX, priv->base + UARTDM_CR);
|
||||
writel(UARTDM_MR1_RX_RDY_CTL, priv->base + UARTDM_MR1);
|
||||
writel(UARTDM_MR2_8_N_1_MODE, priv->base + UARTDM_MR2);
|
||||
|
||||
/* Make sure BAM/single character mode is disabled */
|
||||
writel(0x0, priv->base + UARTDM_DMEN);
|
||||
/* Enable single character mode */
|
||||
writel(UARTDM_DMEN_TXRX_SC_ENABLE, priv->base + UARTDM_DMEN);
|
||||
|
||||
writel(UARTDM_CR_CMD_RESET_RX, priv->base + UARTDM_CR);
|
||||
writel(UARTDM_CR_CMD_RESET_TX, priv->base + UARTDM_CR);
|
||||
writel(UARTDM_CR_RX_ENABLE, priv->base + UARTDM_CR);
|
||||
writel(UARTDM_CR_TX_ENABLE, priv->base + UARTDM_CR);
|
||||
}
|
||||
static int msm_serial_probe(struct udevice *dev)
|
||||
{
|
||||
@ -319,13 +254,9 @@ static inline void _debug_uart_putc(int ch)
|
||||
{
|
||||
struct msm_serial_data *priv = &init_serial_data;
|
||||
|
||||
while (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) &&
|
||||
!(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY))
|
||||
while (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_READY))
|
||||
;
|
||||
|
||||
writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR);
|
||||
|
||||
writel(1, priv->base + UARTDM_NCF_TX);
|
||||
writel(ch, priv->base + UARTDM_TF);
|
||||
}
|
||||
|
||||
|
||||
@ -10,11 +10,14 @@
|
||||
#include <asm/io.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/time.h>
|
||||
#include <misc.h>
|
||||
#include <serial.h>
|
||||
#include <soc/qcom/qup-fw-load.h>
|
||||
#include <soc/qcom/geni-se.h>
|
||||
|
||||
#define UART_OVERSAMPLING 32
|
||||
#define STALE_TIMEOUT 160
|
||||
@ -22,8 +25,6 @@
|
||||
/* Registers*/
|
||||
#define GENI_FORCE_DEFAULT_REG 0x20
|
||||
#define GENI_SER_M_CLK_CFG 0x48
|
||||
#define GENI_SER_S_CLK_CFG 0x4C
|
||||
#define SE_HW_PARAM_0 0xE24
|
||||
#define SE_GENI_STATUS 0x40
|
||||
#define SE_GENI_S_CMD0 0x630
|
||||
#define SE_GENI_S_CMD_CTRL_REG 0x634
|
||||
@ -39,7 +40,6 @@
|
||||
#define SE_GENI_RX_FIFOn 0x780
|
||||
#define SE_GENI_TX_FIFO_STATUS 0x800
|
||||
#define SE_GENI_RX_FIFO_STATUS 0x804
|
||||
#define SE_GENI_TX_WATERMARK_REG 0x80C
|
||||
#define SE_GENI_TX_PACKING_CFG0 0x260
|
||||
#define SE_GENI_TX_PACKING_CFG1 0x264
|
||||
#define SE_GENI_RX_PACKING_CFG0 0x284
|
||||
@ -54,59 +54,24 @@
|
||||
#define SE_UART_RX_TRANS_CFG 0x280
|
||||
#define SE_UART_RX_PARITY_CFG 0x2a8
|
||||
|
||||
#define M_TX_FIFO_WATERMARK_EN (BIT(30))
|
||||
#define DEF_TX_WM 2
|
||||
/* GENI_FORCE_DEFAULT_REG fields */
|
||||
#define FORCE_DEFAULT (BIT(0))
|
||||
|
||||
#define S_CMD_ABORT_EN (BIT(5))
|
||||
|
||||
#define UART_START_READ 0x1
|
||||
|
||||
/* GENI_M_CMD_CTRL_REG */
|
||||
#define M_GENI_CMD_CANCEL (BIT(2))
|
||||
#define M_GENI_CMD_ABORT (BIT(1))
|
||||
#define M_GENI_DISABLE (BIT(0))
|
||||
|
||||
#define M_CMD_ABORT_EN (BIT(5))
|
||||
#define M_CMD_DONE_EN (BIT(0))
|
||||
#define M_CMD_DONE_DISABLE_MASK (~M_CMD_DONE_EN)
|
||||
|
||||
#define S_GENI_CMD_ABORT (BIT(1))
|
||||
|
||||
/* GENI_S_CMD0 fields */
|
||||
#define S_OPCODE_MSK (GENMASK(31, 27))
|
||||
#define S_PARAMS_MSK (GENMASK(26, 0))
|
||||
|
||||
/* GENI_STATUS fields */
|
||||
#define M_GENI_CMD_ACTIVE (BIT(0))
|
||||
#define S_GENI_CMD_ACTIVE (BIT(12))
|
||||
#define M_CMD_DONE_EN (BIT(0))
|
||||
#define S_CMD_DONE_EN (BIT(0))
|
||||
|
||||
#define M_OPCODE_SHIFT 27
|
||||
#define S_OPCODE_SHIFT 27
|
||||
#define M_TX_FIFO_WATERMARK_EN (BIT(30))
|
||||
#define UART_START_TX 0x1
|
||||
#define UART_CTS_MASK (BIT(1))
|
||||
#define M_SEC_IRQ_EN (BIT(31))
|
||||
#define TX_FIFO_WC_MSK (GENMASK(27, 0))
|
||||
#define RX_FIFO_WC_MSK (GENMASK(24, 0))
|
||||
|
||||
#define S_RX_FIFO_WATERMARK_EN (BIT(26))
|
||||
#define S_RX_FIFO_LAST_EN (BIT(27))
|
||||
#define M_RX_FIFO_WATERMARK_EN (BIT(26))
|
||||
#define M_RX_FIFO_LAST_EN (BIT(27))
|
||||
|
||||
/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */
|
||||
#define SER_CLK_EN (BIT(0))
|
||||
#define CLK_DIV_MSK (GENMASK(15, 4))
|
||||
#define CLK_DIV_SHFT 4
|
||||
|
||||
/* SE_HW_PARAM_0 fields */
|
||||
#define TX_FIFO_WIDTH_MSK (GENMASK(29, 24))
|
||||
#define TX_FIFO_WIDTH_SHFT 24
|
||||
#define TX_FIFO_DEPTH_MSK (GENMASK(21, 16))
|
||||
#define TX_FIFO_DEPTH_SHFT 16
|
||||
|
||||
/* GENI SE QUP Registers */
|
||||
@ -131,6 +96,7 @@ struct msm_serial_data {
|
||||
phys_addr_t base;
|
||||
u32 baud;
|
||||
u32 oversampling;
|
||||
struct clk *se;
|
||||
};
|
||||
|
||||
unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
|
||||
@ -181,19 +147,6 @@ static int get_clk_div_rate(u32 baud, u64 sampling_rate, u32 *clk_div)
|
||||
return ser_clk;
|
||||
}
|
||||
|
||||
static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ret = clk_set_rate(clk, rate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine
|
||||
* @base: Pointer to the concerned serial engine.
|
||||
@ -256,7 +209,7 @@ static int msm_serial_setbrg(struct udevice *dev, int baud)
|
||||
pr_err("%s: Couldn't get clock division rate\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = geni_serial_set_clock_rate(dev, clk_rate);
|
||||
ret = clk_set_rate(priv->se, clk_rate);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Couldn't set clock rate: %d\n", __func__, ret);
|
||||
return ret;
|
||||
@ -561,6 +514,42 @@ static int msm_serial_probe(struct udevice *dev)
|
||||
{
|
||||
struct msm_serial_data *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
u32 proto;
|
||||
struct clk *clk;
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
priv->se = clk;
|
||||
|
||||
/* Try enable clock */
|
||||
ret = clk_enable(clk);
|
||||
|
||||
/* Check if firmware loading is needed (BT UART) */
|
||||
proto = readl(priv->base + GENI_FW_REVISION_RO);
|
||||
proto &= FW_REV_PROTOCOL_MSK;
|
||||
proto >>= FW_REV_PROTOCOL_SHFT;
|
||||
|
||||
if (proto == GENI_SE_INVALID_PROTO) {
|
||||
qcom_geni_load_firmware(priv->base, dev);
|
||||
proto = readl(priv->base + GENI_FW_REVISION_RO);
|
||||
proto &= FW_REV_PROTOCOL_MSK;
|
||||
proto >>= FW_REV_PROTOCOL_SHFT;
|
||||
}
|
||||
|
||||
if (proto != GENI_SE_UART) {
|
||||
dev_err(dev, "Invalid proto %d\n", proto);
|
||||
clk_disable(clk);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Don't actually probe non-debug UARTs */
|
||||
if (ofnode_device_is_compatible(dev_ofnode(dev), "qcom,geni-uart"))
|
||||
return -ENOENT;
|
||||
|
||||
/* Now handle clock enable return value */
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = geni_set_oversampling(dev);
|
||||
if (ret < 0)
|
||||
@ -591,6 +580,7 @@ static int msm_serial_ofdata_to_platdata(struct udevice *dev)
|
||||
|
||||
static const struct udevice_id msm_serial_ids[] = {
|
||||
{ .compatible = "qcom,geni-debug-uart" },
|
||||
{ .compatible = "qcom,geni-uart" },
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -605,19 +595,6 @@ U_BOOT_DRIVER(serial_msm_geni) = {
|
||||
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
|
||||
static const struct udevice_id geniqup_ids[] = {
|
||||
{ .compatible = "qcom,geni-se-qup" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(geni_se_qup) = {
|
||||
.name = "geni-se-qup",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = geniqup_ids,
|
||||
.bind = dm_scan_fdt_dev,
|
||||
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_UART_MSM_GENI
|
||||
|
||||
static struct msm_serial_data init_serial_data = {
|
||||
|
||||
@ -60,6 +60,7 @@ config USB_GADGET_VENDOR_NUM
|
||||
default 0x0955 if ARCH_TEGRA
|
||||
default 0x1f3a if ARCH_SUNXI
|
||||
default 0x2207 if ARCH_ROCKCHIP
|
||||
default 0x18d1 if ARCH_QCOM
|
||||
default 0x0
|
||||
help
|
||||
Vendor ID of the USB device emulated, reported to the host device.
|
||||
@ -87,6 +88,7 @@ config USB_GADGET_PRODUCT_NUM
|
||||
default 0x350b if ROCKCHIP_RK3588
|
||||
default 0x350c if ROCKCHIP_RK3528
|
||||
default 0x350e if ROCKCHIP_RK3576
|
||||
default 0x4ee0 if ARCH_QCOM
|
||||
default 0x0
|
||||
help
|
||||
Product ID of the USB device emulated, reported to the host device.
|
||||
|
||||
@ -24,10 +24,11 @@
|
||||
struct msm_ehci_priv {
|
||||
struct ehci_ctrl ctrl; /* Needed by EHCI */
|
||||
struct usb_ehci *ehci; /* Start of IP core*/
|
||||
struct ulpi_viewport ulpi_vp; /* ULPI Viewport */
|
||||
struct phy phy;
|
||||
struct clk iface_clk;
|
||||
struct clk core_clk;
|
||||
};
|
||||
|
||||
struct qcom_ci_hdrc_priv {
|
||||
struct clk_bulk clks;
|
||||
};
|
||||
|
||||
static int msm_init_after_reset(struct ehci_ctrl *dev)
|
||||
@ -56,64 +57,31 @@ static int ehci_usb_probe(struct udevice *dev)
|
||||
struct ehci_hcor *hcor;
|
||||
int ret;
|
||||
|
||||
ret = clk_get_by_name(dev, "core", &p->core_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get core clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "iface", &p->iface_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get iface clock: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(&p->core_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(&p->iface_clk);
|
||||
if (ret)
|
||||
goto cleanup_core;
|
||||
|
||||
hccr = (struct ehci_hccr *)((phys_addr_t)&ehci->caplength);
|
||||
hcor = (struct ehci_hcor *)((phys_addr_t)hccr +
|
||||
HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
|
||||
|
||||
ret = generic_setup_phy(dev, &p->phy, 0, PHY_MODE_USB_HOST, 0);
|
||||
if (ret)
|
||||
goto cleanup_iface;
|
||||
return ret;
|
||||
|
||||
ret = board_usb_init(0, plat->init_type);
|
||||
if (ret < 0)
|
||||
goto cleanup_iface;
|
||||
return ret;
|
||||
|
||||
return ehci_register(dev, hccr, hcor, &msm_ehci_ops, 0,
|
||||
plat->init_type);
|
||||
|
||||
cleanup_iface:
|
||||
clk_disable_unprepare(&p->iface_clk);
|
||||
cleanup_core:
|
||||
clk_disable_unprepare(&p->core_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ehci_usb_remove(struct udevice *dev)
|
||||
{
|
||||
struct msm_ehci_priv *p = dev_get_priv(dev);
|
||||
struct usb_ehci *ehci = p->ehci;
|
||||
int ret;
|
||||
|
||||
ret = ehci_deregister(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Stop controller. */
|
||||
clrbits_le32(&ehci->usbcmd, CMD_RUN);
|
||||
|
||||
clk_disable_unprepare(&p->iface_clk);
|
||||
clk_disable_unprepare(&p->core_clk);
|
||||
|
||||
ret = generic_shutdown_phy(&p->phy);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -122,15 +90,6 @@ static int ehci_usb_remove(struct udevice *dev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Reset controller */
|
||||
setbits_le32(&ehci->usbcmd, CMD_RESET);
|
||||
|
||||
/* Wait for reset */
|
||||
if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) {
|
||||
printf("Stuck on USB reset.\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -138,38 +97,14 @@ static int ehci_usb_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct msm_ehci_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->ulpi_vp.port_num = 0;
|
||||
priv->ehci = dev_read_addr_ptr(dev);
|
||||
|
||||
if (priv->ehci == (void *)FDT_ADDR_T_NONE)
|
||||
if (!priv->ehci)
|
||||
return -EINVAL;
|
||||
|
||||
/* Warning: this will not work if viewport address is > 64 bit due to
|
||||
* ULPI design.
|
||||
*/
|
||||
priv->ulpi_vp.viewport_addr = (phys_addr_t)&priv->ehci->ulpi_viewpoint;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ehci_usb_of_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev));
|
||||
ofnode phy_node;
|
||||
|
||||
if (!ofnode_valid(ulpi_node))
|
||||
return 0;
|
||||
|
||||
phy_node = ofnode_first_subnode(ulpi_node);
|
||||
if (!ofnode_valid(phy_node)) {
|
||||
printf("%s: ulpi subnode with no phy\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy",
|
||||
phy_node, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CI_UDC)
|
||||
/* Little quirk that MSM needs with Chipidea controller
|
||||
* Must reinit phy after reset
|
||||
@ -182,17 +117,10 @@ void ci_init_after_reset(struct ehci_ctrl *ctrl)
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct udevice_id ehci_usb_ids[] = {
|
||||
{ .compatible = "qcom,ci-hdrc", },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(usb_ehci) = {
|
||||
.name = "ehci_msm",
|
||||
.id = UCLASS_USB,
|
||||
.of_match = ehci_usb_ids,
|
||||
.of_to_plat = ehci_usb_of_to_plat,
|
||||
.bind = ehci_usb_of_bind,
|
||||
.probe = ehci_usb_probe,
|
||||
.remove = ehci_usb_remove,
|
||||
.ops = &ehci_usb_ops,
|
||||
@ -200,3 +128,63 @@ U_BOOT_DRIVER(usb_ehci) = {
|
||||
.plat_auto = sizeof(struct usb_plat),
|
||||
.flags = DM_FLAG_ALLOC_PRIV_DMA,
|
||||
};
|
||||
|
||||
static int qcom_ci_hdrc_probe(struct udevice *dev)
|
||||
{
|
||||
struct qcom_ci_hdrc_priv *p = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_get_bulk(dev, &p->clks);
|
||||
if (ret && (ret != -ENOSYS && ret != -ENOENT)) {
|
||||
dev_err(dev, "Failed to get clocks: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return clk_enable_bulk(&p->clks);
|
||||
}
|
||||
|
||||
static int qcom_ci_hdrc_remove(struct udevice *dev)
|
||||
{
|
||||
struct qcom_ci_hdrc_priv *p = dev_get_priv(dev);
|
||||
|
||||
return clk_release_bulk(&p->clks);
|
||||
}
|
||||
|
||||
static int qcom_ci_hdrc_bind(struct udevice *dev)
|
||||
{
|
||||
ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev));
|
||||
ofnode phy_node;
|
||||
int ret;
|
||||
|
||||
ret = device_bind_driver_to_node(dev, "ehci_msm", "ehci_msm",
|
||||
dev_ofnode(dev), NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ofnode_valid(ulpi_node))
|
||||
return 0;
|
||||
|
||||
phy_node = ofnode_first_subnode(ulpi_node);
|
||||
if (!ofnode_valid(phy_node)) {
|
||||
printf("%s: ulpi subnode with no phy\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy",
|
||||
phy_node, NULL);
|
||||
}
|
||||
|
||||
static const struct udevice_id qcom_ci_hdrc_ids[] = {
|
||||
{ .compatible = "qcom,ci-hdrc", },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(qcom_ci_hdrc) = {
|
||||
.name = "qcom_ci_hdrc",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = qcom_ci_hdrc_ids,
|
||||
.bind = qcom_ci_hdrc_bind,
|
||||
.probe = qcom_ci_hdrc_probe,
|
||||
.remove = qcom_ci_hdrc_remove,
|
||||
.priv_auto = sizeof(struct qcom_ci_hdrc_priv),
|
||||
};
|
||||
|
||||
@ -6,6 +6,13 @@
|
||||
#ifndef _QCOM_GENI_SE
|
||||
#define _QCOM_GENI_SE
|
||||
|
||||
enum geni_se_xfer_mode {
|
||||
GENI_SE_INVALID,
|
||||
GENI_SE_FIFO,
|
||||
GENI_SE_DMA,
|
||||
GENI_GPI_DMA,
|
||||
};
|
||||
|
||||
/* Protocols supported by GENI Serial Engines */
|
||||
enum geni_se_protocol_type {
|
||||
GENI_SE_NONE,
|
||||
@ -14,6 +21,7 @@ enum geni_se_protocol_type {
|
||||
GENI_SE_I2C,
|
||||
GENI_SE_I3C,
|
||||
GENI_SE_SPI_SLAVE,
|
||||
GENI_SE_INVALID_PROTO = 255,
|
||||
};
|
||||
|
||||
#define QUP_HW_VER_REG 0x4
|
||||
@ -29,6 +37,7 @@ enum geni_se_protocol_type {
|
||||
#define GENI_SER_S_CLK_CFG 0x4c
|
||||
#define GENI_IF_DISABLE_RO 0x64
|
||||
#define GENI_FW_REVISION_RO 0x68
|
||||
#define GENI_DFS_IF_CFG 0x80
|
||||
#define SE_GENI_CLK_SEL 0x7c
|
||||
#define SE_GENI_CFG_SEQ_START 0x84
|
||||
#define SE_GENI_BYTE_GRAN 0x254
|
||||
@ -57,15 +66,24 @@ enum geni_se_protocol_type {
|
||||
#define SE_GENI_IOS 0x908
|
||||
#define SE_DMA_TX_IRQ_STAT 0xc40
|
||||
#define SE_DMA_TX_IRQ_CLR 0xc44
|
||||
#define SE_DMA_TX_IRQ_EN_SET 0xc4c
|
||||
#define SE_DMA_TX_FSM_RST 0xc58
|
||||
#define SE_DMA_RX_IRQ_STAT 0xd40
|
||||
#define SE_DMA_RX_IRQ_CLR 0xd44
|
||||
#define SE_DMA_RX_IRQ_EN_SET 0xd4c
|
||||
#define SE_DMA_RX_LEN_IN 0xd54
|
||||
#define SE_DMA_RX_FSM_RST 0xd58
|
||||
#define SE_GSI_EVENT_EN 0xe18
|
||||
#define SE_IRQ_EN 0xe1c
|
||||
#define SE_HW_PARAM_0 0xe24
|
||||
#define SE_HW_PARAM_1 0xe28
|
||||
#define SE_DMA_GENERAL_CFG 0xe30
|
||||
|
||||
/* GENI_DFS_IF_CFG fields */
|
||||
#define DFS_IF_EN BIT(0)
|
||||
|
||||
/* SE_DMA_RX_IRQ_EN_SET fields */
|
||||
#define RESET_DONE_EN_SET BIT(3)
|
||||
|
||||
/* GENI_FORCE_DEFAULT_REG fields */
|
||||
#define FORCE_DEFAULT BIT(0)
|
||||
@ -262,4 +280,22 @@ enum geni_se_protocol_type {
|
||||
/* QUP SE VERSION value for major number 2 and minor number 5 */
|
||||
#define QUP_SE_VERSION_2_5 0x20050000
|
||||
|
||||
/* SE_DMA_GENERAL_CFG */
|
||||
#define DMA_RX_CLK_CGC_ON BIT(0)
|
||||
#define DMA_TX_CLK_CGC_ON BIT(1)
|
||||
#define DMA_AHB_SLV_CFG_ON BIT(2)
|
||||
#define AHB_SEC_SLV_CLK_CGC_ON BIT(3)
|
||||
#define DUMMY_RX_NON_BUFFERABLE BIT(4)
|
||||
#define RX_DMA_ZERO_PADDING_EN BIT(5)
|
||||
#define RX_DMA_IRQ_DELAY_MSK GENMASK(8, 6)
|
||||
#define RX_DMA_IRQ_DELAY_SHFT 6
|
||||
|
||||
#define GENI_SE_DMA_DONE_EN BIT(0)
|
||||
#define GENI_SE_DMA_EOT_EN BIT(1)
|
||||
#define GENI_SE_DMA_AHB_ERR_EN BIT(2)
|
||||
|
||||
#define GENI_SE_DMA_EOT_BUF BIT(0)
|
||||
|
||||
#define GENI_DMA_MODE_EN BIT(0)
|
||||
|
||||
#endif
|
||||
|
||||
178
include/soc/qcom/qup-fw-load.h
Normal file
178
include/soc/qcom/qup-fw-load.h
Normal file
@ -0,0 +1,178 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _LINUX_QCOM_QUP_FW_LOAD
|
||||
#define _LINUX_QCOM_QUP_FW_LOAD
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
/*Magic numbers*/
|
||||
#define MAGIC_NUM_SE 0x57464553
|
||||
|
||||
/* Common SE registers*/
|
||||
#define GENI_INIT_CFG_REVISION 0x0
|
||||
#define GENI_S_INIT_CFG_REVISION 0x4
|
||||
#define GENI_FORCE_DEFAULT_REG 0x20
|
||||
#define GENI_CGC_CTRL 0x28
|
||||
#define GENI_CFG_REG0 0x100
|
||||
|
||||
#define QUPV3_SE_HW_PARAM_1 0xE28
|
||||
#define RX_FIFO_WIDTH_BIT 24
|
||||
#define RX_FIFO_WIDTH_MASK 0x3F
|
||||
|
||||
/*Same registers as GENI_DMA_MODE_EN*/
|
||||
#define QUPV3_SE_GENI_DMA_MODE_EN 0x258
|
||||
#define GENI_M_IRQ_ENABLE 0x614
|
||||
#define GENI_S_IRQ_ENABLE 0x644
|
||||
#define GENI_RX_RFR_WATERMARK_REG 0x814
|
||||
#define DMA_TX_IRQ_EN_SET 0xC4C
|
||||
#define DMA_RX_IRQ_EN_SET 0xD4C
|
||||
#define DMA_GENERAL_CFG 0xE30
|
||||
#define SE_GENI_FW_REVISION 0x1000
|
||||
#define SE_S_FW_REVISION 0x1004
|
||||
#define SE_GENI_CFG_RAMN 0x1010
|
||||
#define SE_GENI_CLK_CTRL 0x2000
|
||||
#define SE_DMA_IF_EN 0x2004
|
||||
#define SE_FIFO_IF_DISABLE 0x2008
|
||||
|
||||
#define MAX_GENI_CFG_RAMn_CNT 455
|
||||
|
||||
#define MI_PBT_NON_PAGED_SEGMENT 0x0
|
||||
#define MI_PBT_HASH_SEGMENT 0x2
|
||||
#define MI_PBT_NOTUSED_SEGMENT 0x3
|
||||
#define MI_PBT_SHARED_SEGMENT 0x4
|
||||
#define MI_PBT_FLAG_PAGE_MODE_MASK 0x100000
|
||||
#define MI_PBT_FLAG_PAGE_MODE_SHIFT 0x14
|
||||
#define MI_PBT_FLAG_SEGMENT_TYPE_MASK 0x7000000
|
||||
#define MI_PBT_FLAG_SEGMENT_TYPE_SHIFT 0x18
|
||||
#define MI_PBT_FLAG_ACCESS_TYPE_MASK 0xE00000
|
||||
#define MI_PBT_FLAG_ACCESS_TYPE_SHIFT 0x15
|
||||
|
||||
#define MI_PBT_PAGE_MODE_VALUE(x) \
|
||||
(((x) & MI_PBT_FLAG_PAGE_MODE_MASK) >> \
|
||||
MI_PBT_FLAG_PAGE_MODE_SHIFT)
|
||||
|
||||
#define MI_PBT_SEGMENT_TYPE_VALUE(x) \
|
||||
(((x) & MI_PBT_FLAG_SEGMENT_TYPE_MASK) >> \
|
||||
MI_PBT_FLAG_SEGMENT_TYPE_SHIFT)
|
||||
|
||||
#define MI_PBT_ACCESS_TYPE_VALUE(x) \
|
||||
(((x) & MI_PBT_FLAG_ACCESS_TYPE_MASK) >> \
|
||||
MI_PBT_FLAG_ACCESS_TYPE_SHIFT)
|
||||
|
||||
/* GENI_FORCE_DEFAULT_REG fields */
|
||||
#define FORCE_DEFAULT BIT(0)
|
||||
|
||||
/* FW_REVISION_RO fields */
|
||||
#define FW_REV_PROTOCOL_SHFT 8
|
||||
#define FW_REV_VERSION_SHFT 0
|
||||
|
||||
#define GENI_FW_REVISION_RO 0x68
|
||||
#define GENI_S_FW_REVISION_RO 0x6C
|
||||
|
||||
/* SE_GENI_DMA_MODE_EN */
|
||||
#define GENI_DMA_MODE_EN BIT(0)
|
||||
|
||||
/* GENI_M_IRQ_EN fields */
|
||||
#define M_CMD_DONE_EN BIT(0)
|
||||
#define M_IO_DATA_DEASSERT_EN BIT(22)
|
||||
#define M_IO_DATA_ASSERT_EN BIT(23)
|
||||
#define M_RX_FIFO_RD_ERR_EN BIT(24)
|
||||
#define M_RX_FIFO_WR_ERR_EN BIT(25)
|
||||
#define M_RX_FIFO_WATERMARK_EN BIT(26)
|
||||
#define M_RX_FIFO_LAST_EN BIT(27)
|
||||
#define M_TX_FIFO_RD_ERR_EN BIT(28)
|
||||
#define M_TX_FIFO_WR_ERR_EN BIT(29)
|
||||
#define M_TX_FIFO_WATERMARK_EN BIT(30)
|
||||
#define M_COMMON_GENI_M_IRQ_EN (GENMASK(6, 1) | \
|
||||
M_IO_DATA_DEASSERT_EN | \
|
||||
M_IO_DATA_ASSERT_EN | M_RX_FIFO_RD_ERR_EN | \
|
||||
M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | \
|
||||
M_TX_FIFO_WR_ERR_EN)
|
||||
|
||||
/* GENI_S_IRQ_EN fields */
|
||||
#define S_CMD_OVERRUN_EN BIT(1)
|
||||
#define S_ILLEGAL_CMD_EN BIT(2)
|
||||
#define S_CMD_CANCEL_EN BIT(4)
|
||||
#define S_CMD_ABORT_EN BIT(5)
|
||||
#define S_GP_IRQ_0_EN BIT(9)
|
||||
#define S_GP_IRQ_1_EN BIT(10)
|
||||
#define S_GP_IRQ_2_EN BIT(11)
|
||||
#define S_GP_IRQ_3_EN BIT(12)
|
||||
#define S_RX_FIFO_RD_ERR_EN BIT(24)
|
||||
#define S_RX_FIFO_WR_ERR_EN BIT(25)
|
||||
#define S_COMMON_GENI_S_IRQ_EN (GENMASK(5, 1) | GENMASK(13, 9) | \
|
||||
S_RX_FIFO_RD_ERR_EN | S_RX_FIFO_WR_ERR_EN)
|
||||
|
||||
#define GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK 0x00000200
|
||||
#define GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK 0x00000100
|
||||
|
||||
#define GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK 0x00000001
|
||||
|
||||
#define DMA_TX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK 0x00000008
|
||||
#define DMA_TX_IRQ_EN_SET_SBE_EN_SET_BMSK 0x00000004
|
||||
#define DMA_TX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK 0x00000001
|
||||
|
||||
#define DMA_RX_IRQ_EN_SET_FLUSH_DONE_EN_SET_BMSK 0x00000010
|
||||
#define DMA_RX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK 0x00000008
|
||||
#define DMA_RX_IRQ_EN_SET_SBE_EN_SET_BMSK 0x00000004
|
||||
#define DMA_RX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK 0x00000001
|
||||
|
||||
#define DMA_GENERAL_CFG_AHB_SEC_SLV_CLK_CGC_ON_BMSK 0x00000008
|
||||
#define DMA_GENERAL_CFG_DMA_AHB_SLV_CLK_CGC_ON_BMSK 0x00000004
|
||||
#define DMA_GENERAL_CFG_DMA_TX_CLK_CGC_ON_BMSK 0x00000002
|
||||
#define DMA_GENERAL_CFG_DMA_RX_CLK_CGC_ON_BMSK 0x00000001
|
||||
|
||||
#define GENI_CLK_CTRL_SER_CLK_SEL_BMSK 0x00000001
|
||||
#define DMA_IF_EN_DMA_IF_EN_BMSK 0x00000001
|
||||
#define SE_GSI_EVENT_EN_BMSK 0x0000000f
|
||||
#define SE_IRQ_EN_RMSK 0x0000000f
|
||||
|
||||
#define QUPV3_COMMON_CFG 0x0120
|
||||
#define FAST_SWITCH_TO_HIGH_DISABLE_BMASK 0x00000001
|
||||
|
||||
#define QUPV3_SE_AHB_M_CFG 0x0118
|
||||
#define AHB_M_CLK_CGC_ON_BMASK 0x00000001
|
||||
|
||||
#define QUPV3_COMMON_CGC_CTRL 0x021C
|
||||
#define COMMON_CSR_SLV_CLK_CGC_ON_BMASK 0x00000001
|
||||
|
||||
/* access ports */
|
||||
#define geni_setbits32(_addr, _v) writel_relaxed(readl_relaxed(_addr) | (_v), (_addr))
|
||||
#define geni_clrbits32(_addr, _v) writel_relaxed(readl_relaxed(_addr) & ~(_v), (_addr))
|
||||
|
||||
/**
|
||||
* struct elf_se_hdr - firmware configurations
|
||||
*
|
||||
* @magic: set to 'SEFW'
|
||||
* @version: A 32-bit value indicating the structure’s version number
|
||||
* @core_version: QUPV3_HW_VERSION
|
||||
* @serial_protocol: Programmed into GENI_FW_REVISION
|
||||
* @fw_version: Programmed into GENI_FW_REVISION
|
||||
* @cfg_version: Programmed into GENI_INIT_CFG_REVISION
|
||||
* @fw_size_in_items: Number of (uint32_t) GENI_FW_RAM words
|
||||
* @fw_offset: Byte offset of GENI_FW_RAM array
|
||||
* @cfg_size_in_items: Number of GENI_FW_CFG index/value pairs
|
||||
* @cfg_idx_offset: Byte offset of GENI_FW_CFG index array
|
||||
* @cfg_val_offset: Byte offset of GENI_FW_CFG values array
|
||||
*/
|
||||
struct elf_se_hdr {
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 core_version;
|
||||
u16 serial_protocol;
|
||||
u16 fw_version;
|
||||
u16 cfg_version;
|
||||
u16 fw_size_in_items;
|
||||
u16 fw_offset;
|
||||
u16 cfg_size_in_items;
|
||||
u16 cfg_idx_offset;
|
||||
u16 cfg_val_offset;
|
||||
};
|
||||
|
||||
struct udevice;
|
||||
|
||||
int qcom_geni_load_firmware(phys_addr_t qup_base, struct udevice *dev);
|
||||
|
||||
#endif /* _LINUX_QCOM_QUP_FW_LOAD */
|
||||
Loading…
x
Reference in New Issue
Block a user