summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/Kconfig3
-rw-r--r--drivers/soc/Makefile7
-rw-r--r--drivers/soc/amlogic/meson-clk-measure.c462
-rw-r--r--drivers/soc/amlogic/meson-gx-socinfo.c12
-rw-r--r--drivers/soc/apple/rtkit-internal.h1
-rw-r--r--drivers/soc/apple/rtkit.c112
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-ctrl.c2
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-snoop.c19
-rw-r--r--drivers/soc/aspeed/aspeed-p2a-ctrl.c2
-rw-r--r--drivers/soc/aspeed/aspeed-uart-routing.c2
-rw-r--r--drivers/soc/atmel/soc.c30
-rw-r--r--drivers/soc/atmel/soc.h12
-rw-r--r--drivers/soc/canaan/Kconfig4
-rw-r--r--drivers/soc/cirrus/Kconfig17
-rw-r--r--drivers/soc/cirrus/Makefile2
-rw-r--r--drivers/soc/cirrus/soc-ep93xx.c252
-rw-r--r--drivers/soc/dove/pmu.c7
-rw-r--r--drivers/soc/fsl/Kconfig4
-rw-r--r--drivers/soc/fsl/dpaa2-console.c2
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c2
-rw-r--r--drivers/soc/fsl/qbman/Kconfig2
-rw-r--r--drivers/soc/fsl/qbman/qman.c7
-rw-r--r--drivers/soc/fsl/qbman/qman_ccsr.c2
-rw-r--r--drivers/soc/fsl/qbman/qman_portal.c5
-rw-r--r--drivers/soc/fsl/qbman/qman_test_stash.c6
-rw-r--r--drivers/soc/fsl/qe/Kconfig17
-rw-r--r--drivers/soc/fsl/qe/qe_common.c80
-rw-r--r--drivers/soc/fsl/qe/qe_ic.c23
-rw-r--r--drivers/soc/fsl/qe/qmc.c704
-rw-r--r--drivers/soc/fsl/qe/tsa.c689
-rw-r--r--drivers/soc/fsl/qe/tsa.h3
-rw-r--r--drivers/soc/fsl/qe/ucc.c1
-rw-r--r--drivers/soc/fsl/rcpm.c1
-rw-r--r--drivers/soc/fujitsu/a64fx-diag.c2
-rw-r--r--drivers/soc/hisilicon/Kconfig9
-rw-r--r--drivers/soc/hisilicon/kunpeng_hccs.c538
-rw-r--r--drivers/soc/hisilicon/kunpeng_hccs.h35
-rw-r--r--drivers/soc/imx/Makefile2
-rw-r--r--drivers/soc/imx/soc-imx8m.c294
-rw-r--r--drivers/soc/imx/soc-imx9.c128
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-npe.c3
-rw-r--r--drivers/soc/ixp4xx/ixp4xx-qmgr.c3
-rw-r--r--drivers/soc/litex/Kconfig2
-rw-r--r--drivers/soc/litex/litex_soc_ctrl.c27
-rw-r--r--drivers/soc/loongson/loongson2_guts.c7
-rw-r--r--drivers/soc/mediatek/Kconfig11
-rw-r--r--drivers/soc/mediatek/Makefile1
-rw-r--r--drivers/soc/mediatek/mt8167-mmsys.h31
-rw-r--r--drivers/soc/mediatek/mt8173-mmsys.h99
-rw-r--r--drivers/soc/mediatek/mt8183-mmsys.h50
-rw-r--r--drivers/soc/mediatek/mt8186-mmsys.h88
-rw-r--r--drivers/soc/mediatek/mt8188-mmsys.h266
-rw-r--r--drivers/soc/mediatek/mt8192-mmsys.h71
-rw-r--r--drivers/soc/mediatek/mt8195-mmsys.h632
-rw-r--r--drivers/soc/mediatek/mt8365-mmsys.h84
-rw-r--r--drivers/soc/mediatek/mtk-cmdq-helper.c386
-rw-r--r--drivers/soc/mediatek/mtk-devapc.c21
-rw-r--r--drivers/soc/mediatek/mtk-dvfsrc.c578
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.c3
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.h14
-rw-r--r--drivers/soc/mediatek/mtk-mutex.c98
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c120
-rw-r--r--drivers/soc/mediatek/mtk-regulator-coupler.c1
-rw-r--r--drivers/soc/mediatek/mtk-socinfo.c38
-rw-r--r--drivers/soc/mediatek/mtk-svs.c4
-rw-r--r--drivers/soc/microchip/mpfs-sys-controller.c2
-rw-r--r--drivers/soc/pxa/ssp.c4
-rw-r--r--drivers/soc/qcom/Kconfig20
-rw-r--r--drivers/soc/qcom/Makefile3
-rw-r--r--drivers/soc/qcom/apr.c9
-rw-r--r--drivers/soc/qcom/cmd-db.c43
-rw-r--r--drivers/soc/qcom/icc-bwmon.c32
-rw-r--r--drivers/soc/qcom/ice.c419
-rw-r--r--drivers/soc/qcom/llcc-qcom.c3848
-rw-r--r--drivers/soc/qcom/mdt_loader.c6
-rw-r--r--drivers/soc/qcom/ocmem.c19
-rw-r--r--drivers/soc/qcom/pdr_interface.c54
-rw-r--r--drivers/soc/qcom/pdr_internal.h317
-rw-r--r--drivers/soc/qcom/pmic_glink.c133
-rw-r--r--drivers/soc/qcom/pmic_glink_altmode.c60
-rw-r--r--drivers/soc/qcom/pmic_pdcharger_ulog.c4
-rw-r--r--drivers/soc/qcom/pmic_pdcharger_ulog.h2
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c3
-rw-r--r--drivers/soc/qcom/qcom-pbs.c38
-rw-r--r--drivers/soc/qcom/qcom_aoss.c13
-rw-r--r--drivers/soc/qcom/qcom_gsbi.c2
-rw-r--r--drivers/soc/qcom/qcom_pd_mapper.c720
-rw-r--r--drivers/soc/qcom/qcom_pdr_msg.c352
-rw-r--r--drivers/soc/qcom/qcom_stats.c6
-rw-r--r--drivers/soc/qcom/qmi_interface.c2
-rw-r--r--drivers/soc/qcom/ramp_controller.c4
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c4
-rw-r--r--drivers/soc/qcom/rpm-proc.c2
-rw-r--r--drivers/soc/qcom/rpm_master_stats.c6
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c21
-rw-r--r--drivers/soc/qcom/rpmh.c1
-rw-r--r--drivers/soc/qcom/smd-rpm.c41
-rw-r--r--drivers/soc/qcom/smem.c79
-rw-r--r--drivers/soc/qcom/smem_state.c15
-rw-r--r--drivers/soc/qcom/smp2p.c51
-rw-r--r--drivers/soc/qcom/smsm.c59
-rw-r--r--drivers/soc/qcom/socinfo.c39
-rw-r--r--drivers/soc/qcom/spm.c1
-rw-r--r--drivers/soc/qcom/trace-aoss.h4
-rw-r--r--drivers/soc/qcom/trace-rpmh.h4
-rw-r--r--drivers/soc/qcom/trace-smp2p.h98
-rw-r--r--drivers/soc/qcom/trace_icc-bwmon.h48
-rw-r--r--drivers/soc/qcom/wcnss_ctrl.c11
-rw-r--r--drivers/soc/renesas/Kconfig83
-rw-r--r--drivers/soc/renesas/Makefile5
-rw-r--r--drivers/soc/renesas/r9a08g045-sysc.c23
-rw-r--r--drivers/soc/renesas/r9a09g047-sys.c67
-rw-r--r--drivers/soc/renesas/r9a09g056-sys.c75
-rw-r--r--drivers/soc/renesas/r9a09g057-sys.c67
-rw-r--r--drivers/soc/renesas/renesas-soc.c13
-rw-r--r--drivers/soc/renesas/rz-sysc.c140
-rw-r--r--drivers/soc/renesas/rz-sysc.h47
-rw-r--r--drivers/soc/rockchip/grf.c32
-rw-r--r--drivers/soc/rockchip/io-domain.c48
-rw-r--r--drivers/soc/samsung/exynos-asv.c11
-rw-r--r--drivers/soc/samsung/exynos-chipid.c12
-rw-r--r--drivers/soc/samsung/exynos-pmu.c141
-rw-r--r--drivers/soc/samsung/exynos-pmu.h1
-rw-r--r--drivers/soc/samsung/exynos-usi.c108
-rw-r--r--drivers/soc/samsung/exynos3250-pmu.c1
-rw-r--r--drivers/soc/samsung/exynos5250-pmu.c1
-rw-r--r--drivers/soc/samsung/exynos5420-pmu.c1
-rw-r--r--drivers/soc/sophgo/Kconfig34
-rw-r--r--drivers/soc/sophgo/Makefile4
-rw-r--r--drivers/soc/sophgo/cv1800-rtcsys.c63
-rw-r--r--drivers/soc/sophgo/sg2044-topsys.c45
-rw-r--r--drivers/soc/sunxi/sunxi_sram.c4
-rw-r--r--drivers/soc/tegra/cbb/tegra-cbb.c20
-rw-r--r--drivers/soc/tegra/cbb/tegra194-cbb.c2
-rw-r--r--drivers/soc/tegra/cbb/tegra234-cbb.c2
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c4
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c17
-rw-r--r--drivers/soc/tegra/pmc.c30
-rw-r--r--drivers/soc/ti/k3-ringacc.c16
-rw-r--r--drivers/soc/ti/k3-socinfo.c17
-rw-r--r--drivers/soc/ti/knav_dma.c26
-rw-r--r--drivers/soc/ti/knav_qmss.h2
-rw-r--r--drivers/soc/ti/knav_qmss_acc.c2
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c118
-rw-r--r--drivers/soc/ti/pm33xx.c58
-rw-r--r--drivers/soc/ti/pruss.c180
-rw-r--r--drivers/soc/ti/smartreflex.c6
-rw-r--r--drivers/soc/ti/ti_sci_inta_msi.c10
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c17
-rw-r--r--drivers/soc/versatile/Kconfig4
-rw-r--r--drivers/soc/versatile/soc-integrator.c1
-rw-r--r--drivers/soc/versatile/soc-realview.c20
-rw-r--r--drivers/soc/vt8500/Kconfig19
-rw-r--r--drivers/soc/vt8500/Makefile2
-rw-r--r--drivers/soc/vt8500/wmt-socinfo.c125
-rw-r--r--drivers/soc/xilinx/xlnx_event_manager.c22
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c157
157 files changed, 11639 insertions, 3003 deletions
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 5d924e946507..a2d65adffb80 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -7,6 +7,7 @@ source "drivers/soc/aspeed/Kconfig"
source "drivers/soc/atmel/Kconfig"
source "drivers/soc/bcm/Kconfig"
source "drivers/soc/canaan/Kconfig"
+source "drivers/soc/cirrus/Kconfig"
source "drivers/soc/fsl/Kconfig"
source "drivers/soc/fujitsu/Kconfig"
source "drivers/soc/hisilicon/Kconfig"
@@ -22,11 +23,13 @@ source "drivers/soc/qcom/Kconfig"
source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/samsung/Kconfig"
+source "drivers/soc/sophgo/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
source "drivers/soc/ux500/Kconfig"
source "drivers/soc/versatile/Kconfig"
+source "drivers/soc/vt8500/Kconfig"
source "drivers/soc/xilinx/Kconfig"
endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index ba8f5b5460e1..c9e689080ceb 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -7,7 +7,8 @@ obj-y += apple/
obj-y += aspeed/
obj-$(CONFIG_ARCH_AT91) += atmel/
obj-y += bcm/
-obj-$(CONFIG_SOC_CANAAN) += canaan/
+obj-$(CONFIG_ARCH_CANAAN) += canaan/
+obj-$(CONFIG_EP93XX_SOC) += cirrus/
obj-$(CONFIG_ARCH_DOVE) += dove/
obj-$(CONFIG_MACH_DOVE) += dove/
obj-y += fsl/
@@ -28,9 +29,11 @@ obj-y += qcom/
obj-y += renesas/
obj-y += rockchip/
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
+obj-y += sophgo/
obj-y += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
obj-$(CONFIG_ARCH_U8500) += ux500/
-obj-$(CONFIG_PLAT_VERSATILE) += versatile/
+obj-y += versatile/
+obj-y += vt8500/
obj-y += xilinx/
diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
index 3f3039600357..d862e30a244e 100644
--- a/drivers/soc/amlogic/meson-clk-measure.c
+++ b/drivers/soc/amlogic/meson-clk-measure.c
@@ -14,11 +14,6 @@
static DEFINE_MUTEX(measure_lock);
-#define MSR_CLK_DUTY 0x0
-#define MSR_CLK_REG0 0x4
-#define MSR_CLK_REG1 0x8
-#define MSR_CLK_REG2 0xc
-
#define MSR_DURATION GENMASK(15, 0)
#define MSR_ENABLE BIT(16)
#define MSR_CONT BIT(17) /* continuous measurement */
@@ -33,23 +28,34 @@ static DEFINE_MUTEX(measure_lock);
#define DIV_STEP 32
#define DIV_MAX 640
-#define CLK_MSR_MAX 128
-
struct meson_msr_id {
struct meson_msr *priv;
unsigned int id;
const char *name;
};
+struct msr_reg_offset {
+ unsigned int duty_val;
+ unsigned int freq_ctrl;
+ unsigned int duty_ctrl;
+ unsigned int freq_val;
+};
+
+struct meson_msr_data {
+ struct meson_msr_id *msr_table;
+ unsigned int msr_count;
+ const struct msr_reg_offset *reg;
+};
+
struct meson_msr {
struct regmap *regmap;
- struct meson_msr_id msr_table[CLK_MSR_MAX];
+ struct meson_msr_data data;
};
#define CLK_MSR_ID(__id, __name) \
[__id] = {.id = __id, .name = __name,}
-static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = {
+static const struct meson_msr_id clk_msr_m8[] = {
CLK_MSR_ID(0, "ring_osc_out_ee0"),
CLK_MSR_ID(1, "ring_osc_out_ee1"),
CLK_MSR_ID(2, "ring_osc_out_ee2"),
@@ -98,7 +104,7 @@ static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = {
CLK_MSR_ID(63, "mipi_csi_cfg"),
};
-static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
+static const struct meson_msr_id clk_msr_gx[] = {
CLK_MSR_ID(0, "ring_osc_out_ee_0"),
CLK_MSR_ID(1, "ring_osc_out_ee_1"),
CLK_MSR_ID(2, "ring_osc_out_ee_2"),
@@ -168,7 +174,7 @@ static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
CLK_MSR_ID(82, "ge2d"),
};
-static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = {
+static const struct meson_msr_id clk_msr_axg[] = {
CLK_MSR_ID(0, "ring_osc_out_ee_0"),
CLK_MSR_ID(1, "ring_osc_out_ee_1"),
CLK_MSR_ID(2, "ring_osc_out_ee_2"),
@@ -242,7 +248,7 @@ static struct meson_msr_id clk_msr_axg[CLK_MSR_MAX] = {
CLK_MSR_ID(109, "audio_locker_in"),
};
-static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
+static const struct meson_msr_id clk_msr_g12a[] = {
CLK_MSR_ID(0, "ring_osc_out_ee_0"),
CLK_MSR_ID(1, "ring_osc_out_ee_1"),
CLK_MSR_ID(2, "ring_osc_out_ee_2"),
@@ -358,7 +364,7 @@ static struct meson_msr_id clk_msr_g12a[CLK_MSR_MAX] = {
CLK_MSR_ID(122, "audio_pdm_dclk"),
};
-static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = {
+static const struct meson_msr_id clk_msr_sm1[] = {
CLK_MSR_ID(0, "ring_osc_out_ee_0"),
CLK_MSR_ID(1, "ring_osc_out_ee_1"),
CLK_MSR_ID(2, "ring_osc_out_ee_2"),
@@ -488,10 +494,304 @@ static struct meson_msr_id clk_msr_sm1[CLK_MSR_MAX] = {
CLK_MSR_ID(127, "csi2_data"),
};
+static const struct meson_msr_id clk_msr_c3[] = {
+ CLK_MSR_ID(0, "sys_clk"),
+ CLK_MSR_ID(1, "axi_clk"),
+ CLK_MSR_ID(2, "rtc_clk"),
+ CLK_MSR_ID(3, "p20_usb2_ckout"),
+ CLK_MSR_ID(4, "eth_mpll_test"),
+ CLK_MSR_ID(5, "sys_pll"),
+ CLK_MSR_ID(6, "cpu_clk_div16"),
+ CLK_MSR_ID(7, "ts_pll"),
+ CLK_MSR_ID(8, "fclk_div2"),
+ CLK_MSR_ID(9, "fclk_div2p5"),
+ CLK_MSR_ID(10, "fclk_div3"),
+ CLK_MSR_ID(11, "fclk_div4"),
+ CLK_MSR_ID(12, "fclk_div5"),
+ CLK_MSR_ID(13, "fclk_div7"),
+ CLK_MSR_ID(15, "fclk_50m"),
+ CLK_MSR_ID(16, "sys_oscin32k_i"),
+ CLK_MSR_ID(17, "mclk_pll"),
+ CLK_MSR_ID(19, "hifi_pll"),
+ CLK_MSR_ID(20, "gp0_pll"),
+ CLK_MSR_ID(21, "gp1_pll"),
+ CLK_MSR_ID(22, "eth_mppll_50m_ckout"),
+ CLK_MSR_ID(23, "sys_pll_div16"),
+ CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
+ CLK_MSR_ID(26, "nna_core"),
+ CLK_MSR_ID(27, "rtc_sec_pulse_out"),
+ CLK_MSR_ID(28, "rtc_osc_clk_out"),
+ CLK_MSR_ID(29, "debug_in_clk"),
+ CLK_MSR_ID(30, "mod_eth_phy_ref_clk"),
+ CLK_MSR_ID(31, "mod_eth_tx_clk"),
+ CLK_MSR_ID(32, "eth_125m"),
+ CLK_MSR_ID(33, "eth_rmii"),
+ CLK_MSR_ID(34, "co_clkin_to_mac"),
+ CLK_MSR_ID(36, "co_rx_clk"),
+ CLK_MSR_ID(37, "co_tx_clk"),
+ CLK_MSR_ID(38, "eth_phy_rxclk"),
+ CLK_MSR_ID(39, "eth_phy_plltxclk"),
+ CLK_MSR_ID(40, "ephy_test_clk"),
+ CLK_MSR_ID(66, "vapb"),
+ CLK_MSR_ID(67, "ge2d"),
+ CLK_MSR_ID(68, "dewarpa"),
+ CLK_MSR_ID(70, "mipi_dsi_meas"),
+ CLK_MSR_ID(71, "dsi_phy"),
+ CLK_MSR_ID(79, "rama"),
+ CLK_MSR_ID(94, "vc9000e_core"),
+ CLK_MSR_ID(95, "vc9000e_sys"),
+ CLK_MSR_ID(96, "vc9000e_aclk"),
+ CLK_MSR_ID(97, "hcodec"),
+ CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
+ CLK_MSR_ID(107, "mipi_csi_phy_clk_out[0]"),
+ CLK_MSR_ID(108, "mipi_csi_phy_clk_out[1]"),
+ CLK_MSR_ID(110, "spifc"),
+ CLK_MSR_ID(111, "saradc"),
+ CLK_MSR_ID(112, "ts"),
+ CLK_MSR_ID(113, "sd_emmc_c"),
+ CLK_MSR_ID(114, "sd_emmc_b"),
+ CLK_MSR_ID(115, "sd_emmc_a"),
+ CLK_MSR_ID(116, "gpio_msr_clk"),
+ CLK_MSR_ID(117, "spicc_b"),
+ CLK_MSR_ID(118, "spicc_a"),
+ CLK_MSR_ID(122, "mod_audio_pdm_dclk_o"),
+ CLK_MSR_ID(124, "o_earcrx_dmac_clk"),
+ CLK_MSR_ID(125, "o_earcrx_cmdc_clk"),
+ CLK_MSR_ID(126, "o_earctx_dmac_clk"),
+ CLK_MSR_ID(127, "o_earctx_cmdc_clk"),
+ CLK_MSR_ID(128, "o_tohdmitx_bclk"),
+ CLK_MSR_ID(129, "o_tohdmitx_mclk"),
+ CLK_MSR_ID(130, "o_tohdmitx_spdif_clk"),
+ CLK_MSR_ID(131, "o_toacodec_bclk"),
+ CLK_MSR_ID(132, "o_toacodec_mclk"),
+ CLK_MSR_ID(133, "o_spdifout_b_mst_clk"),
+ CLK_MSR_ID(134, "o_spdifout_mst_clk"),
+ CLK_MSR_ID(135, "o_spdifin_mst_clk"),
+ CLK_MSR_ID(136, "o_audio_mclk"),
+ CLK_MSR_ID(137, "o_vad_clk"),
+ CLK_MSR_ID(138, "o_tdmout_d_sclk"),
+ CLK_MSR_ID(139, "o_tdmout_c_sclk"),
+ CLK_MSR_ID(140, "o_tdmout_b_sclk"),
+ CLK_MSR_ID(141, "o_tdmout_a_sclk"),
+ CLK_MSR_ID(142, "o_tdminb_1b_sclk"),
+ CLK_MSR_ID(143, "o_tdmin_1b_sclk"),
+ CLK_MSR_ID(144, "o_tdmin_d_sclk"),
+ CLK_MSR_ID(145, "o_tdmin_c_sclk"),
+ CLK_MSR_ID(146, "o_tdmin_b_sclk"),
+ CLK_MSR_ID(147, "o_tdmin_a_sclk"),
+ CLK_MSR_ID(148, "o_resampleb_clk"),
+ CLK_MSR_ID(149, "o_resamplea_clk"),
+ CLK_MSR_ID(150, "o_pdmb_sysclk"),
+ CLK_MSR_ID(151, "o_pdmb_dclk"),
+ CLK_MSR_ID(152, "o_pdm_sysclk"),
+ CLK_MSR_ID(153, "o_pdm_dclk"),
+ CLK_MSR_ID(154, "c_alockerb_out_clk"),
+ CLK_MSR_ID(155, "c_alockerb_in_clk"),
+ CLK_MSR_ID(156, "c_alocker_out_clk"),
+ CLK_MSR_ID(157, "c_alocker_in_clk"),
+ CLK_MSR_ID(158, "audio_mst_clk[34]"),
+ CLK_MSR_ID(159, "audio_mst_clk[35]"),
+ CLK_MSR_ID(160, "pwm_n"),
+ CLK_MSR_ID(161, "pwm_m"),
+ CLK_MSR_ID(162, "pwm_l"),
+ CLK_MSR_ID(163, "pwm_k"),
+ CLK_MSR_ID(164, "pwm_j"),
+ CLK_MSR_ID(165, "pwm_i"),
+ CLK_MSR_ID(166, "pwm_h"),
+ CLK_MSR_ID(167, "pwm_g"),
+ CLK_MSR_ID(168, "pwm_f"),
+ CLK_MSR_ID(169, "pwm_e"),
+ CLK_MSR_ID(170, "pwm_d"),
+ CLK_MSR_ID(171, "pwm_c"),
+ CLK_MSR_ID(172, "pwm_b"),
+ CLK_MSR_ID(173, "pwm_a"),
+ CLK_MSR_ID(174, "AU_DAC1_CLK_TO_GPIO"),
+ CLK_MSR_ID(175, "AU_ADC_CLK_TO_GPIO"),
+ CLK_MSR_ID(176, "rng_ring_osc_clk[0]"),
+ CLK_MSR_ID(177, "rng_ring_osc_clk[1]"),
+ CLK_MSR_ID(178, "rng_ring_osc_clk[2]"),
+ CLK_MSR_ID(179, "rng_ring_osc_clk[3]"),
+ CLK_MSR_ID(180, "sys_cpu_ring_osc_clk[0]"),
+ CLK_MSR_ID(181, "sys_cpu_ring_osc_clk[1]"),
+ CLK_MSR_ID(182, "sys_cpu_ring_osc_clk[2]"),
+ CLK_MSR_ID(183, "sys_cpu_ring_osc_clk[3]"),
+ CLK_MSR_ID(184, "sys_cpu_ring_osc_clk[4]"),
+ CLK_MSR_ID(185, "sys_cpu_ring_osc_clk[5]"),
+ CLK_MSR_ID(186, "sys_cpu_ring_osc_clk[6]"),
+ CLK_MSR_ID(187, "sys_cpu_ring_osc_clk[7]"),
+ CLK_MSR_ID(188, "sys_cpu_ring_osc_clk[8]"),
+ CLK_MSR_ID(189, "sys_cpu_ring_osc_clk[9]"),
+ CLK_MSR_ID(190, "sys_cpu_ring_osc_clk[10]"),
+ CLK_MSR_ID(191, "sys_cpu_ring_osc_clk[11]"),
+ CLK_MSR_ID(192, "am_ring_osc_clk_out[12](dmc)"),
+ CLK_MSR_ID(193, "am_ring_osc_clk_out[13](rama)"),
+ CLK_MSR_ID(194, "am_ring_osc_clk_out[14](nna)"),
+ CLK_MSR_ID(195, "am_ring_osc_clk_out[15](nna)"),
+ CLK_MSR_ID(200, "rng_ring_osc_clk_1[0]"),
+ CLK_MSR_ID(201, "rng_ring_osc_clk_1[1]"),
+ CLK_MSR_ID(202, "rng_ring_osc_clk_1[2]"),
+ CLK_MSR_ID(203, "rng_ring_osc_clk_1[3]"),
+
+};
+
+static const struct meson_msr_id clk_msr_s4[] = {
+ CLK_MSR_ID(0, "sys_clk"),
+ CLK_MSR_ID(1, "axi_clk"),
+ CLK_MSR_ID(2, "rtc_clk"),
+ CLK_MSR_ID(5, "mali"),
+ CLK_MSR_ID(6, "cpu_clk_div16"),
+ CLK_MSR_ID(7, "ceca_clk"),
+ CLK_MSR_ID(8, "cecb_clk"),
+ CLK_MSR_ID(10, "fclk_div5"),
+ CLK_MSR_ID(11, "mpll0"),
+ CLK_MSR_ID(12, "mpll1"),
+ CLK_MSR_ID(13, "mpll2"),
+ CLK_MSR_ID(14, "mpll3"),
+ CLK_MSR_ID(15, "fclk_50m"),
+ CLK_MSR_ID(16, "pcie_clk_inp"),
+ CLK_MSR_ID(17, "pcie_clk_inn"),
+ CLK_MSR_ID(18, "mpll_clk_test_out"),
+ CLK_MSR_ID(19, "hifi_pll"),
+ CLK_MSR_ID(20, "gp0_pll"),
+ CLK_MSR_ID(21, "gp1_pll"),
+ CLK_MSR_ID(22, "eth_mppll_50m_ckout"),
+ CLK_MSR_ID(23, "sys_pll_div16"),
+ CLK_MSR_ID(24, "ddr_dpll_pt_clk"),
+ CLK_MSR_ID(30, "mod_eth_phy_ref_clk"),
+ CLK_MSR_ID(31, "mod_eth_tx_clk"),
+ CLK_MSR_ID(32, "eth_125m"),
+ CLK_MSR_ID(33, "eth_rmii"),
+ CLK_MSR_ID(34, "co_clkin_to_mac"),
+ CLK_MSR_ID(35, "mod_eth_rx_clk_rmii"),
+ CLK_MSR_ID(36, "co_rx_clk"),
+ CLK_MSR_ID(37, "co_tx_clk"),
+ CLK_MSR_ID(38, "eth_phy_rxclk"),
+ CLK_MSR_ID(39, "eth_phy_plltxclk"),
+ CLK_MSR_ID(40, "ephy_test_clk"),
+ CLK_MSR_ID(50, "vid_pll_div_clk_out"),
+ CLK_MSR_ID(51, "enci"),
+ CLK_MSR_ID(52, "encp"),
+ CLK_MSR_ID(53, "encl"),
+ CLK_MSR_ID(54, "vdac"),
+ CLK_MSR_ID(55, "cdac_clk_c"),
+ CLK_MSR_ID(56, "mod_tcon_clko"),
+ CLK_MSR_ID(57, "lcd_an_clk_ph2"),
+ CLK_MSR_ID(58, "lcd_an_clk_ph3"),
+ CLK_MSR_ID(59, "hdmitx_pixel"),
+ CLK_MSR_ID(60, "vdin_meas"),
+ CLK_MSR_ID(61, "vpu"),
+ CLK_MSR_ID(62, "vpu_clkb"),
+ CLK_MSR_ID(63, "vpu_clkb_tmp"),
+ CLK_MSR_ID(64, "vpu_clkc"),
+ CLK_MSR_ID(65, "vid_lock"),
+ CLK_MSR_ID(66, "vapb"),
+ CLK_MSR_ID(67, "ge2d"),
+ CLK_MSR_ID(68, "cts_hdcp22_esmclk"),
+ CLK_MSR_ID(69, "cts_hdcp22_skpclk"),
+ CLK_MSR_ID(76, "hdmitx_tmds"),
+ CLK_MSR_ID(77, "hdmitx_sys_clk"),
+ CLK_MSR_ID(78, "hdmitx_fe_clk"),
+ CLK_MSR_ID(79, "rama"),
+ CLK_MSR_ID(93, "vdec"),
+ CLK_MSR_ID(99, "hevcf"),
+ CLK_MSR_ID(100, "demod_core"),
+ CLK_MSR_ID(101, "adc_extclk_in"),
+ CLK_MSR_ID(102, "cts_demod_core_t2_clk"),
+ CLK_MSR_ID(103, "adc_dpll_intclk"),
+ CLK_MSR_ID(104, "adc_dpll_clk_b3"),
+ CLK_MSR_ID(105, "s2_adc_clk"),
+ CLK_MSR_ID(106, "deskew_pll_clk_div32_out"),
+ CLK_MSR_ID(110, "sc"),
+ CLK_MSR_ID(111, "sar_adc"),
+ CLK_MSR_ID(113, "sd_emmc_c"),
+ CLK_MSR_ID(114, "sd_emmc_b"),
+ CLK_MSR_ID(115, "sd_emmc_a"),
+ CLK_MSR_ID(116, "gpio_msr_clk"),
+ CLK_MSR_ID(118, "spicc0"),
+ CLK_MSR_ID(121, "ts"),
+ CLK_MSR_ID(130, "audio_vad_clk"),
+ CLK_MSR_ID(131, "acodec_dac_clk_x128"),
+ CLK_MSR_ID(132, "audio_locker_in_clk"),
+ CLK_MSR_ID(133, "audio_locker_out_clk"),
+ CLK_MSR_ID(134, "audio_tdmout_c_sclk"),
+ CLK_MSR_ID(135, "audio_tdmout_b_sclk"),
+ CLK_MSR_ID(136, "audio_tdmout_a_sclk"),
+ CLK_MSR_ID(137, "audio_tdmin_lb_sclk"),
+ CLK_MSR_ID(138, "audio_tdmin_c_sclk"),
+ CLK_MSR_ID(139, "audio_tdmin_b_sclk"),
+ CLK_MSR_ID(140, "audio_tdmin_a_sclk"),
+ CLK_MSR_ID(141, "audio_resamplea_clk"),
+ CLK_MSR_ID(142, "audio_pdm_sysclk"),
+ CLK_MSR_ID(143, "audio_spdifout_b_mst_clk"),
+ CLK_MSR_ID(144, "audio_spdifout_mst_clk"),
+ CLK_MSR_ID(145, "audio_spdifin_mst_clk"),
+ CLK_MSR_ID(146, "audio_pdm_dclk"),
+ CLK_MSR_ID(147, "audio_resampleb_clk"),
+ CLK_MSR_ID(160, "pwm_j"),
+ CLK_MSR_ID(161, "pwm_i"),
+ CLK_MSR_ID(162, "pwm_h"),
+ CLK_MSR_ID(163, "pwm_g"),
+ CLK_MSR_ID(164, "pwm_f"),
+ CLK_MSR_ID(165, "pwm_e"),
+ CLK_MSR_ID(166, "pwm_d"),
+ CLK_MSR_ID(167, "pwm_c"),
+ CLK_MSR_ID(168, "pwm_b"),
+ CLK_MSR_ID(169, "pwm_a"),
+ CLK_MSR_ID(176, "rng_ring_0"),
+ CLK_MSR_ID(177, "rng_ring_1"),
+ CLK_MSR_ID(178, "rng_ring_2"),
+ CLK_MSR_ID(179, "rng_ring_3"),
+ CLK_MSR_ID(180, "dmc_osc_ring(LVT16)"),
+ CLK_MSR_ID(181, "gpu_osc_ring0(LVT16)"),
+ CLK_MSR_ID(182, "gpu_osc_ring1(ULVT16)"),
+ CLK_MSR_ID(183, "gpu_osc_ring2(SLVT16)"),
+ CLK_MSR_ID(184, "vpu_osc_ring0(SVT24)"),
+ CLK_MSR_ID(185, "vpu_osc_ring1(LVT20)"),
+ CLK_MSR_ID(186, "vpu_osc_ring2(LVT16)"),
+ CLK_MSR_ID(187, "dos_osc_ring0(SVT24)"),
+ CLK_MSR_ID(188, "dos_osc_ring1(SVT16)"),
+ CLK_MSR_ID(189, "dos_osc_ring2(LVT16)"),
+ CLK_MSR_ID(190, "dos_osc_ring3(ULVT20)"),
+ CLK_MSR_ID(192, "axi_sram_osc_ring(SVT16)"),
+ CLK_MSR_ID(193, "demod_osc_ring0"),
+ CLK_MSR_ID(194, "demod_osc_ring1"),
+ CLK_MSR_ID(195, "sar_osc_ring"),
+ CLK_MSR_ID(196, "sys_cpu_osc_ring0"),
+ CLK_MSR_ID(197, "sys_cpu_osc_ring1"),
+ CLK_MSR_ID(198, "sys_cpu_osc_ring2"),
+ CLK_MSR_ID(199, "sys_cpu_osc_ring3"),
+ CLK_MSR_ID(200, "sys_cpu_osc_ring4"),
+ CLK_MSR_ID(201, "sys_cpu_osc_ring5"),
+ CLK_MSR_ID(202, "sys_cpu_osc_ring6"),
+ CLK_MSR_ID(203, "sys_cpu_osc_ring7"),
+ CLK_MSR_ID(204, "sys_cpu_osc_ring8"),
+ CLK_MSR_ID(205, "sys_cpu_osc_ring9"),
+ CLK_MSR_ID(206, "sys_cpu_osc_ring10"),
+ CLK_MSR_ID(207, "sys_cpu_osc_ring11"),
+ CLK_MSR_ID(208, "sys_cpu_osc_ring12"),
+ CLK_MSR_ID(209, "sys_cpu_osc_ring13"),
+ CLK_MSR_ID(210, "sys_cpu_osc_ring14"),
+ CLK_MSR_ID(211, "sys_cpu_osc_ring15"),
+ CLK_MSR_ID(212, "sys_cpu_osc_ring16"),
+ CLK_MSR_ID(213, "sys_cpu_osc_ring17"),
+ CLK_MSR_ID(214, "sys_cpu_osc_ring18"),
+ CLK_MSR_ID(215, "sys_cpu_osc_ring19"),
+ CLK_MSR_ID(216, "sys_cpu_osc_ring20"),
+ CLK_MSR_ID(217, "sys_cpu_osc_ring21"),
+ CLK_MSR_ID(218, "sys_cpu_osc_ring22"),
+ CLK_MSR_ID(219, "sys_cpu_osc_ring23"),
+ CLK_MSR_ID(220, "sys_cpu_osc_ring24"),
+ CLK_MSR_ID(221, "sys_cpu_osc_ring25"),
+ CLK_MSR_ID(222, "sys_cpu_osc_ring26"),
+ CLK_MSR_ID(223, "sys_cpu_osc_ring27"),
+
+};
+
static int meson_measure_id(struct meson_msr_id *clk_msr_id,
- unsigned int duration)
+ unsigned int duration)
{
struct meson_msr *priv = clk_msr_id->priv;
+ const struct msr_reg_offset *reg = priv->data.reg;
unsigned int val;
int ret;
@@ -499,22 +799,22 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
if (ret)
return ret;
- regmap_write(priv->regmap, MSR_CLK_REG0, 0);
+ regmap_write(priv->regmap, reg->freq_ctrl, 0);
/* Set measurement duration */
- regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_DURATION,
+ regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_DURATION,
FIELD_PREP(MSR_DURATION, duration - 1));
/* Set ID */
- regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_CLK_SRC,
+ regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_CLK_SRC,
FIELD_PREP(MSR_CLK_SRC, clk_msr_id->id));
/* Enable & Start */
- regmap_update_bits(priv->regmap, MSR_CLK_REG0,
+ regmap_update_bits(priv->regmap, reg->freq_ctrl,
MSR_RUN | MSR_ENABLE,
MSR_RUN | MSR_ENABLE);
- ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0,
+ ret = regmap_read_poll_timeout(priv->regmap, reg->freq_ctrl,
val, !(val & MSR_BUSY), 10, 10000);
if (ret) {
mutex_unlock(&measure_lock);
@@ -522,10 +822,10 @@ static int meson_measure_id(struct meson_msr_id *clk_msr_id,
}
/* Disable */
- regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0);
+ regmap_update_bits(priv->regmap, reg->freq_ctrl, MSR_ENABLE, 0);
/* Get the value in multiple of gate time counts */
- regmap_read(priv->regmap, MSR_CLK_REG2, &val);
+ regmap_read(priv->regmap, reg->freq_val, &val);
mutex_unlock(&measure_lock);
@@ -573,13 +873,14 @@ DEFINE_SHOW_ATTRIBUTE(clk_msr);
static int clk_msr_summary_show(struct seq_file *s, void *data)
{
struct meson_msr_id *msr_table = s->private;
+ unsigned int msr_count = msr_table->priv->data.msr_count;
unsigned int precision = 0;
int val, i;
seq_puts(s, " clock rate precision\n");
seq_puts(s, "---------------------------------------------\n");
- for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
+ for (i = 0 ; i < msr_count ; ++i) {
if (!msr_table[i].name)
continue;
@@ -595,18 +896,18 @@ static int clk_msr_summary_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(clk_msr_summary);
-static const struct regmap_config meson_clk_msr_regmap_config = {
+static struct regmap_config meson_clk_msr_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
- .max_register = MSR_CLK_REG2,
};
static int meson_msr_probe(struct platform_device *pdev)
{
- const struct meson_msr_id *match_data;
+ const struct meson_msr_data *match_data;
struct meson_msr *priv;
struct dentry *root, *clks;
+ struct resource *res;
void __iomem *base;
int i;
@@ -621,60 +922,142 @@ static int meson_msr_probe(struct platform_device *pdev)
return -ENODEV;
}
- memcpy(priv->msr_table, match_data, sizeof(priv->msr_table));
+ priv->data.msr_table = devm_kcalloc(&pdev->dev,
+ match_data->msr_count,
+ sizeof(struct meson_msr_id),
+ GFP_KERNEL);
+ if (!priv->data.msr_table)
+ return -ENOMEM;
- base = devm_platform_ioremap_resource(pdev, 0);
+ memcpy(priv->data.msr_table, match_data->msr_table,
+ match_data->msr_count * sizeof(struct meson_msr_id));
+ priv->data.msr_count = match_data->msr_count;
+
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base))
return PTR_ERR(base);
+ meson_clk_msr_regmap_config.max_register = resource_size(res) - 4;
priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&meson_clk_msr_regmap_config);
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
+ priv->data.reg = devm_kzalloc(&pdev->dev, sizeof(struct msr_reg_offset),
+ GFP_KERNEL);
+ if (!priv->data.reg)
+ return -ENOMEM;
+
+ memcpy((void *)priv->data.reg, match_data->reg,
+ sizeof(struct msr_reg_offset));
+
root = debugfs_create_dir("meson-clk-msr", NULL);
clks = debugfs_create_dir("clks", root);
debugfs_create_file("measure_summary", 0444, root,
- priv->msr_table, &clk_msr_summary_fops);
+ priv->data.msr_table, &clk_msr_summary_fops);
- for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
- if (!priv->msr_table[i].name)
+ for (i = 0 ; i < priv->data.msr_count ; ++i) {
+ if (!priv->data.msr_table[i].name)
continue;
- priv->msr_table[i].priv = priv;
+ priv->data.msr_table[i].priv = priv;
- debugfs_create_file(priv->msr_table[i].name, 0444, clks,
- &priv->msr_table[i], &clk_msr_fops);
+ debugfs_create_file(priv->data.msr_table[i].name, 0444, clks,
+ &priv->data.msr_table[i], &clk_msr_fops);
}
return 0;
}
+static const struct msr_reg_offset msr_reg_offset = {
+ .duty_val = 0x0,
+ .freq_ctrl = 0x4,
+ .duty_ctrl = 0x8,
+ .freq_val = 0xc,
+};
+
+static const struct meson_msr_data clk_msr_gx_data = {
+ .msr_table = (void *)clk_msr_gx,
+ .msr_count = ARRAY_SIZE(clk_msr_gx),
+ .reg = &msr_reg_offset,
+};
+
+static const struct meson_msr_data clk_msr_m8_data = {
+ .msr_table = (void *)clk_msr_m8,
+ .msr_count = ARRAY_SIZE(clk_msr_m8),
+ .reg = &msr_reg_offset,
+};
+
+static const struct meson_msr_data clk_msr_axg_data = {
+ .msr_table = (void *)clk_msr_axg,
+ .msr_count = ARRAY_SIZE(clk_msr_axg),
+ .reg = &msr_reg_offset,
+};
+
+static const struct meson_msr_data clk_msr_g12a_data = {
+ .msr_table = (void *)clk_msr_g12a,
+ .msr_count = ARRAY_SIZE(clk_msr_g12a),
+ .reg = &msr_reg_offset,
+};
+
+static const struct meson_msr_data clk_msr_sm1_data = {
+ .msr_table = (void *)clk_msr_sm1,
+ .msr_count = ARRAY_SIZE(clk_msr_sm1),
+ .reg = &msr_reg_offset,
+};
+
+static const struct msr_reg_offset msr_reg_offset_v2 = {
+ .freq_ctrl = 0x0,
+ .duty_ctrl = 0x4,
+ .freq_val = 0x8,
+ .duty_val = 0x18,
+};
+
+static const struct meson_msr_data clk_msr_c3_data = {
+ .msr_table = (void *)clk_msr_c3,
+ .msr_count = ARRAY_SIZE(clk_msr_c3),
+ .reg = &msr_reg_offset_v2,
+};
+
+static const struct meson_msr_data clk_msr_s4_data = {
+ .msr_table = (void *)clk_msr_s4,
+ .msr_count = ARRAY_SIZE(clk_msr_s4),
+ .reg = &msr_reg_offset_v2,
+};
+
static const struct of_device_id meson_msr_match_table[] = {
{
.compatible = "amlogic,meson-gx-clk-measure",
- .data = (void *)clk_msr_gx,
+ .data = &clk_msr_gx_data,
},
{
.compatible = "amlogic,meson8-clk-measure",
- .data = (void *)clk_msr_m8,
+ .data = &clk_msr_m8_data,
},
{
.compatible = "amlogic,meson8b-clk-measure",
- .data = (void *)clk_msr_m8,
+ .data = &clk_msr_m8_data,
},
{
.compatible = "amlogic,meson-axg-clk-measure",
- .data = (void *)clk_msr_axg,
+ .data = &clk_msr_axg_data,
},
{
.compatible = "amlogic,meson-g12a-clk-measure",
- .data = (void *)clk_msr_g12a,
+ .data = &clk_msr_g12a_data,
},
{
.compatible = "amlogic,meson-sm1-clk-measure",
- .data = (void *)clk_msr_sm1,
+ .data = &clk_msr_sm1_data,
+ },
+ {
+ .compatible = "amlogic,c3-clk-measure",
+ .data = &clk_msr_c3_data,
+ },
+ {
+ .compatible = "amlogic,s4-clk-measure",
+ .data = &clk_msr_s4_data,
},
{ /* sentinel */ }
};
@@ -688,4 +1071,5 @@ static struct platform_driver meson_msr_driver = {
},
};
module_platform_driver(meson_msr_driver);
+MODULE_DESCRIPTION("Amlogic Meson SoC Clock Measure driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c
index 6abb730344ab..7549f1644e5e 100644
--- a/drivers/soc/amlogic/meson-gx-socinfo.c
+++ b/drivers/soc/amlogic/meson-gx-socinfo.c
@@ -41,6 +41,11 @@ static const struct meson_gx_soc_id {
{ "G12B", 0x29 },
{ "SM1", 0x2b },
{ "A1", 0x2c },
+ { "T7", 0x36 },
+ { "S4", 0x37 },
+ { "A5", 0x3c },
+ { "C3", 0x3d },
+ { "A4", 0x40 },
};
static const struct meson_gx_package_id {
@@ -63,7 +68,9 @@ static const struct meson_gx_package_id {
{ "962X", 0x24, 0x10, 0xf0 },
{ "962E", 0x24, 0x20, 0xf0 },
{ "A113X", 0x25, 0x37, 0xff },
+ { "A113X", 0x25, 0x43, 0xff },
{ "A113D", 0x25, 0x22, 0xff },
+ { "S905L", 0x26, 0, 0x0 },
{ "S905D2", 0x28, 0x10, 0xf0 },
{ "S905Y2", 0x28, 0x30, 0xf0 },
{ "S905X2", 0x28, 0x40, 0xf0 },
@@ -74,6 +81,11 @@ static const struct meson_gx_package_id {
{ "S905X3", 0x2b, 0x10, 0x3f },
{ "S905D3", 0x2b, 0x30, 0x3f },
{ "A113L", 0x2c, 0x0, 0xf8 },
+ { "S805X2", 0x37, 0x2, 0xf },
+ { "C308L", 0x3d, 0x1, 0xf },
+ { "A311D2", 0x36, 0x1, 0xf },
+ { "A113X2", 0x3c, 0x1, 0xf },
+ { "A113L2", 0x40, 0x1, 0xf },
};
static inline unsigned int socinfo_to_major(u32 socinfo)
diff --git a/drivers/soc/apple/rtkit-internal.h b/drivers/soc/apple/rtkit-internal.h
index 27c9fa745fd5..b8d5244678f0 100644
--- a/drivers/soc/apple/rtkit-internal.h
+++ b/drivers/soc/apple/rtkit-internal.h
@@ -44,6 +44,7 @@ struct apple_rtkit {
struct apple_rtkit_shmem ioreport_buffer;
struct apple_rtkit_shmem crashlog_buffer;
+ struct apple_rtkit_shmem oslog_buffer;
struct apple_rtkit_shmem syslog_buffer;
char *syslog_msg_buffer;
diff --git a/drivers/soc/apple/rtkit.c b/drivers/soc/apple/rtkit.c
index e6d940292c9f..5fffd0f003dc 100644
--- a/drivers/soc/apple/rtkit.c
+++ b/drivers/soc/apple/rtkit.c
@@ -12,6 +12,7 @@ enum {
APPLE_RTKIT_PWR_STATE_IDLE = 0x201, /* sleeping, retain state */
APPLE_RTKIT_PWR_STATE_QUIESCED = 0x10, /* running but no communication */
APPLE_RTKIT_PWR_STATE_ON = 0x20, /* normal operating state */
+ APPLE_RTKIT_PWR_STATE_INIT = 0x220, /* init after starting the coproc */
};
enum {
@@ -66,8 +67,9 @@ enum {
#define APPLE_RTKIT_SYSLOG_MSG_SIZE GENMASK_ULL(31, 24)
#define APPLE_RTKIT_OSLOG_TYPE GENMASK_ULL(63, 56)
-#define APPLE_RTKIT_OSLOG_INIT 1
-#define APPLE_RTKIT_OSLOG_ACK 3
+#define APPLE_RTKIT_OSLOG_BUFFER_REQUEST 1
+#define APPLE_RTKIT_OSLOG_SIZE GENMASK_ULL(55, 36)
+#define APPLE_RTKIT_OSLOG_IOVA GENMASK_ULL(35, 0)
#define APPLE_RTKIT_MIN_SUPPORTED_VERSION 11
#define APPLE_RTKIT_MAX_SUPPORTED_VERSION 12
@@ -97,12 +99,19 @@ bool apple_rtkit_is_crashed(struct apple_rtkit *rtk)
}
EXPORT_SYMBOL_GPL(apple_rtkit_is_crashed);
-static void apple_rtkit_management_send(struct apple_rtkit *rtk, u8 type,
+static int apple_rtkit_management_send(struct apple_rtkit *rtk, u8 type,
u64 msg)
{
+ int ret;
+
msg &= ~APPLE_RTKIT_MGMT_TYPE;
msg |= FIELD_PREP(APPLE_RTKIT_MGMT_TYPE, type);
- apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_MGMT, msg, NULL, false);
+ ret = apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_MGMT, msg, NULL, false);
+
+ if (ret)
+ dev_err(rtk->dev, "RTKit: Failed to send management message: %d\n", ret);
+
+ return ret;
}
static void apple_rtkit_management_rx_hello(struct apple_rtkit *rtk, u64 msg)
@@ -251,15 +260,21 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk,
struct apple_rtkit_shmem *buffer,
u8 ep, u64 msg)
{
- size_t n_4kpages = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg);
u64 reply;
int err;
+ /* The different size vs. IOVA shifts look odd but are indeed correct this way */
+ if (ep == APPLE_RTKIT_EP_OSLOG) {
+ buffer->size = FIELD_GET(APPLE_RTKIT_OSLOG_SIZE, msg);
+ buffer->iova = FIELD_GET(APPLE_RTKIT_OSLOG_IOVA, msg) << 12;
+ } else {
+ buffer->size = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_SIZE, msg) << 12;
+ buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg);
+ }
+
buffer->buffer = NULL;
buffer->iomem = NULL;
buffer->is_mapped = false;
- buffer->iova = FIELD_GET(APPLE_RTKIT_BUFFER_REQUEST_IOVA, msg);
- buffer->size = n_4kpages << 12;
dev_dbg(rtk->dev, "RTKit: buffer request for 0x%zx bytes at %pad\n",
buffer->size, &buffer->iova);
@@ -284,17 +299,30 @@ static int apple_rtkit_common_rx_get_buffer(struct apple_rtkit *rtk,
}
if (!buffer->is_mapped) {
- reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE,
- APPLE_RTKIT_BUFFER_REQUEST);
- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE, n_4kpages);
- reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA,
- buffer->iova);
+ /* oslog uses different fields and needs a shifted IOVA instead of size */
+ if (ep == APPLE_RTKIT_EP_OSLOG) {
+ reply = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE,
+ APPLE_RTKIT_OSLOG_BUFFER_REQUEST);
+ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_SIZE, buffer->size);
+ reply |= FIELD_PREP(APPLE_RTKIT_OSLOG_IOVA,
+ buffer->iova >> 12);
+ } else {
+ reply = FIELD_PREP(APPLE_RTKIT_SYSLOG_TYPE,
+ APPLE_RTKIT_BUFFER_REQUEST);
+ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_SIZE,
+ buffer->size >> 12);
+ reply |= FIELD_PREP(APPLE_RTKIT_BUFFER_REQUEST_IOVA,
+ buffer->iova);
+ }
apple_rtkit_send_message(rtk, ep, reply, NULL, false);
}
return 0;
error:
+ dev_err(rtk->dev, "RTKit: failed buffer request for 0x%zx bytes (%d)\n",
+ buffer->size, err);
+
buffer->buffer = NULL;
buffer->iomem = NULL;
buffer->iova = 0;
@@ -360,7 +388,6 @@ static void apple_rtkit_crashlog_rx(struct apple_rtkit *rtk, u64 msg)
apple_rtkit_memcpy(rtk, bfr, &rtk->crashlog_buffer, 0,
rtk->crashlog_buffer.size);
apple_rtkit_crashlog_dump(rtk, bfr, rtk->crashlog_buffer.size);
- kfree(bfr);
} else {
dev_err(rtk->dev,
"RTKit: Couldn't allocate crashlog shadow buffer\n");
@@ -368,7 +395,9 @@ static void apple_rtkit_crashlog_rx(struct apple_rtkit *rtk, u64 msg)
rtk->crashed = true;
if (rtk->ops->crashed)
- rtk->ops->crashed(rtk->cookie);
+ rtk->ops->crashed(rtk->cookie, bfr, rtk->crashlog_buffer.size);
+
+ kfree(bfr);
}
static void apple_rtkit_ioreport_rx(struct apple_rtkit *rtk, u64 msg)
@@ -448,7 +477,7 @@ static void apple_rtkit_syslog_rx_log(struct apple_rtkit *rtk, u64 msg)
log_context[sizeof(log_context) - 1] = 0;
- msglen = rtk->syslog_msg_size - 1;
+ msglen = strnlen(rtk->syslog_msg_buffer, rtk->syslog_msg_size - 1);
while (msglen > 0 &&
should_crop_syslog_char(rtk->syslog_msg_buffer[msglen - 1]))
msglen--;
@@ -482,25 +511,18 @@ static void apple_rtkit_syslog_rx(struct apple_rtkit *rtk, u64 msg)
}
}
-static void apple_rtkit_oslog_rx_init(struct apple_rtkit *rtk, u64 msg)
-{
- u64 ack;
-
- dev_dbg(rtk->dev, "RTKit: oslog init: msg: 0x%llx\n", msg);
- ack = FIELD_PREP(APPLE_RTKIT_OSLOG_TYPE, APPLE_RTKIT_OSLOG_ACK);
- apple_rtkit_send_message(rtk, APPLE_RTKIT_EP_OSLOG, ack, NULL, false);
-}
-
static void apple_rtkit_oslog_rx(struct apple_rtkit *rtk, u64 msg)
{
u8 type = FIELD_GET(APPLE_RTKIT_OSLOG_TYPE, msg);
switch (type) {
- case APPLE_RTKIT_OSLOG_INIT:
- apple_rtkit_oslog_rx_init(rtk, msg);
+ case APPLE_RTKIT_OSLOG_BUFFER_REQUEST:
+ apple_rtkit_common_rx_get_buffer(rtk, &rtk->oslog_buffer,
+ APPLE_RTKIT_EP_OSLOG, msg);
break;
default:
- dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n", msg);
+ dev_warn(rtk->dev, "RTKit: Unknown oslog message: %llx\n",
+ msg);
}
}
@@ -588,11 +610,18 @@ int apple_rtkit_send_message(struct apple_rtkit *rtk, u8 ep, u64 message,
.msg1 = ep,
};
- if (rtk->crashed)
+ if (rtk->crashed) {
+ dev_warn(rtk->dev,
+ "RTKit: Device is crashed, cannot send message\n");
return -EINVAL;
+ }
+
if (ep >= APPLE_RTKIT_APP_ENDPOINT_START &&
- !apple_rtkit_is_running(rtk))
+ !apple_rtkit_is_running(rtk)) {
+ dev_warn(rtk->dev,
+ "RTKit: Endpoint 0x%02x is not running, cannot send message\n", ep);
return -EINVAL;
+ }
/*
* The message will be sent with a MMIO write. We need the barrier
@@ -667,7 +696,7 @@ struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
rtk->mbox->rx = apple_rtkit_rx;
rtk->mbox->cookie = rtk;
- rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_MEM_RECLAIM,
+ rtk->wq = alloc_ordered_workqueue("rtkit-%s", WQ_HIGHPRI | WQ_MEM_RECLAIM,
dev_name(rtk->dev));
if (!rtk->wq) {
ret = -ENOMEM;
@@ -710,6 +739,7 @@ int apple_rtkit_reinit(struct apple_rtkit *rtk)
apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer);
apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer);
+ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer);
apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer);
kfree(rtk->syslog_msg_buffer);
@@ -742,8 +772,10 @@ static int apple_rtkit_set_ap_power_state(struct apple_rtkit *rtk,
reinit_completion(&rtk->ap_pwr_ack_completion);
msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, state);
- apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_AP_PWR_STATE,
- msg);
+ ret = apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_AP_PWR_STATE,
+ msg);
+ if (ret)
+ return ret;
ret = apple_rtkit_wait_for_completion(&rtk->ap_pwr_ack_completion);
if (ret)
@@ -763,8 +795,10 @@ static int apple_rtkit_set_iop_power_state(struct apple_rtkit *rtk,
reinit_completion(&rtk->iop_pwr_ack_completion);
msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, state);
- apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE,
- msg);
+ ret = apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE,
+ msg);
+ if (ret)
+ return ret;
ret = apple_rtkit_wait_for_completion(&rtk->iop_pwr_ack_completion);
if (ret)
@@ -865,6 +899,7 @@ EXPORT_SYMBOL_GPL(apple_rtkit_quiesce);
int apple_rtkit_wake(struct apple_rtkit *rtk)
{
u64 msg;
+ int ret;
if (apple_rtkit_is_running(rtk))
return -EINVAL;
@@ -875,9 +910,11 @@ int apple_rtkit_wake(struct apple_rtkit *rtk)
* Use open-coded apple_rtkit_set_iop_power_state since apple_rtkit_boot
* will wait for the completion anyway.
*/
- msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, APPLE_RTKIT_PWR_STATE_ON);
- apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE,
- msg);
+ msg = FIELD_PREP(APPLE_RTKIT_MGMT_PWR_STATE, APPLE_RTKIT_PWR_STATE_INIT);
+ ret = apple_rtkit_management_send(rtk, APPLE_RTKIT_MGMT_SET_IOP_PWR_STATE,
+ msg);
+ if (ret)
+ return ret;
return apple_rtkit_boot(rtk);
}
@@ -890,6 +927,7 @@ void apple_rtkit_free(struct apple_rtkit *rtk)
apple_rtkit_free_buffer(rtk, &rtk->ioreport_buffer);
apple_rtkit_free_buffer(rtk, &rtk->crashlog_buffer);
+ apple_rtkit_free_buffer(rtk, &rtk->oslog_buffer);
apple_rtkit_free_buffer(rtk, &rtk->syslog_buffer);
kfree(rtk->syslog_msg_buffer);
diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
index e87038009d1b..ee58151bd69e 100644
--- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c
+++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
@@ -353,7 +353,7 @@ static struct platform_driver aspeed_lpc_ctrl_driver = {
.of_match_table = aspeed_lpc_ctrl_match,
},
.probe = aspeed_lpc_ctrl_probe,
- .remove_new = aspeed_lpc_ctrl_remove,
+ .remove = aspeed_lpc_ctrl_remove,
};
module_platform_driver(aspeed_lpc_ctrl_driver);
diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c
index 888b5840c015..ef8f355589a5 100644
--- a/drivers/soc/aspeed/aspeed-lpc-snoop.c
+++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c
@@ -166,7 +166,7 @@ static int aspeed_lpc_snoop_config_irq(struct aspeed_lpc_snoop *lpc_snoop,
int rc;
lpc_snoop->irq = platform_get_irq(pdev, 0);
- if (!lpc_snoop->irq)
+ if (lpc_snoop->irq < 0)
return -ENODEV;
rc = devm_request_irq(dev, lpc_snoop->irq,
@@ -200,11 +200,15 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
lpc_snoop->chan[channel].miscdev.minor = MISC_DYNAMIC_MINOR;
lpc_snoop->chan[channel].miscdev.name =
devm_kasprintf(dev, GFP_KERNEL, "%s%d", DEVICE_NAME, channel);
+ if (!lpc_snoop->chan[channel].miscdev.name) {
+ rc = -ENOMEM;
+ goto err_free_fifo;
+ }
lpc_snoop->chan[channel].miscdev.fops = &snoop_fops;
lpc_snoop->chan[channel].miscdev.parent = dev;
rc = misc_register(&lpc_snoop->chan[channel].miscdev);
if (rc)
- return rc;
+ goto err_free_fifo;
/* Enable LPC snoop channel at requested port */
switch (channel) {
@@ -221,7 +225,8 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
hicrb_en = HICRB_ENSNP1D;
break;
default:
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_misc_deregister;
}
regmap_update_bits(lpc_snoop->regmap, HICR5, hicr5_en, hicr5_en);
@@ -231,6 +236,12 @@ static int aspeed_lpc_enable_snoop(struct aspeed_lpc_snoop *lpc_snoop,
regmap_update_bits(lpc_snoop->regmap, HICRB,
hicrb_en, hicrb_en);
+ return 0;
+
+err_misc_deregister:
+ misc_deregister(&lpc_snoop->chan[channel].miscdev);
+err_free_fifo:
+ kfifo_free(&lpc_snoop->chan[channel].fifo);
return rc;
}
@@ -366,7 +377,7 @@ static struct platform_driver aspeed_lpc_snoop_driver = {
.of_match_table = aspeed_lpc_snoop_match,
},
.probe = aspeed_lpc_snoop_probe,
- .remove_new = aspeed_lpc_snoop_remove,
+ .remove = aspeed_lpc_snoop_remove,
};
module_platform_driver(aspeed_lpc_snoop_driver);
diff --git a/drivers/soc/aspeed/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
index 8610ddacc7bc..6cc943744e12 100644
--- a/drivers/soc/aspeed/aspeed-p2a-ctrl.c
+++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
@@ -431,7 +431,7 @@ static struct platform_driver aspeed_p2a_ctrl_driver = {
.of_match_table = aspeed_p2a_ctrl_match,
},
.probe = aspeed_p2a_ctrl_probe,
- .remove_new = aspeed_p2a_ctrl_remove,
+ .remove = aspeed_p2a_ctrl_remove,
};
module_platform_driver(aspeed_p2a_ctrl_driver);
diff --git a/drivers/soc/aspeed/aspeed-uart-routing.c b/drivers/soc/aspeed/aspeed-uart-routing.c
index a2195f062e01..0191e36e66e1 100644
--- a/drivers/soc/aspeed/aspeed-uart-routing.c
+++ b/drivers/soc/aspeed/aspeed-uart-routing.c
@@ -589,7 +589,7 @@ static struct platform_driver aspeed_uart_routing_driver = {
.of_match_table = aspeed_uart_routing_table,
},
.probe = aspeed_uart_routing_probe,
- .remove_new = aspeed_uart_routing_remove,
+ .remove = aspeed_uart_routing_remove,
};
module_platform_driver(aspeed_uart_routing_driver);
diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c
index cc9a3e107479..09347bccdb1d 100644
--- a/drivers/soc/atmel/soc.c
+++ b/drivers/soc/atmel/soc.c
@@ -101,6 +101,29 @@ static const struct at91_soc socs[] __initconst = {
AT91_CIDR_VERSION_MASK, SAM9X60_D6K_EXID_MATCH,
"sam9x60 8MiB SDRAM SiP", "sam9x60"),
#endif
+#ifdef CONFIG_SOC_SAM9X7
+ AT91_SOC(SAM9X7_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+ AT91_CIDR_VERSION_MASK, SAM9X70_EXID_MATCH,
+ "sam9x70", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+ AT91_CIDR_VERSION_MASK, SAM9X72_EXID_MATCH,
+ "sam9x72", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D1M_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 16MB DDR2 SiP", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D5M_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 64MB DDR2 SiP", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D1G_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 125MB DDR3L SiP ", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D2G_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 250MB DDR3L SiP", "sam9x7"),
+#endif
#ifdef CONFIG_SOC_SAMA5
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
AT91_CIDR_VERSION_MASK, SAMA5D21CU_EXID_MATCH,
@@ -223,6 +246,9 @@ static const struct at91_soc socs[] __initconst = {
"samv70q19", "samv7"),
#endif
#ifdef CONFIG_SOC_SAMA7
+ AT91_SOC(SAMA7D65_CIDR_MATCH, AT91_CIDR_MASK_SAMA7G5,
+ AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7D65_EXID_MATCH,
+ "sama7d65", "sama7d6"),
AT91_SOC(SAMA7G5_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
AT91_CIDR_VERSION_MASK_SAMA7G5, SAMA7G51_EXID_MATCH,
"sama7g51", "sama7g5"),
@@ -282,6 +308,7 @@ static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
void __iomem *regs;
static const struct of_device_id chipids[] = {
{ .compatible = "atmel,sama5d2-chipid" },
+ { .compatible = "microchip,sama7d65-chipid" },
{ .compatible = "microchip,sama7g5-chipid" },
{ },
};
@@ -370,13 +397,14 @@ static const struct of_device_id at91_soc_allowed_list[] __initconst = {
{ .compatible = "atmel,at91sam9", },
{ .compatible = "atmel,sama5", },
{ .compatible = "atmel,samv7", },
+ { .compatible = "microchip,sama7d65", },
{ .compatible = "microchip,sama7g5", },
{ }
};
static int __init atmel_soc_device_init(void)
{
- struct device_node *np = of_find_node_by_path("/");
+ struct device_node *np __free(device_node) = of_find_node_by_path("/");
if (!of_match_node(at91_soc_allowed_list, np))
return 0;
diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h
index 7a9f47ce85fb..66a74017d9a3 100644
--- a/drivers/soc/atmel/soc.h
+++ b/drivers/soc/atmel/soc.h
@@ -44,6 +44,8 @@ at91_soc_init(const struct at91_soc *socs);
#define AT91SAM9X5_CIDR_MATCH 0x019a05a0
#define AT91SAM9N12_CIDR_MATCH 0x019a07a0
#define SAM9X60_CIDR_MATCH 0x019b35a0
+#define SAM9X7_CIDR_MATCH 0x09750020
+#define SAMA7D65_CIDR_MATCH 0x00262100
#define SAMA7G5_CIDR_MATCH 0x00162100
#define AT91SAM9M11_EXID_MATCH 0x00000001
@@ -66,6 +68,16 @@ at91_soc_init(const struct at91_soc *socs);
#define SAM9X60_D1G_EXID_MATCH 0x00000010
#define SAM9X60_D6K_EXID_MATCH 0x00000011
+#define SAM9X70_EXID_MATCH 0x00000005
+#define SAM9X72_EXID_MATCH 0x00000004
+#define SAM9X75_D1G_EXID_MATCH 0x00000018
+#define SAM9X75_D2G_EXID_MATCH 0x00000020
+#define SAM9X75_D1M_EXID_MATCH 0x00000003
+#define SAM9X75_D5M_EXID_MATCH 0x00000010
+#define SAM9X75_EXID_MATCH 0x00000000
+
+#define SAMA7D65_EXID_MATCH 0x00000080
+
#define SAMA7G51_EXID_MATCH 0x3
#define SAMA7G52_EXID_MATCH 0x2
#define SAMA7G53_EXID_MATCH 0x1
diff --git a/drivers/soc/canaan/Kconfig b/drivers/soc/canaan/Kconfig
index 43ced2bf8444..3121d351fea6 100644
--- a/drivers/soc/canaan/Kconfig
+++ b/drivers/soc/canaan/Kconfig
@@ -2,9 +2,9 @@
config SOC_K210_SYSCTL
bool "Canaan Kendryte K210 SoC system controller"
- depends on RISCV && SOC_CANAAN && OF
+ depends on RISCV && SOC_CANAAN_K210 && OF
depends on COMMON_CLK_K210
- default SOC_CANAAN
+ default SOC_CANAAN_K210
select PM
select MFD_SYSCON
help
diff --git a/drivers/soc/cirrus/Kconfig b/drivers/soc/cirrus/Kconfig
new file mode 100644
index 000000000000..d8b3b1e68998
--- /dev/null
+++ b/drivers/soc/cirrus/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_EP93XX
+
+config EP93XX_SOC
+ bool "Cirrus EP93xx chips SoC"
+ select SOC_BUS
+ select AUXILIARY_BUS
+ default y
+ help
+ Enable support SoC for Cirrus EP93xx chips.
+
+ Cirrus EP93xx chips have several swlocked registers,
+ this driver provides locked access for reset, pinctrl
+ and clk devices implemented as auxiliary devices.
+
+endif
diff --git a/drivers/soc/cirrus/Makefile b/drivers/soc/cirrus/Makefile
new file mode 100644
index 000000000000..9e6608b67f76
--- /dev/null
+++ b/drivers/soc/cirrus/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += soc-ep93xx.o
diff --git a/drivers/soc/cirrus/soc-ep93xx.c b/drivers/soc/cirrus/soc-ep93xx.c
new file mode 100644
index 000000000000..3e79b3b13aef
--- /dev/null
+++ b/drivers/soc/cirrus/soc-ep93xx.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SoC driver for Cirrus EP93xx chips.
+ * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me>
+ *
+ * Based on a rewrite of arch/arm/mach-ep93xx/core.c
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * Thanks go to Michael Burian and Ray Lehtiniemi for their key
+ * role in the ep93xx Linux community.
+ */
+
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/sys_soc.h>
+
+#include <linux/soc/cirrus/ep93xx.h>
+
+#define EP93XX_SYSCON_DEVCFG 0x80
+
+#define EP93XX_SWLOCK_MAGICK 0xaa
+#define EP93XX_SYSCON_SWLOCK 0xc0
+#define EP93XX_SYSCON_SYSCFG 0x9c
+#define EP93XX_SYSCON_SYSCFG_REV_MASK GENMASK(31, 28)
+#define EP93XX_SYSCON_SYSCFG_REV_SHIFT 28
+
+struct ep93xx_map_info {
+ spinlock_t lock;
+ void __iomem *base;
+ struct regmap *map;
+};
+
+/*
+ * EP93xx System Controller software locked register write
+ *
+ * Logic safeguards are included to condition the control signals for
+ * power connection to the matrix to prevent part damage. In addition, a
+ * software lock register is included that must be written with 0xAA
+ * before each register write to change the values of the four switch
+ * matrix control registers.
+ */
+static void ep93xx_regmap_write(struct regmap *map, spinlock_t *lock,
+ unsigned int reg, unsigned int val)
+{
+ guard(spinlock_irqsave)(lock);
+
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ regmap_write(map, reg, val);
+}
+
+static void ep93xx_regmap_update_bits(struct regmap *map, spinlock_t *lock,
+ unsigned int reg, unsigned int mask,
+ unsigned int val)
+{
+ guard(spinlock_irqsave)(lock);
+
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ /* force write is required to clear swlock if no changes are made */
+ regmap_update_bits_base(map, reg, mask, val, NULL, false, true);
+}
+
+static void ep93xx_unregister_adev(void *_adev)
+{
+ struct auxiliary_device *adev = _adev;
+
+ auxiliary_device_delete(adev);
+ auxiliary_device_uninit(adev);
+}
+
+static void ep93xx_adev_release(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+ struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev);
+
+ kfree(rdev);
+}
+
+static struct auxiliary_device __init *ep93xx_adev_alloc(struct device *parent,
+ const char *name,
+ struct ep93xx_map_info *info)
+{
+ struct ep93xx_regmap_adev *rdev __free(kfree) = NULL;
+ struct auxiliary_device *adev;
+ int ret;
+
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
+ if (!rdev)
+ return ERR_PTR(-ENOMEM);
+
+ rdev->map = info->map;
+ rdev->base = info->base;
+ rdev->lock = &info->lock;
+ rdev->write = ep93xx_regmap_write;
+ rdev->update_bits = ep93xx_regmap_update_bits;
+
+ adev = &rdev->adev;
+ adev->name = name;
+ adev->dev.parent = parent;
+ adev->dev.release = ep93xx_adev_release;
+
+ ret = auxiliary_device_init(adev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &no_free_ptr(rdev)->adev;
+}
+
+static int __init ep93xx_controller_register(struct device *parent, const char *name,
+ struct ep93xx_map_info *info)
+{
+ struct auxiliary_device *adev;
+ int ret;
+
+ adev = ep93xx_adev_alloc(parent, name, info);
+ if (IS_ERR(adev))
+ return PTR_ERR(adev);
+
+ ret = auxiliary_device_add(adev);
+ if (ret) {
+ auxiliary_device_uninit(adev);
+ return ret;
+ }
+
+ return devm_add_action_or_reset(parent, ep93xx_unregister_adev, adev);
+}
+
+static unsigned int __init ep93xx_soc_revision(struct regmap *map)
+{
+ unsigned int val;
+
+ regmap_read(map, EP93XX_SYSCON_SYSCFG, &val);
+ val &= EP93XX_SYSCON_SYSCFG_REV_MASK;
+ val >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT;
+ return val;
+}
+
+static const char __init *ep93xx_get_soc_rev(unsigned int rev)
+{
+ switch (rev) {
+ case EP93XX_CHIP_REV_D0:
+ return "D0";
+ case EP93XX_CHIP_REV_D1:
+ return "D1";
+ case EP93XX_CHIP_REV_E0:
+ return "E0";
+ case EP93XX_CHIP_REV_E1:
+ return "E1";
+ case EP93XX_CHIP_REV_E2:
+ return "E2";
+ default:
+ return "unknown";
+ }
+}
+
+static const char *pinctrl_names[] __initconst = {
+ "pinctrl-ep9301", /* EP93XX_9301_SOC */
+ "pinctrl-ep9307", /* EP93XX_9307_SOC */
+ "pinctrl-ep9312", /* EP93XX_9312_SOC */
+};
+
+static int __init ep93xx_syscon_probe(struct platform_device *pdev)
+{
+ enum ep93xx_soc_model model;
+ struct ep93xx_map_info *map_info;
+ struct soc_device_attribute *attrs;
+ struct soc_device *soc_dev;
+ struct device *dev = &pdev->dev;
+ struct regmap *map;
+ void __iomem *base;
+ unsigned int rev;
+ int ret;
+
+ model = (enum ep93xx_soc_model)(uintptr_t)device_get_match_data(dev);
+
+ map = device_node_to_regmap(dev->of_node);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ attrs = devm_kzalloc(dev, sizeof(*attrs), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ rev = ep93xx_soc_revision(map);
+
+ attrs->machine = of_flat_dt_get_machine_name();
+ attrs->family = "Cirrus Logic EP93xx";
+ attrs->revision = ep93xx_get_soc_rev(rev);
+
+ soc_dev = soc_device_register(attrs);
+ if (IS_ERR(soc_dev))
+ return PTR_ERR(soc_dev);
+
+ map_info = devm_kzalloc(dev, sizeof(*map_info), GFP_KERNEL);
+ if (!map_info)
+ return -ENOMEM;
+
+ spin_lock_init(&map_info->lock);
+ map_info->map = map;
+ map_info->base = base;
+
+ ret = ep93xx_controller_register(dev, pinctrl_names[model], map_info);
+ if (ret)
+ dev_err(dev, "registering pinctrl controller failed\n");
+
+ /*
+ * EP93xx SSP clock rate was doubled in version E2. For more information
+ * see section 6 "2x SSP (Synchronous Serial Port) Clock – Revision E2 only":
+ * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
+ */
+ if (rev == EP93XX_CHIP_REV_E2)
+ ret = ep93xx_controller_register(dev, "clk-ep93xx.e2", map_info);
+ else
+ ret = ep93xx_controller_register(dev, "clk-ep93xx", map_info);
+ if (ret)
+ dev_err(dev, "registering clock controller failed\n");
+
+ ret = ep93xx_controller_register(dev, "reset-ep93xx", map_info);
+ if (ret)
+ dev_err(dev, "registering reset controller failed\n");
+
+ return 0;
+}
+
+static const struct of_device_id ep9301_syscon_of_device_ids[] = {
+ { .compatible = "cirrus,ep9301-syscon", .data = (void *)EP93XX_9301_SOC },
+ { .compatible = "cirrus,ep9302-syscon", .data = (void *)EP93XX_9301_SOC },
+ { .compatible = "cirrus,ep9307-syscon", .data = (void *)EP93XX_9307_SOC },
+ { .compatible = "cirrus,ep9312-syscon", .data = (void *)EP93XX_9312_SOC },
+ { .compatible = "cirrus,ep9315-syscon", .data = (void *)EP93XX_9312_SOC },
+ { /* sentinel */ }
+};
+
+static struct platform_driver ep9301_syscon_driver = {
+ .driver = {
+ .name = "ep9301-syscon",
+ .of_match_table = ep9301_syscon_of_device_ids,
+ },
+};
+builtin_platform_driver_probe(ep9301_syscon_driver, ep93xx_syscon_probe);
diff --git a/drivers/soc/dove/pmu.c b/drivers/soc/dove/pmu.c
index 6202dbcd20a8..7bbd3f940e4d 100644
--- a/drivers/soc/dove/pmu.c
+++ b/drivers/soc/dove/pmu.c
@@ -257,10 +257,9 @@ static void pmu_irq_handler(struct irq_desc *desc)
* So, let's structure the code so that the window is as small as
* possible.
*/
- irq_gc_lock(gc);
+ guard(raw_spinlock)(&gc->lock);
done &= readl_relaxed(base + PMC_IRQ_CAUSE);
writel_relaxed(done, base + PMC_IRQ_CAUSE);
- irq_gc_unlock(gc);
}
static int __init dove_init_pmu_irq(struct pmu_data *pmu, int irq)
@@ -274,8 +273,8 @@ static int __init dove_init_pmu_irq(struct pmu_data *pmu, int irq)
writel(0, pmu->pmc_base + PMC_IRQ_MASK);
writel(0, pmu->pmc_base + PMC_IRQ_CAUSE);
- domain = irq_domain_add_linear(pmu->of_node, NR_PMU_IRQS,
- &irq_generic_chip_ops, NULL);
+ domain = irq_domain_create_linear(of_fwnode_handle(pmu->of_node), NR_PMU_IRQS,
+ &irq_generic_chip_ops, NULL);
if (!domain) {
pr_err("%s: unable to add irq domain\n", name);
return -ENOMEM;
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index fcec6ed83d5e..47870e29c290 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -22,7 +22,7 @@ config FSL_GUTS
config FSL_MC_DPIO
tristate "QorIQ DPAA2 DPIO driver"
- depends on FSL_MC_BUS
+ depends on FSL_MC_BUS && NET
select SOC_BUS
select FSL_GUTS
select DIMLIB
@@ -36,7 +36,7 @@ config FSL_MC_DPIO
config DPAA2_CONSOLE
tristate "QorIQ DPAA2 console driver"
depends on OF && (ARCH_LAYERSCAPE || COMPILE_TEST)
- default y
+ default ARCH_LAYERSCAPE
help
Console driver for DPAA2 platforms. Exports 2 char devices,
/dev/dpaa2_mc_console and /dev/dpaa2_aiop_console,
diff --git a/drivers/soc/fsl/dpaa2-console.c b/drivers/soc/fsl/dpaa2-console.c
index 6dbc77db7718..6310f54e68a2 100644
--- a/drivers/soc/fsl/dpaa2-console.c
+++ b/drivers/soc/fsl/dpaa2-console.c
@@ -320,7 +320,7 @@ static struct platform_driver dpaa2_console_driver = {
.of_match_table = dpaa2_console_match_table,
},
.probe = dpaa2_console_probe,
- .remove_new = dpaa2_console_remove,
+ .remove = dpaa2_console_remove,
};
module_platform_driver(dpaa2_console_driver);
diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
index b811446e0fa5..0b60ed16297c 100644
--- a/drivers/soc/fsl/dpio/dpio-service.c
+++ b/drivers/soc/fsl/dpio/dpio-service.c
@@ -891,7 +891,7 @@ void dpaa2_io_update_net_dim(struct dpaa2_io *d, __u64 frames, __u64 bytes)
d->frames += frames;
dim_update_sample(d->event_ctr, d->frames, d->bytes, &dim_sample);
- net_dim(&d->rx_dim, dim_sample);
+ net_dim(&d->rx_dim, &dim_sample);
spin_unlock(&d->dim_lock);
}
diff --git a/drivers/soc/fsl/qbman/Kconfig b/drivers/soc/fsl/qbman/Kconfig
index bdecb86bb656..27774ec6ff90 100644
--- a/drivers/soc/fsl/qbman/Kconfig
+++ b/drivers/soc/fsl/qbman/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menuconfig FSL_DPAA
bool "QorIQ DPAA1 framework support"
- depends on ((FSL_SOC_BOOKE || ARCH_LAYERSCAPE) && ARCH_DMA_ADDR_T_64BIT)
+ depends on ((FSL_SOC_BOOKE || ARCH_LAYERSCAPE || COMPILE_TEST) && ARCH_DMA_ADDR_T_64BIT)
select GENERIC_ALLOCATOR
help
The Freescale Data Path Acceleration Architecture (DPAA) is a set of
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
index 7e9074519ad2..9be240999f87 100644
--- a/drivers/soc/fsl/qbman/qman.c
+++ b/drivers/soc/fsl/qbman/qman.c
@@ -1270,7 +1270,7 @@ static int qman_create_portal(struct qman_portal *portal,
qm_dqrr_set_ithresh(p, QMAN_PIRQ_DQRR_ITHRESH);
qm_mr_set_ithresh(p, QMAN_PIRQ_MR_ITHRESH);
qm_out(p, QM_REG_ITPR, QMAN_PIRQ_IPERIOD);
- portal->cgrs = kmalloc_array(2, sizeof(*cgrs), GFP_KERNEL);
+ portal->cgrs = kmalloc_array(2, sizeof(*portal->cgrs), GFP_KERNEL);
if (!portal->cgrs)
goto fail_cgrs;
/* initial snapshot is no-depletion */
@@ -2546,11 +2546,6 @@ release_lock:
}
EXPORT_SYMBOL(qman_delete_cgr);
-struct cgr_comp {
- struct qman_cgr *cgr;
- struct completion completion;
-};
-
static void qman_delete_cgr_smp_call(void *p)
{
qman_delete_cgr((struct qman_cgr *)p);
diff --git a/drivers/soc/fsl/qbman/qman_ccsr.c b/drivers/soc/fsl/qbman/qman_ccsr.c
index 392e54f14dbe..aa5348f4902f 100644
--- a/drivers/soc/fsl/qbman/qman_ccsr.c
+++ b/drivers/soc/fsl/qbman/qman_ccsr.c
@@ -791,8 +791,6 @@ static int fsl_qman_probe(struct platform_device *pdev)
* FQD memory MUST be zero'd by software
*/
zero_priv_mem(fqd_a, fqd_sz);
-#else
- WARN(1, "Unexpected architecture using non shared-dma-mem reservations");
#endif
dev_dbg(dev, "Allocated FQD 0x%llx 0x%zx\n", fqd_a, fqd_sz);
diff --git a/drivers/soc/fsl/qbman/qman_portal.c b/drivers/soc/fsl/qbman/qman_portal.c
index e23b60618c1a..456ef5d5c199 100644
--- a/drivers/soc/fsl/qbman/qman_portal.c
+++ b/drivers/soc/fsl/qbman/qman_portal.c
@@ -48,9 +48,10 @@ static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
struct device *dev = pcfg->dev;
int ret;
- pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
- if (!pcfg->iommu_domain) {
+ pcfg->iommu_domain = iommu_paging_domain_alloc(dev);
+ if (IS_ERR(pcfg->iommu_domain)) {
dev_err(dev, "%s(): iommu_domain_alloc() failed", __func__);
+ pcfg->iommu_domain = NULL;
goto no_iommu;
}
ret = fsl_pamu_configure_l1_stash(pcfg->iommu_domain, cpu);
diff --git a/drivers/soc/fsl/qbman/qman_test_stash.c b/drivers/soc/fsl/qbman/qman_test_stash.c
index b7e8e5ec884c..f4d3c2146f4f 100644
--- a/drivers/soc/fsl/qbman/qman_test_stash.c
+++ b/drivers/soc/fsl/qbman/qman_test_stash.c
@@ -108,14 +108,12 @@ static int on_all_cpus(int (*fn)(void))
.fn = fn,
.started = ATOMIC_INIT(0)
};
- struct task_struct *k = kthread_create(bstrap_fn, &bstrap,
- "hotpotato%d", cpu);
+ struct task_struct *k = kthread_run_on_cpu(bstrap_fn, &bstrap,
+ cpu, "hotpotato%d");
int ret;
if (IS_ERR(k))
return -ENOMEM;
- kthread_bind(k, cpu);
- wake_up_process(k);
/*
* If we call kthread_stop() before the "wake up" has had an
* effect, then the thread may exit with -EINTR without ever
diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index fa9ffbed0e92..eb03f42ab978 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -17,7 +17,7 @@ config QUICC_ENGINE
config UCC_SLOW
bool
- default y if SERIAL_QE
+ default y if SERIAL_QE || (CPM_QMC && QUICC_ENGINE)
help
This option provides qe_lib support to UCC slow
protocols: UART, BISYNC, QMC
@@ -31,26 +31,27 @@ config UCC_FAST
config UCC
bool
- default y if UCC_FAST || UCC_SLOW
+ default y if UCC_FAST || UCC_SLOW || (CPM_TSA && QUICC_ENGINE)
config CPM_TSA
- tristate "CPM TSA support"
+ tristate "CPM/QE TSA support"
depends on OF && HAS_IOMEM
- depends on CPM1 || (CPM && COMPILE_TEST)
+ depends on CPM1 || QUICC_ENGINE || \
+ ((CPM || QUICC_ENGINE) && COMPILE_TEST)
help
- Freescale CPM Time Slot Assigner (TSA)
+ Freescale CPM/QE Time Slot Assigner (TSA)
controller.
This option enables support for this
controller
config CPM_QMC
- tristate "CPM QMC support"
+ tristate "CPM/QE QMC support"
depends on OF && HAS_IOMEM
- depends on CPM1 || (FSL_SOC && CPM && COMPILE_TEST)
+ depends on FSL_SOC
depends on CPM_TSA
help
- Freescale CPM QUICC Multichannel Controller
+ Freescale CPM/QE QUICC Multichannel Controller
(QMC)
This option enables support for this
diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c
index a877347d37d3..02c29f5f86d3 100644
--- a/drivers/soc/fsl/qe/qe_common.c
+++ b/drivers/soc/fsl/qe/qe_common.c
@@ -13,6 +13,7 @@
* 2006 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*/
+#include <linux/device.h>
#include <linux/genalloc.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -187,6 +188,49 @@ void cpm_muram_free(s32 offset)
}
EXPORT_SYMBOL(cpm_muram_free);
+static void devm_cpm_muram_release(struct device *dev, void *res)
+{
+ s32 *info = res;
+
+ cpm_muram_free(*info);
+}
+
+/**
+ * devm_cpm_muram_alloc - Resource-managed cpm_muram_alloc
+ * @dev: Device to allocate memory for
+ * @size: number of bytes to allocate
+ * @align: requested alignment, in bytes
+ *
+ * This function returns a non-negative offset into the muram area, or
+ * a negative errno on failure as cpm_muram_alloc() does.
+ * Use cpm_muram_addr() to get the virtual address of the area.
+ *
+ * Compare against cpm_muram_alloc(), the memory allocated by this
+ * resource-managed version is automatically freed on driver detach and so,
+ * cpm_muram_free() must not be called to release the allocated memory.
+ */
+s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
+ unsigned long align)
+{
+ s32 info;
+ s32 *dr;
+
+ dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ info = cpm_muram_alloc(size, align);
+ if (info >= 0) {
+ *dr = info;
+ devres_add(dev, dr);
+ } else {
+ devres_free(dr);
+ }
+
+ return info;
+}
+EXPORT_SYMBOL(devm_cpm_muram_alloc);
+
/*
* cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
* @offset: offset of allocation start address
@@ -212,6 +256,42 @@ s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
EXPORT_SYMBOL(cpm_muram_alloc_fixed);
/**
+ * devm_cpm_muram_alloc_fixed - Resource-managed cpm_muram_alloc_fixed
+ * @dev: Device to allocate memory for
+ * @offset: offset of allocation start address
+ * @size: number of bytes to allocate
+ *
+ * This function returns a non-negative offset into the muram area, or
+ * a negative errno on failure as cpm_muram_alloc_fixed() does.
+ * Use cpm_muram_addr() to get the virtual address of the area.
+ *
+ * Compare against cpm_muram_alloc_fixed(), the memory allocated by this
+ * resource-managed version is automatically freed on driver detach and so,
+ * cpm_muram_free() must not be called to release the allocated memory.
+ */
+s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
+ unsigned long size)
+{
+ s32 info;
+ s32 *dr;
+
+ dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ info = cpm_muram_alloc_fixed(offset, size);
+ if (info >= 0) {
+ *dr = info;
+ devres_add(dev, dr);
+ } else {
+ devres_free(dr);
+ }
+
+ return info;
+}
+EXPORT_SYMBOL(devm_cpm_muram_alloc_fixed);
+
+/**
* cpm_muram_addr - turn a muram offset into a virtual address
* @offset: muram offset to convert
*/
diff --git a/drivers/soc/fsl/qe/qe_ic.c b/drivers/soc/fsl/qe/qe_ic.c
index bbae3d39c7be..4068b501a3a3 100644
--- a/drivers/soc/fsl/qe/qe_ic.c
+++ b/drivers/soc/fsl/qe/qe_ic.c
@@ -232,11 +232,6 @@ static inline void qe_ic_write(__be32 __iomem *base, unsigned int reg,
iowrite32be(value, base + (reg >> 2));
}
-static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
-{
- return irq_get_chip_data(virq);
-}
-
static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
{
return irq_data_get_irq_chip_data(d);
@@ -344,7 +339,7 @@ static unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
if (irq == 0)
return 0;
- return irq_linear_revmap(qe_ic->irqhost, irq);
+ return irq_find_mapping(qe_ic->irqhost, irq);
}
/* Return an interrupt vector or 0 if no interrupt is pending. */
@@ -360,7 +355,7 @@ static unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
if (irq == 0)
return 0;
- return irq_linear_revmap(qe_ic->irqhost, irq);
+ return irq_find_mapping(qe_ic->irqhost, irq);
}
static void qe_ic_cascade_low(struct irq_desc *desc)
@@ -446,8 +441,8 @@ static int qe_ic_init(struct platform_device *pdev)
high_handler = NULL;
}
- qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
- &qe_ic_host_ops, qe_ic);
+ qe_ic->irqhost = irq_domain_create_linear(of_fwnode_handle(node), NR_QE_IC_INTS,
+ &qe_ic_host_ops, qe_ic);
if (qe_ic->irqhost == NULL) {
dev_err(dev, "failed to add irq domain\n");
return -ENODEV;
@@ -455,13 +450,11 @@ static int qe_ic_init(struct platform_device *pdev)
qe_ic_write(qe_ic->regs, QEIC_CICR, 0);
- irq_set_handler_data(qe_ic->virq_low, qe_ic);
- irq_set_chained_handler(qe_ic->virq_low, low_handler);
+ irq_set_chained_handler_and_data(qe_ic->virq_low, low_handler, qe_ic);
- if (high_handler) {
- irq_set_handler_data(qe_ic->virq_high, qe_ic);
- irq_set_chained_handler(qe_ic->virq_high, high_handler);
- }
+ if (high_handler)
+ irq_set_chained_handler_and_data(qe_ic->virq_high,
+ high_handler, qe_ic);
return 0;
}
static const struct of_device_id qe_ic_ids[] = {
diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index f498db9abe35..36c0ccc06151 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -8,7 +8,9 @@
*/
#include <soc/fsl/qe/qmc.h>
+#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
#include <linux/hdlc.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -18,31 +20,41 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <soc/fsl/cpm.h>
+#include <soc/fsl/qe/ucc_slow.h>
+#include <soc/fsl/qe/qe.h>
#include <sysdev/fsl_soc.h>
#include "tsa.h"
-/* SCC general mode register high (32 bits) */
+/* SCC general mode register low (32 bits) (GUMR_L in QE) */
#define SCC_GSMRL 0x00
-#define SCC_GSMRL_ENR (1 << 5)
-#define SCC_GSMRL_ENT (1 << 4)
-#define SCC_GSMRL_MODE_QMC (0x0A << 0)
+#define SCC_GSMRL_ENR BIT(5)
+#define SCC_GSMRL_ENT BIT(4)
+#define SCC_GSMRL_MODE_MASK GENMASK(3, 0)
+#define SCC_CPM1_GSMRL_MODE_QMC FIELD_PREP_CONST(SCC_GSMRL_MODE_MASK, 0x0A)
+#define SCC_QE_GSMRL_MODE_QMC FIELD_PREP_CONST(SCC_GSMRL_MODE_MASK, 0x02)
-/* SCC general mode register low (32 bits) */
+/* SCC general mode register high (32 bits) (identical to GUMR_H in QE) */
#define SCC_GSMRH 0x04
-#define SCC_GSMRH_CTSS (1 << 7)
-#define SCC_GSMRH_CDS (1 << 8)
-#define SCC_GSMRH_CTSP (1 << 9)
-#define SCC_GSMRH_CDP (1 << 10)
-
-/* SCC event register (16 bits) */
+#define SCC_GSMRH_CTSS BIT(7)
+#define SCC_GSMRH_CDS BIT(8)
+#define SCC_GSMRH_CTSP BIT(9)
+#define SCC_GSMRH_CDP BIT(10)
+#define SCC_GSMRH_TTX BIT(11)
+#define SCC_GSMRH_TRX BIT(12)
+
+/* SCC event register (16 bits) (identical to UCCE in QE) */
#define SCC_SCCE 0x10
-#define SCC_SCCE_IQOV (1 << 3)
-#define SCC_SCCE_GINT (1 << 2)
-#define SCC_SCCE_GUN (1 << 1)
-#define SCC_SCCE_GOV (1 << 0)
+#define SCC_SCCE_IQOV BIT(3)
+#define SCC_SCCE_GINT BIT(2)
+#define SCC_SCCE_GUN BIT(1)
+#define SCC_SCCE_GOV BIT(0)
/* SCC mask register (16 bits) */
#define SCC_SCCM 0x14
+
+/* UCC Extended Mode Register (8 bits, QE only) */
+#define SCC_QE_UCC_GUEMR 0x90
+
/* Multichannel base pointer (32 bits) */
#define QMC_GBL_MCBASE 0x00
/* Multichannel controller state (16 bits) */
@@ -73,27 +85,42 @@
#define QMC_GBL_TSATTX 0x60
/* CRC constant (16 bits) */
#define QMC_GBL_C_MASK16 0xA0
+/* Rx framer base pointer (16 bits, QE only) */
+#define QMC_QE_GBL_RX_FRM_BASE 0xAC
+/* Tx framer base pointer (16 bits, QE only) */
+#define QMC_QE_GBL_TX_FRM_BASE 0xAE
+/* A reserved area (0xB0 -> 0xC3) that must be initialized to 0 (QE only) */
+#define QMC_QE_GBL_RSV_B0_START 0xB0
+#define QMC_QE_GBL_RSV_B0_SIZE 0x14
+/* QMC Global Channel specific base (32 bits, QE only) */
+#define QMC_QE_GBL_GCSBASE 0xC4
/* TSA entry (16bit entry in TSATRX and TSATTX) */
-#define QMC_TSA_VALID (1 << 15)
-#define QMC_TSA_WRAP (1 << 14)
-#define QMC_TSA_MASK (0x303F)
-#define QMC_TSA_CHANNEL(x) ((x) << 6)
+#define QMC_TSA_VALID BIT(15)
+#define QMC_TSA_WRAP BIT(14)
+#define QMC_TSA_MASK_MASKH GENMASK(13, 12)
+#define QMC_TSA_MASK_MASKL GENMASK(5, 0)
+#define QMC_TSA_MASK_8BIT (FIELD_PREP_CONST(QMC_TSA_MASK_MASKH, 0x3) | \
+ FIELD_PREP_CONST(QMC_TSA_MASK_MASKL, 0x3F))
+#define QMC_TSA_CHANNEL_MASK GENMASK(11, 6)
+#define QMC_TSA_CHANNEL(x) FIELD_PREP(QMC_TSA_CHANNEL_MASK, x)
/* Tx buffer descriptor base address (16 bits, offset from MCBASE) */
#define QMC_SPE_TBASE 0x00
/* Channel mode register (16 bits) */
#define QMC_SPE_CHAMR 0x02
-#define QMC_SPE_CHAMR_MODE_HDLC (1 << 15)
-#define QMC_SPE_CHAMR_MODE_TRANSP ((0 << 15) | (1 << 13))
-#define QMC_SPE_CHAMR_ENT (1 << 12)
-#define QMC_SPE_CHAMR_POL (1 << 8)
-#define QMC_SPE_CHAMR_HDLC_IDLM (1 << 13)
-#define QMC_SPE_CHAMR_HDLC_CRC (1 << 7)
-#define QMC_SPE_CHAMR_HDLC_NOF (0x0f << 0)
-#define QMC_SPE_CHAMR_TRANSP_RD (1 << 14)
-#define QMC_SPE_CHAMR_TRANSP_SYNC (1 << 10)
+#define QMC_SPE_CHAMR_MODE_MASK GENMASK(15, 15)
+#define QMC_SPE_CHAMR_MODE_HDLC FIELD_PREP_CONST(QMC_SPE_CHAMR_MODE_MASK, 1)
+#define QMC_SPE_CHAMR_MODE_TRANSP (FIELD_PREP_CONST(QMC_SPE_CHAMR_MODE_MASK, 0) | BIT(13))
+#define QMC_SPE_CHAMR_ENT BIT(12)
+#define QMC_SPE_CHAMR_POL BIT(8)
+#define QMC_SPE_CHAMR_HDLC_IDLM BIT(13)
+#define QMC_SPE_CHAMR_HDLC_CRC BIT(7)
+#define QMC_SPE_CHAMR_HDLC_NOF_MASK GENMASK(3, 0)
+#define QMC_SPE_CHAMR_HDLC_NOF(x) FIELD_PREP(QMC_SPE_CHAMR_HDLC_NOF_MASK, x)
+#define QMC_SPE_CHAMR_TRANSP_RD BIT(14)
+#define QMC_SPE_CHAMR_TRANSP_SYNC BIT(10)
/* Tx internal state (32 bits) */
#define QMC_SPE_TSTATE 0x04
@@ -120,43 +147,47 @@
/* Transparent synchronization (16 bits) */
#define QMC_SPE_TRNSYNC 0x3C
-#define QMC_SPE_TRNSYNC_RX(x) ((x) << 8)
-#define QMC_SPE_TRNSYNC_TX(x) ((x) << 0)
+#define QMC_SPE_TRNSYNC_RX_MASK GENMASK(15, 8)
+#define QMC_SPE_TRNSYNC_RX(x) FIELD_PREP(QMC_SPE_TRNSYNC_RX_MASK, x)
+#define QMC_SPE_TRNSYNC_TX_MASK GENMASK(7, 0)
+#define QMC_SPE_TRNSYNC_TX(x) FIELD_PREP(QMC_SPE_TRNSYNC_TX_MASK, x)
/* Interrupt related registers bits */
-#define QMC_INT_V (1 << 15)
-#define QMC_INT_W (1 << 14)
-#define QMC_INT_NID (1 << 13)
-#define QMC_INT_IDL (1 << 12)
-#define QMC_INT_GET_CHANNEL(x) (((x) & 0x0FC0) >> 6)
-#define QMC_INT_MRF (1 << 5)
-#define QMC_INT_UN (1 << 4)
-#define QMC_INT_RXF (1 << 3)
-#define QMC_INT_BSY (1 << 2)
-#define QMC_INT_TXB (1 << 1)
-#define QMC_INT_RXB (1 << 0)
+#define QMC_INT_V BIT(15)
+#define QMC_INT_W BIT(14)
+#define QMC_INT_NID BIT(13)
+#define QMC_INT_IDL BIT(12)
+#define QMC_INT_CHANNEL_MASK GENMASK(11, 6)
+#define QMC_INT_GET_CHANNEL(x) FIELD_GET(QMC_INT_CHANNEL_MASK, x)
+#define QMC_INT_MRF BIT(5)
+#define QMC_INT_UN BIT(4)
+#define QMC_INT_RXF BIT(3)
+#define QMC_INT_BSY BIT(2)
+#define QMC_INT_TXB BIT(1)
+#define QMC_INT_RXB BIT(0)
/* BD related registers bits */
-#define QMC_BD_RX_E (1 << 15)
-#define QMC_BD_RX_W (1 << 13)
-#define QMC_BD_RX_I (1 << 12)
-#define QMC_BD_RX_L (1 << 11)
-#define QMC_BD_RX_F (1 << 10)
-#define QMC_BD_RX_CM (1 << 9)
-#define QMC_BD_RX_UB (1 << 7)
-#define QMC_BD_RX_LG (1 << 5)
-#define QMC_BD_RX_NO (1 << 4)
-#define QMC_BD_RX_AB (1 << 3)
-#define QMC_BD_RX_CR (1 << 2)
-
-#define QMC_BD_TX_R (1 << 15)
-#define QMC_BD_TX_W (1 << 13)
-#define QMC_BD_TX_I (1 << 12)
-#define QMC_BD_TX_L (1 << 11)
-#define QMC_BD_TX_TC (1 << 10)
-#define QMC_BD_TX_CM (1 << 9)
-#define QMC_BD_TX_UB (1 << 7)
-#define QMC_BD_TX_PAD (0x0f << 0)
+#define QMC_BD_RX_E BIT(15)
+#define QMC_BD_RX_W BIT(13)
+#define QMC_BD_RX_I BIT(12)
+#define QMC_BD_RX_L BIT(11)
+#define QMC_BD_RX_F BIT(10)
+#define QMC_BD_RX_CM BIT(9)
+#define QMC_BD_RX_UB BIT(7)
+#define QMC_BD_RX_LG BIT(5)
+#define QMC_BD_RX_NO BIT(4)
+#define QMC_BD_RX_AB BIT(3)
+#define QMC_BD_RX_CR BIT(2)
+
+#define QMC_BD_TX_R BIT(15)
+#define QMC_BD_TX_W BIT(13)
+#define QMC_BD_TX_I BIT(12)
+#define QMC_BD_TX_L BIT(11)
+#define QMC_BD_TX_TC BIT(10)
+#define QMC_BD_TX_CM BIT(9)
+#define QMC_BD_TX_UB BIT(7)
+#define QMC_BD_TX_PAD_MASK GENMASK(3, 0)
+#define QMC_BD_TX_PAD(x) FIELD_PREP(QMC_BD_TX_PAD_MASK, x)
/* Numbers of BDs and interrupt items */
#define QMC_NB_TXBDS 8
@@ -184,7 +215,7 @@ struct qmc_chan {
u64 rx_ts_mask;
bool is_reverse_data;
- spinlock_t tx_lock;
+ spinlock_t tx_lock; /* Protect Tx related data */
cbd_t __iomem *txbds;
cbd_t __iomem *txbd_free;
cbd_t __iomem *txbd_done;
@@ -192,7 +223,7 @@ struct qmc_chan {
u64 nb_tx_underrun;
bool is_tx_stopped;
- spinlock_t rx_lock;
+ spinlock_t rx_lock; /* Protect Rx related data */
cbd_t __iomem *rxbds;
cbd_t __iomem *rxbd_free;
cbd_t __iomem *rxbd_done;
@@ -203,13 +234,31 @@ struct qmc_chan {
bool is_rx_stopped;
};
+enum qmc_version {
+ QMC_CPM1,
+ QMC_QE,
+};
+
+struct qmc_data {
+ enum qmc_version version;
+ u32 tstate; /* Initial TSTATE value */
+ u32 rstate; /* Initial RSTATE value */
+ u32 zistate; /* Initial ZISTATE value */
+ u32 zdstate_hdlc; /* Initial ZDSTATE value (HDLC mode) */
+ u32 zdstate_transp; /* Initial ZDSTATE value (Transparent mode) */
+ u32 rpack; /* Initial RPACK value */
+};
+
struct qmc {
struct device *dev;
+ const struct qmc_data *data;
struct tsa_serial *tsa_serial;
void __iomem *scc_regs;
void __iomem *scc_pram;
void __iomem *dpram;
u16 scc_pram_offset;
+ u32 dpram_offset;
+ u32 qe_subblock;
cbd_t __iomem *bd_table;
dma_addr_t bd_dma_addr;
size_t bd_size;
@@ -222,6 +271,11 @@ struct qmc {
struct qmc_chan *chans[64];
};
+static void qmc_write8(void __iomem *addr, u8 val)
+{
+ iowrite8(val, addr);
+}
+
static void qmc_write16(void __iomem *addr, u16 val)
{
iowrite16be(val, addr);
@@ -262,6 +316,13 @@ static void qmc_setbits32(void __iomem *addr, u32 set)
qmc_write32(addr, qmc_read32(addr) | set);
}
+static bool qmc_is_qe(const struct qmc *qmc)
+{
+ if (IS_ENABLED(CONFIG_QUICC_ENGINE) && IS_ENABLED(CONFIG_CPM))
+ return qmc->data->version == QMC_QE;
+
+ return IS_ENABLED(CONFIG_QUICC_ENGINE);
+}
int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info)
{
@@ -348,8 +409,8 @@ int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param
switch (param->mode) {
case QMC_HDLC:
- if ((param->hdlc.max_rx_buf_size % 4) ||
- (param->hdlc.max_rx_buf_size < 8))
+ if (param->hdlc.max_rx_buf_size % 4 ||
+ param->hdlc.max_rx_buf_size < 8)
return -EINVAL;
qmc_write16(chan->qmc->scc_pram + QMC_GBL_MRBLR,
@@ -532,11 +593,12 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
/* Restart receiver if needed */
if (chan->is_rx_halted && !chan->is_rx_stopped) {
/* Restart receiver */
- if (chan->mode == QMC_TRANSPARENT)
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
- else
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK, chan->qmc->data->rpack);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE,
+ chan->mode == QMC_TRANSPARENT ?
+ chan->qmc->data->zdstate_transp :
+ chan->qmc->data->zdstate_hdlc);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE, chan->qmc->data->rstate);
chan->is_rx_halted = false;
}
chan->rx_pending++;
@@ -641,7 +703,7 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser
return -EINVAL;
}
- val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+ val = QMC_TSA_VALID | QMC_TSA_MASK_8BIT | QMC_TSA_CHANNEL(chan->id);
/* Check entries based on Rx stuff*/
for (i = 0; i < info->nb_rx_ts; i++) {
@@ -662,7 +724,7 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser
continue;
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
- ~QMC_TSA_WRAP, enable ? val : 0x0000);
+ (u16)~QMC_TSA_WRAP, enable ? val : 0x0000);
}
return 0;
@@ -677,7 +739,7 @@ static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct tsa_seria
/* Use a Rx 32 entries table */
- val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+ val = QMC_TSA_VALID | QMC_TSA_MASK_8BIT | QMC_TSA_CHANNEL(chan->id);
/* Check entries based on Rx stuff */
for (i = 0; i < info->nb_rx_ts; i++) {
@@ -698,7 +760,7 @@ static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct tsa_seria
continue;
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
- ~QMC_TSA_WRAP, enable ? val : 0x0000);
+ (u16)~QMC_TSA_WRAP, enable ? val : 0x0000);
}
return 0;
@@ -713,7 +775,7 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_seria
/* Use a Tx 32 entries table */
- val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+ val = QMC_TSA_VALID | QMC_TSA_MASK_8BIT | QMC_TSA_CHANNEL(chan->id);
/* Check entries based on Tx stuff */
for (i = 0; i < info->nb_tx_ts; i++) {
@@ -734,7 +796,7 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_seria
continue;
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2),
- ~QMC_TSA_WRAP, enable ? val : 0x0000);
+ (u16)~QMC_TSA_WRAP, enable ? val : 0x0000);
}
return 0;
@@ -774,11 +836,18 @@ static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable)
return qmc_chan_setup_tsa_32rx(chan, &info, enable);
}
-static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode)
+static int qmc_chan_cpm1_command(struct qmc_chan *chan, u8 qmc_opcode)
{
return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E);
}
+static int qmc_chan_qe_command(struct qmc_chan *chan, u32 cmd)
+{
+ if (!qe_issue_cmd(cmd, chan->qmc->qe_subblock, chan->id, 0))
+ return -EIO;
+ return 0;
+}
+
static int qmc_chan_stop_rx(struct qmc_chan *chan)
{
unsigned long flags;
@@ -793,7 +862,9 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan)
}
/* Send STOP RECEIVE command */
- ret = qmc_chan_command(chan, 0x0);
+ ret = qmc_is_qe(chan->qmc) ?
+ qmc_chan_qe_command(chan, QE_QMC_STOP_RX) :
+ qmc_chan_cpm1_command(chan, 0x0);
if (ret) {
dev_err(chan->qmc->dev, "chan %u: Send STOP RECEIVE failed (%d)\n",
chan->id, ret);
@@ -830,7 +901,9 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan)
}
/* Send STOP TRANSMIT command */
- ret = qmc_chan_command(chan, 0x1);
+ ret = qmc_is_qe(chan->qmc) ?
+ qmc_chan_qe_command(chan, QE_QMC_STOP_TX) :
+ qmc_chan_cpm1_command(chan, 0x1);
if (ret) {
dev_err(chan->qmc->dev, "chan %u: Send STOP TRANSMIT failed (%d)\n",
chan->id, ret);
@@ -889,6 +962,7 @@ EXPORT_SYMBOL(qmc_chan_stop);
static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
{
struct tsa_serial_info info;
+ unsigned int w_rx, w_tx;
u16 first_rx, last_tx;
u16 trnsync;
int ret;
@@ -898,6 +972,14 @@ static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
if (ret)
return ret;
+ w_rx = hweight64(chan->rx_ts_mask);
+ w_tx = hweight64(chan->tx_ts_mask);
+ if (w_rx <= 1 && w_tx <= 1) {
+ dev_dbg(qmc->dev, "only one or zero ts -> disable trnsync\n");
+ qmc_clrbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_TRANSP_SYNC);
+ return 0;
+ }
+
/* Find the first Rx TS allocated to the channel */
first_rx = chan->rx_ts_mask ? __ffs64(chan->rx_ts_mask) + 1 : 0;
@@ -911,6 +993,7 @@ static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
trnsync |= QMC_SPE_TRNSYNC_TX((last_tx % info.nb_tx_ts) * 2);
qmc_write16(chan->s_param + QMC_SPE_TRNSYNC, trnsync);
+ qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_TRANSP_SYNC);
dev_dbg(qmc->dev, "chan %u: trnsync=0x%04x, rx %u/%u 0x%llx, tx %u/%u 0x%llx\n",
chan->id, trnsync,
@@ -940,19 +1023,22 @@ static int qmc_chan_start_rx(struct qmc_chan *chan)
goto end;
}
- ret = qmc_setup_chan_trnsync(chan->qmc, chan);
- if (ret) {
- dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
- chan->id, ret);
- goto end;
+ if (chan->mode == QMC_TRANSPARENT) {
+ ret = qmc_setup_chan_trnsync(chan->qmc, chan);
+ if (ret) {
+ dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
+ chan->id, ret);
+ goto end;
+ }
}
/* Restart the receiver */
- if (chan->mode == QMC_TRANSPARENT)
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
- else
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK, chan->qmc->data->rpack);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE,
+ chan->mode == QMC_TRANSPARENT ?
+ chan->qmc->data->zdstate_transp :
+ chan->qmc->data->zdstate_hdlc);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE, chan->qmc->data->rstate);
chan->is_rx_halted = false;
chan->is_rx_stopped = false;
@@ -982,11 +1068,13 @@ static int qmc_chan_start_tx(struct qmc_chan *chan)
goto end;
}
- ret = qmc_setup_chan_trnsync(chan->qmc, chan);
- if (ret) {
- dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
- chan->id, ret);
- goto end;
+ if (chan->mode == QMC_TRANSPARENT) {
+ ret = qmc_setup_chan_trnsync(chan->qmc, chan);
+ if (ret) {
+ dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
+ chan->id, ret);
+ goto end;
+ }
}
/*
@@ -1096,8 +1184,8 @@ static void qmc_chan_reset_tx(struct qmc_chan *chan)
qmc_read16(chan->s_param + QMC_SPE_TBASE));
/* Reset TSTATE and ZISTATE to their initial value */
- qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000);
- qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100);
+ qmc_write32(chan->s_param + QMC_SPE_TSTATE, chan->qmc->data->tstate);
+ qmc_write32(chan->s_param + QMC_SPE_ZISTATE, chan->qmc->data->zistate);
spin_unlock_irqrestore(&chan->tx_lock, flags);
}
@@ -1127,7 +1215,7 @@ static int qmc_check_chans(struct qmc *qmc)
if (ret)
return ret;
- if ((info.nb_tx_ts > 64) || (info.nb_rx_ts > 64)) {
+ if (info.nb_tx_ts > 64 || info.nb_rx_ts > 64) {
dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned not supported\n");
return -EINVAL;
}
@@ -1136,7 +1224,7 @@ static int qmc_check_chans(struct qmc *qmc)
* If more than 32 TS are assigned to this serial, one common table is
* used for Tx and Rx and so masks must be equal for all channels.
*/
- if ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) {
+ if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32) {
if (info.nb_tx_ts != info.nb_rx_ts) {
dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned are not equal\n");
return -EINVAL;
@@ -1368,13 +1456,14 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan)
val = ((chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)) + QMC_NB_TXBDS) * sizeof(cbd_t);
qmc_write16(chan->s_param + QMC_SPE_RBASE, val);
qmc_write16(chan->s_param + QMC_SPE_RBPTR, val);
- qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
- qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100);
+ qmc_write32(chan->s_param + QMC_SPE_TSTATE, chan->qmc->data->tstate);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE, chan->qmc->data->rstate);
+ qmc_write32(chan->s_param + QMC_SPE_ZISTATE, chan->qmc->data->zistate);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK, chan->qmc->data->rpack);
if (chan->mode == QMC_TRANSPARENT) {
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, chan->qmc->data->zdstate_transp);
qmc_write16(chan->s_param + QMC_SPE_TMRBLR, 60);
- val = QMC_SPE_CHAMR_MODE_TRANSP | QMC_SPE_CHAMR_TRANSP_SYNC;
+ val = QMC_SPE_CHAMR_MODE_TRANSP;
if (chan->is_reverse_data)
val |= QMC_SPE_CHAMR_TRANSP_RD;
qmc_write16(chan->s_param + QMC_SPE_CHAMR, val);
@@ -1382,10 +1471,10 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan)
if (ret)
return ret;
} else {
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, chan->qmc->data->zdstate_hdlc);
qmc_write16(chan->s_param + QMC_SPE_MFLR, 60);
qmc_write16(chan->s_param + QMC_SPE_CHAMR,
- QMC_SPE_CHAMR_MODE_HDLC | QMC_SPE_CHAMR_HDLC_IDLM);
+ QMC_SPE_CHAMR_MODE_HDLC | QMC_SPE_CHAMR_HDLC_IDLM);
}
/* Do not enable interrupts now. They will be enabled later */
@@ -1510,11 +1599,14 @@ static void qmc_irq_gint(struct qmc *qmc)
/* Restart the receiver if needed */
spin_lock_irqsave(&chan->rx_lock, flags);
if (chan->rx_pending && !chan->is_rx_stopped) {
- if (chan->mode == QMC_TRANSPARENT)
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
- else
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK,
+ chan->qmc->data->rpack);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE,
+ chan->mode == QMC_TRANSPARENT ?
+ chan->qmc->data->zdstate_transp :
+ chan->qmc->data->zdstate_hdlc);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE,
+ chan->qmc->data->rstate);
chan->is_rx_halted = false;
} else {
chan->is_rx_halted = true;
@@ -1558,27 +1650,74 @@ static irqreturn_t qmc_irq_handler(int irq, void *priv)
return IRQ_HANDLED;
}
-static int qmc_probe(struct platform_device *pdev)
+static int qmc_qe_soft_qmc_init(struct qmc *qmc, struct device_node *np)
{
- struct device_node *np = pdev->dev.of_node;
- unsigned int nb_chans;
- struct resource *res;
- struct qmc *qmc;
- int irq;
+ struct qe_firmware_info *qe_fw_info;
+ const struct qe_firmware *qe_fw;
+ const struct firmware *fw;
+ const char *filename;
int ret;
- qmc = devm_kzalloc(&pdev->dev, sizeof(*qmc), GFP_KERNEL);
- if (!qmc)
- return -ENOMEM;
+ ret = of_property_read_string(np, "fsl,soft-qmc", &filename);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ /* fsl,soft-qmc property not set -> Simply do nothing */
+ return 0;
+ default:
+ dev_err(qmc->dev, "%pOF: failed to read fsl,soft-qmc\n",
+ np);
+ return ret;
+ }
- qmc->dev = &pdev->dev;
- INIT_LIST_HEAD(&qmc->chan_head);
+ qe_fw_info = qe_get_firmware_info();
+ if (qe_fw_info) {
+ if (!strstr(qe_fw_info->id, "Soft-QMC")) {
+ dev_err(qmc->dev, "Another Firmware is already loaded\n");
+ return -EALREADY;
+ }
+ dev_info(qmc->dev, "Firmware already loaded\n");
+ return 0;
+ }
+
+ dev_info(qmc->dev, "Using firmware %s\n", filename);
+
+ ret = request_firmware(&fw, filename, qmc->dev);
+ if (ret) {
+ dev_err(qmc->dev, "Failed to request firmware %s\n", filename);
+ return ret;
+ }
+
+ qe_fw = (const struct qe_firmware *)fw->data;
+
+ if (fw->size < sizeof(qe_fw->header) ||
+ be32_to_cpu(qe_fw->header.length) != fw->size) {
+ dev_err(qmc->dev, "Invalid firmware %s\n", filename);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = qe_upload_firmware(qe_fw);
+ if (ret) {
+ dev_err(qmc->dev, "Failed to load firmware %s\n", filename);
+ goto end;
+ }
+
+ ret = 0;
+end:
+ release_firmware(fw);
+ return ret;
+}
+
+static int qmc_cpm1_init_resources(struct qmc *qmc, struct platform_device *pdev)
+{
+ struct resource *res;
qmc->scc_regs = devm_platform_ioremap_resource_byname(pdev, "scc_regs");
if (IS_ERR(qmc->scc_regs))
return PTR_ERR(qmc->scc_regs);
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scc_pram");
if (!res)
return -EINVAL;
@@ -1591,44 +1730,214 @@ static int qmc_probe(struct platform_device *pdev)
if (IS_ERR(qmc->dpram))
return PTR_ERR(qmc->dpram);
+ return 0;
+}
+
+static int qmc_qe_init_resources(struct qmc *qmc, struct platform_device *pdev)
+{
+ struct resource *res;
+ int ucc_num;
+ s32 info;
+
+ qmc->scc_regs = devm_platform_ioremap_resource_byname(pdev, "ucc_regs");
+ if (IS_ERR(qmc->scc_regs))
+ return PTR_ERR(qmc->scc_regs);
+
+ ucc_num = tsa_serial_get_num(qmc->tsa_serial);
+ if (ucc_num < 0)
+ return dev_err_probe(qmc->dev, ucc_num, "Failed to get UCC num\n");
+
+ qmc->qe_subblock = ucc_slow_get_qe_cr_subblock(ucc_num);
+ if (qmc->qe_subblock == QE_CR_SUBBLOCK_INVALID) {
+ dev_err(qmc->dev, "Unsupported ucc num %u\n", ucc_num);
+ return -EINVAL;
+ }
+ /* Allocate the 'Global Multichannel Parameters' and the
+ * 'Framer parameters' areas. The 'Framer parameters' area
+ * is located right after the 'Global Multichannel Parameters'.
+ * The 'Framer parameters' need 1 byte per receive and transmit
+ * channel. The maximum number of receive or transmit channel
+ * is 64. So reserve 2 * 64 bytes for the 'Framer parameters'.
+ */
+ info = devm_qe_muram_alloc(qmc->dev, UCC_SLOW_PRAM_SIZE + 2 * 64,
+ ALIGNMENT_OF_UCC_SLOW_PRAM);
+ if (info < 0)
+ return info;
+
+ if (!qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, qmc->qe_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, info)) {
+ dev_err(qmc->dev, "QE_ASSIGN_PAGE_TO_DEVICE cmd failed");
+ return -EIO;
+ }
+ qmc->scc_pram = qe_muram_addr(info);
+ qmc->scc_pram_offset = info;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpram");
+ if (!res)
+ return -EINVAL;
+ qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0));
+ qmc->dpram = devm_ioremap_resource(qmc->dev, res);
+ if (IS_ERR(qmc->scc_pram))
+ return PTR_ERR(qmc->scc_pram);
+
+ return 0;
+}
+
+static int qmc_init_resources(struct qmc *qmc, struct platform_device *pdev)
+{
+ return qmc_is_qe(qmc) ?
+ qmc_qe_init_resources(qmc, pdev) :
+ qmc_cpm1_init_resources(qmc, pdev);
+}
+
+static int qmc_cpm1_init_scc(struct qmc *qmc)
+{
+ u32 val;
+ int ret;
+
+ /* Connect the serial (SCC) to TSA */
+ ret = tsa_serial_connect(qmc->tsa_serial);
+ if (ret)
+ return dev_err_probe(qmc->dev, ret, "Failed to connect TSA serial\n");
+
+ /* Init GMSR_H and GMSR_L registers */
+ val = SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP;
+ qmc_write32(qmc->scc_regs + SCC_GSMRH, val);
+
+ /* enable QMC mode */
+ qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_CPM1_GSMRL_MODE_QMC);
+
+ /* Disable and clear interrupts */
+ qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000);
+ qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F);
+
+ return 0;
+}
+
+static int qmc_qe_init_ucc(struct qmc *qmc)
+{
+ u32 val;
+ int ret;
+
+ /* Set the UCC in slow mode */
+ qmc_write8(qmc->scc_regs + SCC_QE_UCC_GUEMR,
+ UCC_GUEMR_SET_RESERVED3 | UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX);
+
+ /* Connect the serial (UCC) to TSA */
+ ret = tsa_serial_connect(qmc->tsa_serial);
+ if (ret)
+ return dev_err_probe(qmc->dev, ret, "Failed to connect TSA serial\n");
+
+ /* Initialize the QMC tx startup addresses */
+ if (!qe_issue_cmd(QE_PUSHSCHED, qmc->qe_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0x80)) {
+ dev_err(qmc->dev, "QE_CMD_PUSH_SCHED tx cmd failed");
+ ret = -EIO;
+ goto err_tsa_serial_disconnect;
+ }
+
+ /* Initialize the QMC rx startup addresses */
+ if (!qe_issue_cmd(QE_PUSHSCHED, qmc->qe_subblock | 0x00020000,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0x82)) {
+ dev_err(qmc->dev, "QE_CMD_PUSH_SCHED rx cmd failed");
+ ret = -EIO;
+ goto err_tsa_serial_disconnect;
+ }
+
+ /* Re-init RXPTR and TXPTR with the content of RX_S_PTR and
+ * TX_S_PTR (RX_S_PTR and TX_S_PTR are initialized during
+ * qmc_setup_tsa() call
+ */
+ val = qmc_read16(qmc->scc_pram + QMC_GBL_RX_S_PTR);
+ qmc_write16(qmc->scc_pram + QMC_GBL_RXPTR, val);
+ val = qmc_read16(qmc->scc_pram + QMC_GBL_TX_S_PTR);
+ qmc_write16(qmc->scc_pram + QMC_GBL_TXPTR, val);
+
+ /* Init GUMR_H and GUMR_L registers (SCC GSMR_H and GSMR_L) */
+ val = SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP |
+ SCC_GSMRH_TRX | SCC_GSMRH_TTX;
+ qmc_write32(qmc->scc_regs + SCC_GSMRH, val);
+
+ /* enable QMC mode */
+ qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_QE_GSMRL_MODE_QMC);
+
+ /* Disable and clear interrupts */
+ qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000);
+ qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F);
+
+ return 0;
+
+err_tsa_serial_disconnect:
+ tsa_serial_disconnect(qmc->tsa_serial);
+ return ret;
+}
+
+static int qmc_init_xcc(struct qmc *qmc)
+{
+ return qmc_is_qe(qmc) ?
+ qmc_qe_init_ucc(qmc) :
+ qmc_cpm1_init_scc(qmc);
+}
+
+static void qmc_exit_xcc(struct qmc *qmc)
+{
+ /* Disconnect the serial from TSA */
+ tsa_serial_disconnect(qmc->tsa_serial);
+}
+
+static int qmc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ unsigned int nb_chans;
+ struct qmc *qmc;
+ int irq;
+ int ret;
+
+ qmc = devm_kzalloc(&pdev->dev, sizeof(*qmc), GFP_KERNEL);
+ if (!qmc)
+ return -ENOMEM;
+
+ qmc->dev = &pdev->dev;
+ qmc->data = of_device_get_match_data(&pdev->dev);
+ if (!qmc->data) {
+ dev_err(qmc->dev, "Missing match data\n");
+ return -EINVAL;
+ }
+ INIT_LIST_HEAD(&qmc->chan_head);
+
qmc->tsa_serial = devm_tsa_serial_get_byphandle(qmc->dev, np, "fsl,tsa-serial");
if (IS_ERR(qmc->tsa_serial)) {
return dev_err_probe(qmc->dev, PTR_ERR(qmc->tsa_serial),
"Failed to get TSA serial\n");
}
- /* Connect the serial (SCC) to TSA */
- ret = tsa_serial_connect(qmc->tsa_serial);
- if (ret) {
- dev_err(qmc->dev, "Failed to connect TSA serial\n");
+ ret = qmc_init_resources(qmc, pdev);
+ if (ret)
return ret;
+
+ if (qmc_is_qe(qmc)) {
+ ret = qmc_qe_soft_qmc_init(qmc, np);
+ if (ret)
+ return ret;
}
/* Parse channels informationss */
ret = qmc_of_parse_chans(qmc, np);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
nb_chans = qmc_nb_chans(qmc);
- /* Init GMSR_H and GMSR_L registers */
- qmc_write32(qmc->scc_regs + SCC_GSMRH,
- SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP);
-
- /* enable QMC mode */
- qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_MODE_QMC);
-
/*
* Allocate the buffer descriptor table
* 8 rx and 8 tx descriptors per channel
*/
qmc->bd_size = (nb_chans * (QMC_NB_TXBDS + QMC_NB_RXBDS)) * sizeof(cbd_t);
qmc->bd_table = dmam_alloc_coherent(qmc->dev, qmc->bd_size,
- &qmc->bd_dma_addr, GFP_KERNEL);
+ &qmc->bd_dma_addr, GFP_KERNEL);
if (!qmc->bd_table) {
dev_err(qmc->dev, "Failed to allocate bd table\n");
- ret = -ENOMEM;
- goto err_tsa_serial_disconnect;
+ return -ENOMEM;
}
memset(qmc->bd_table, 0, qmc->bd_size);
@@ -1637,11 +1946,10 @@ static int qmc_probe(struct platform_device *pdev)
/* Allocate the interrupt table */
qmc->int_size = QMC_NB_INTS * sizeof(u16);
qmc->int_table = dmam_alloc_coherent(qmc->dev, qmc->int_size,
- &qmc->int_dma_addr, GFP_KERNEL);
+ &qmc->int_dma_addr, GFP_KERNEL);
if (!qmc->int_table) {
dev_err(qmc->dev, "Failed to allocate interrupt table\n");
- ret = -ENOMEM;
- goto err_tsa_serial_disconnect;
+ return -ENOMEM;
}
memset(qmc->int_table, 0, qmc->int_size);
@@ -1658,40 +1966,61 @@ static int qmc_probe(struct platform_device *pdev)
qmc_write32(qmc->scc_pram + QMC_GBL_C_MASK32, 0xDEBB20E3);
qmc_write16(qmc->scc_pram + QMC_GBL_C_MASK16, 0xF0B8);
+ if (qmc_is_qe(qmc)) {
+ /* Zeroed the reserved area */
+ memset_io(qmc->scc_pram + QMC_QE_GBL_RSV_B0_START, 0,
+ QMC_QE_GBL_RSV_B0_SIZE);
+
+ qmc_write32(qmc->scc_pram + QMC_QE_GBL_GCSBASE, qmc->dpram_offset);
+
+ /* Init 'framer parameters' area and set the base addresses */
+ memset_io(qmc->scc_pram + UCC_SLOW_PRAM_SIZE, 0x01, 64);
+ memset_io(qmc->scc_pram + UCC_SLOW_PRAM_SIZE + 64, 0x01, 64);
+ qmc_write16(qmc->scc_pram + QMC_QE_GBL_RX_FRM_BASE,
+ qmc->scc_pram_offset + UCC_SLOW_PRAM_SIZE);
+ qmc_write16(qmc->scc_pram + QMC_QE_GBL_TX_FRM_BASE,
+ qmc->scc_pram_offset + UCC_SLOW_PRAM_SIZE + 64);
+ }
+
ret = qmc_init_tsa(qmc);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
qmc_write16(qmc->scc_pram + QMC_GBL_QMCSTATE, 0x8000);
ret = qmc_setup_chans(qmc);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
/* Init interrupts table */
ret = qmc_setup_ints(qmc);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
- /* Disable and clear interrupts, set the irq handler */
- qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000);
- qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F);
+ /* Init SCC (CPM1) or UCC (QE) */
+ ret = qmc_init_xcc(qmc);
+ if (ret)
+ return ret;
+
+ /* Set the irq handler */
irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- goto err_tsa_serial_disconnect;
+ if (irq < 0) {
+ ret = irq;
+ goto err_exit_xcc;
+ }
ret = devm_request_irq(qmc->dev, irq, qmc_irq_handler, 0, "qmc", qmc);
if (ret < 0)
- goto err_tsa_serial_disconnect;
+ goto err_exit_xcc;
/* Enable interrupts */
qmc_write16(qmc->scc_regs + SCC_SCCM,
- SCC_SCCE_IQOV | SCC_SCCE_GINT | SCC_SCCE_GUN | SCC_SCCE_GOV);
+ SCC_SCCE_IQOV | SCC_SCCE_GINT | SCC_SCCE_GUN | SCC_SCCE_GOV);
ret = qmc_finalize_chans(qmc);
if (ret < 0)
goto err_disable_intr;
- /* Enable transmiter and receiver */
+ /* Enable transmitter and receiver */
qmc_setbits32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
platform_set_drvdata(pdev, qmc);
@@ -1709,8 +2038,8 @@ err_disable_txrx:
err_disable_intr:
qmc_write16(qmc->scc_regs + SCC_SCCM, 0);
-err_tsa_serial_disconnect:
- tsa_serial_disconnect(qmc->tsa_serial);
+err_exit_xcc:
+ qmc_exit_xcc(qmc);
return ret;
}
@@ -1718,18 +2047,43 @@ static void qmc_remove(struct platform_device *pdev)
{
struct qmc *qmc = platform_get_drvdata(pdev);
- /* Disable transmiter and receiver */
+ /* Disable transmitter and receiver */
qmc_setbits32(qmc->scc_regs + SCC_GSMRL, 0);
/* Disable interrupts */
qmc_write16(qmc->scc_regs + SCC_SCCM, 0);
- /* Disconnect the serial from TSA */
- tsa_serial_disconnect(qmc->tsa_serial);
+ /* Exit SCC (CPM1) or UCC (QE) */
+ qmc_exit_xcc(qmc);
}
+static const struct qmc_data qmc_data_cpm1 __maybe_unused = {
+ .version = QMC_CPM1,
+ .tstate = 0x30000000,
+ .rstate = 0x31000000,
+ .zistate = 0x00000100,
+ .zdstate_hdlc = 0x00000080,
+ .zdstate_transp = 0x18000080,
+ .rpack = 0x00000000,
+};
+
+static const struct qmc_data qmc_data_qe __maybe_unused = {
+ .version = QMC_QE,
+ .tstate = 0x30000000,
+ .rstate = 0x30000000,
+ .zistate = 0x00000200,
+ .zdstate_hdlc = 0x80FFFFE0,
+ .zdstate_transp = 0x003FFFE2,
+ .rpack = 0x80000000,
+};
+
static const struct of_device_id qmc_id_table[] = {
- { .compatible = "fsl,cpm1-scc-qmc" },
+#if IS_ENABLED(CONFIG_CPM1)
+ { .compatible = "fsl,cpm1-scc-qmc", .data = &qmc_data_cpm1 },
+#endif
+#if IS_ENABLED(CONFIG_QUICC_ENGINE)
+ { .compatible = "fsl,qe-ucc-qmc", .data = &qmc_data_qe },
+#endif
{} /* sentinel */
};
MODULE_DEVICE_TABLE(of, qmc_id_table);
@@ -1740,7 +2094,7 @@ static struct platform_driver qmc_driver = {
.of_match_table = of_match_ptr(qmc_id_table),
},
.probe = qmc_probe,
- .remove_new = qmc_remove,
+ .remove = qmc_remove,
};
module_platform_driver(qmc_driver);
@@ -1777,13 +2131,28 @@ static struct qmc_chan *qmc_chan_get_from_qmc(struct device_node *qmc_np, unsign
return qmc_chan;
}
-struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name)
+int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name)
+{
+ int count;
+
+ /* phandles are fixed args phandles with one arg */
+ count = of_count_phandle_with_args(np, phandles_name, NULL);
+ if (count < 0)
+ return count;
+
+ return count / 2;
+}
+EXPORT_SYMBOL(qmc_chan_count_phandles);
+
+struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np,
+ const char *phandles_name,
+ int index)
{
struct of_phandle_args out_args;
struct qmc_chan *qmc_chan;
int ret;
- ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0,
+ ret = of_parse_phandle_with_fixed_args(np, phandles_name, 1, index,
&out_args);
if (ret < 0)
return ERR_PTR(ret);
@@ -1797,7 +2166,7 @@ struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phan
of_node_put(out_args.np);
return qmc_chan;
}
-EXPORT_SYMBOL(qmc_chan_get_byphandle);
+EXPORT_SYMBOL(qmc_chan_get_byphandles_index);
struct qmc_chan *qmc_chan_get_bychild(struct device_node *np)
{
@@ -1827,9 +2196,10 @@ static void devm_qmc_chan_release(struct device *dev, void *res)
qmc_chan_put(*qmc_chan);
}
-struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev,
- struct device_node *np,
- const char *phandle_name)
+struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev,
+ struct device_node *np,
+ const char *phandles_name,
+ int index)
{
struct qmc_chan *qmc_chan;
struct qmc_chan **dr;
@@ -1838,7 +2208,7 @@ struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev,
if (!dr)
return ERR_PTR(-ENOMEM);
- qmc_chan = qmc_chan_get_byphandle(np, phandle_name);
+ qmc_chan = qmc_chan_get_byphandles_index(np, phandles_name, index);
if (!IS_ERR(qmc_chan)) {
*dr = qmc_chan;
devres_add(dev, dr);
@@ -1848,7 +2218,7 @@ struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev,
return qmc_chan;
}
-EXPORT_SYMBOL(devm_qmc_chan_get_byphandle);
+EXPORT_SYMBOL(devm_qmc_chan_get_byphandles_index);
struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev,
struct device_node *np)
@@ -1873,5 +2243,5 @@ struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev,
EXPORT_SYMBOL(devm_qmc_chan_get_bychild);
MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
-MODULE_DESCRIPTION("CPM QMC driver");
+MODULE_DESCRIPTION("CPM/QE QMC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c
index 6c5741cf5e9d..4a88e54d25b9 100644
--- a/drivers/soc/fsl/qe/tsa.c
+++ b/drivers/soc/fsl/qe/tsa.c
@@ -9,6 +9,8 @@
#include "tsa.h"
#include <dt-bindings/soc/cpm1-fsl,tsa.h>
+#include <dt-bindings/soc/qe-fsl,tsa.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -16,86 +18,116 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <soc/fsl/qe/ucc.h>
+
+/* TSA SI RAM routing tables entry (CPM1) */
+#define TSA_CPM1_SIRAM_ENTRY_LAST BIT(16)
+#define TSA_CPM1_SIRAM_ENTRY_BYTE BIT(17)
+#define TSA_CPM1_SIRAM_ENTRY_CNT_MASK GENMASK(21, 18)
+#define TSA_CPM1_SIRAM_ENTRY_CNT(x) FIELD_PREP(TSA_CPM1_SIRAM_ENTRY_CNT_MASK, x)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_MASK GENMASK(24, 22)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_NU FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x0)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SCC2 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x2)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SCC3 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x3)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SCC4 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x4)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SMC1 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x5)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SMC2 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x6)
+
+/* TSA SI RAM routing tables entry (QE) */
+#define TSA_QE_SIRAM_ENTRY_LAST BIT(0)
+#define TSA_QE_SIRAM_ENTRY_BYTE BIT(1)
+#define TSA_QE_SIRAM_ENTRY_CNT_MASK GENMASK(4, 2)
+#define TSA_QE_SIRAM_ENTRY_CNT(x) FIELD_PREP(TSA_QE_SIRAM_ENTRY_CNT_MASK, x)
+#define TSA_QE_SIRAM_ENTRY_CSEL_MASK GENMASK(8, 5)
+#define TSA_QE_SIRAM_ENTRY_CSEL_NU FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0x0)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC5 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0x1)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC1 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0x9)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC2 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0xa)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC3 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0xb)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC4 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0xc)
-
-/* TSA SI RAM routing tables entry */
-#define TSA_SIRAM_ENTRY_LAST (1 << 16)
-#define TSA_SIRAM_ENTRY_BYTE (1 << 17)
-#define TSA_SIRAM_ENTRY_CNT(x) (((x) & 0x0f) << 18)
-#define TSA_SIRAM_ENTRY_CSEL_MASK (0x7 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_NU (0x0 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SCC2 (0x2 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SCC3 (0x3 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SCC4 (0x4 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SMC1 (0x5 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SMC2 (0x6 << 22)
-
-/* SI mode register (32 bits) */
-#define TSA_SIMODE 0x00
-#define TSA_SIMODE_SMC2 0x80000000
-#define TSA_SIMODE_SMC1 0x00008000
-#define TSA_SIMODE_TDMA(x) ((x) << 0)
-#define TSA_SIMODE_TDMB(x) ((x) << 16)
-#define TSA_SIMODE_TDM_MASK 0x0fff
-#define TSA_SIMODE_TDM_SDM_MASK 0x0c00
-#define TSA_SIMODE_TDM_SDM_NORM 0x0000
-#define TSA_SIMODE_TDM_SDM_ECHO 0x0400
-#define TSA_SIMODE_TDM_SDM_INTL_LOOP 0x0800
-#define TSA_SIMODE_TDM_SDM_LOOP_CTRL 0x0c00
-#define TSA_SIMODE_TDM_RFSD(x) ((x) << 8)
-#define TSA_SIMODE_TDM_DSC 0x0080
-#define TSA_SIMODE_TDM_CRT 0x0040
-#define TSA_SIMODE_TDM_STZ 0x0020
-#define TSA_SIMODE_TDM_CE 0x0010
-#define TSA_SIMODE_TDM_FE 0x0008
-#define TSA_SIMODE_TDM_GM 0x0004
-#define TSA_SIMODE_TDM_TFSD(x) ((x) << 0)
-
-/* SI global mode register (8 bits) */
-#define TSA_SIGMR 0x04
-#define TSA_SIGMR_ENB (1<<3)
-#define TSA_SIGMR_ENA (1<<2)
-#define TSA_SIGMR_RDM_MASK 0x03
-#define TSA_SIGMR_RDM_STATIC_TDMA 0x00
-#define TSA_SIGMR_RDM_DYN_TDMA 0x01
-#define TSA_SIGMR_RDM_STATIC_TDMAB 0x02
-#define TSA_SIGMR_RDM_DYN_TDMAB 0x03
-
-/* SI status register (8 bits) */
-#define TSA_SISTR 0x06
-
-/* SI command register (8 bits) */
-#define TSA_SICMR 0x07
+/*
+ * SI mode register :
+ * - CPM1: 32bit register split in 2*16bit (16bit TDM)
+ * - QE: 4x16bit registers, one per TDM
+ */
+#define TSA_CPM1_SIMODE 0x00
+#define TSA_QE_SIAMR 0x00
+#define TSA_QE_SIBMR 0x02
+#define TSA_QE_SICMR 0x04
+#define TSA_QE_SIDMR 0x06
+#define TSA_CPM1_SIMODE_SMC2 BIT(31)
+#define TSA_CPM1_SIMODE_SMC1 BIT(15)
+#define TSA_CPM1_SIMODE_TDMA_MASK GENMASK(11, 0)
+#define TSA_CPM1_SIMODE_TDMA(x) FIELD_PREP(TSA_CPM1_SIMODE_TDMA_MASK, x)
+#define TSA_CPM1_SIMODE_TDMB_MASK GENMASK(27, 16)
+#define TSA_CPM1_SIMODE_TDMB(x) FIELD_PREP(TSA_CPM1_SIMODE_TDMB_MASK, x)
+#define TSA_QE_SIMODE_TDM_SAD_MASK GENMASK(15, 12)
+#define TSA_QE_SIMODE_TDM_SAD(x) FIELD_PREP(TSA_QE_SIMODE_TDM_SAD_MASK, x)
+#define TSA_CPM1_SIMODE_TDM_MASK GENMASK(11, 0)
+#define TSA_SIMODE_TDM_SDM_MASK GENMASK(11, 10)
+#define TSA_SIMODE_TDM_SDM_NORM FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x0)
+#define TSA_SIMODE_TDM_SDM_ECHO FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x1)
+#define TSA_SIMODE_TDM_SDM_INTL_LOOP FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x2)
+#define TSA_SIMODE_TDM_SDM_LOOP_CTRL FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x3)
+#define TSA_SIMODE_TDM_RFSD_MASK GENMASK(9, 8)
+#define TSA_SIMODE_TDM_RFSD(x) FIELD_PREP(TSA_SIMODE_TDM_RFSD_MASK, x)
+#define TSA_SIMODE_TDM_DSC BIT(7)
+#define TSA_SIMODE_TDM_CRT BIT(6)
+#define TSA_CPM1_SIMODE_TDM_STZ BIT(5) /* bit 5: STZ in CPM1 */
+#define TSA_QE_SIMODE_TDM_SL BIT(5) /* bit 5: SL in QE */
+#define TSA_SIMODE_TDM_CE BIT(4)
+#define TSA_SIMODE_TDM_FE BIT(3)
+#define TSA_SIMODE_TDM_GM BIT(2)
+#define TSA_SIMODE_TDM_TFSD_MASK GENMASK(1, 0)
+#define TSA_SIMODE_TDM_TFSD(x) FIELD_PREP(TSA_SIMODE_TDM_TFSD_MASK, x)
+
+/* CPM SI global mode register (8 bits) */
+#define TSA_CPM1_SIGMR 0x04
+#define TSA_CPM1_SIGMR_ENB BIT(3)
+#define TSA_CPM1_SIGMR_ENA BIT(2)
+#define TSA_CPM1_SIGMR_RDM_MASK GENMASK(1, 0)
+#define TSA_CPM1_SIGMR_RDM_STATIC_TDMA FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x0)
+#define TSA_CPM1_SIGMR_RDM_DYN_TDMA FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x1)
+#define TSA_CPM1_SIGMR_RDM_STATIC_TDMAB FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x2)
+#define TSA_CPM1_SIGMR_RDM_DYN_TDMAB FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x3)
+
+/* QE SI global mode register high (8 bits) */
+#define TSA_QE_SIGLMRH 0x08
+#define TSA_QE_SIGLMRH_END BIT(3)
+#define TSA_QE_SIGLMRH_ENC BIT(2)
+#define TSA_QE_SIGLMRH_ENB BIT(1)
+#define TSA_QE_SIGLMRH_ENA BIT(0)
/* SI clock route register (32 bits) */
-#define TSA_SICR 0x0C
-#define TSA_SICR_SCC2(x) ((x) << 8)
-#define TSA_SICR_SCC3(x) ((x) << 16)
-#define TSA_SICR_SCC4(x) ((x) << 24)
-#define TSA_SICR_SCC_MASK 0x0ff
-#define TSA_SICR_SCC_GRX (1 << 7)
-#define TSA_SICR_SCC_SCX_TSA (1 << 6)
-#define TSA_SICR_SCC_RXCS_MASK (0x7 << 3)
-#define TSA_SICR_SCC_RXCS_BRG1 (0x0 << 3)
-#define TSA_SICR_SCC_RXCS_BRG2 (0x1 << 3)
-#define TSA_SICR_SCC_RXCS_BRG3 (0x2 << 3)
-#define TSA_SICR_SCC_RXCS_BRG4 (0x3 << 3)
-#define TSA_SICR_SCC_RXCS_CLK15 (0x4 << 3)
-#define TSA_SICR_SCC_RXCS_CLK26 (0x5 << 3)
-#define TSA_SICR_SCC_RXCS_CLK37 (0x6 << 3)
-#define TSA_SICR_SCC_RXCS_CLK48 (0x7 << 3)
-#define TSA_SICR_SCC_TXCS_MASK (0x7 << 0)
-#define TSA_SICR_SCC_TXCS_BRG1 (0x0 << 0)
-#define TSA_SICR_SCC_TXCS_BRG2 (0x1 << 0)
-#define TSA_SICR_SCC_TXCS_BRG3 (0x2 << 0)
-#define TSA_SICR_SCC_TXCS_BRG4 (0x3 << 0)
-#define TSA_SICR_SCC_TXCS_CLK15 (0x4 << 0)
-#define TSA_SICR_SCC_TXCS_CLK26 (0x5 << 0)
-#define TSA_SICR_SCC_TXCS_CLK37 (0x6 << 0)
-#define TSA_SICR_SCC_TXCS_CLK48 (0x7 << 0)
-
-/* Serial interface RAM pointer register (32 bits) */
-#define TSA_SIRP 0x10
+#define TSA_CPM1_SICR 0x0C
+#define TSA_CPM1_SICR_SCC2_MASK GENMASK(15, 8)
+#define TSA_CPM1_SICR_SCC2(x) FIELD_PREP(TSA_CPM1_SICR_SCC2_MASK, x)
+#define TSA_CPM1_SICR_SCC3_MASK GENMASK(23, 16)
+#define TSA_CPM1_SICR_SCC3(x) FIELD_PREP(TSA_CPM1_SICR_SCC3_MASK, x)
+#define TSA_CPM1_SICR_SCC4_MASK GENMASK(31, 24)
+#define TSA_CPM1_SICR_SCC4(x) FIELD_PREP(TSA_CPM1_SICR_SCC4_MASK, x)
+#define TSA_CPM1_SICR_SCC_MASK GENMASK(7, 0)
+#define TSA_CPM1_SICR_SCC_GRX BIT(7)
+#define TSA_CPM1_SICR_SCC_SCX_TSA BIT(6)
+#define TSA_CPM1_SICR_SCC_RXCS_MASK GENMASK(5, 3)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG1 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x0)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG2 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x1)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG3 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x2)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG4 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x3)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK15 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x4)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK26 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x5)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK37 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x6)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK48 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x7)
+#define TSA_CPM1_SICR_SCC_TXCS_MASK GENMASK(2, 0)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG1 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x0)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG2 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x1)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG3 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x2)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG4 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x3)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK15 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x4)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK26 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x5)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK37 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x6)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK48 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x7)
struct tsa_entries_area {
void __iomem *entries_start;
@@ -114,15 +146,31 @@ struct tsa_tdm {
#define TSA_TDMA 0
#define TSA_TDMB 1
+#define TSA_TDMC 2 /* QE implementation only */
+#define TSA_TDMD 3 /* QE implementation only */
+
+enum tsa_version {
+ TSA_CPM1 = 1, /* Avoid 0 value */
+ TSA_QE,
+};
struct tsa {
struct device *dev;
void __iomem *si_regs;
void __iomem *si_ram;
resource_size_t si_ram_sz;
- spinlock_t lock;
+ spinlock_t lock; /* Lock for read/modify/write sequence */
+ enum tsa_version version;
int tdms; /* TSA_TDMx ORed */
+#if IS_ENABLED(CONFIG_QUICC_ENGINE)
+ struct tsa_tdm tdm[4]; /* TDMa, TDMb, TDMc and TDMd */
+#else
struct tsa_tdm tdm[2]; /* TDMa and TDMb */
+#endif
+ /* Same number of serials for CPM1 and QE:
+ * CPM1: NU, 3 SCCs and 2 SMCs
+ * QE: NU and 5 UCCs
+ */
struct tsa_serial {
unsigned int id;
struct tsa_serial_info info;
@@ -140,7 +188,12 @@ static inline void tsa_write32(void __iomem *addr, u32 val)
iowrite32be(val, addr);
}
-static inline void tsa_write8(void __iomem *addr, u32 val)
+static inline void tsa_write16(void __iomem *addr, u16 val)
+{
+ iowrite16be(val, addr);
+}
+
+static inline void tsa_write8(void __iomem *addr, u8 val)
{
iowrite8(val, addr);
}
@@ -150,17 +203,68 @@ static inline u32 tsa_read32(void __iomem *addr)
return ioread32be(addr);
}
+static inline u16 tsa_read16(void __iomem *addr)
+{
+ return ioread16be(addr);
+}
+
static inline void tsa_clrbits32(void __iomem *addr, u32 clr)
{
tsa_write32(addr, tsa_read32(addr) & ~clr);
}
+static inline void tsa_clrbits16(void __iomem *addr, u16 clr)
+{
+ tsa_write16(addr, tsa_read16(addr) & ~clr);
+}
+
static inline void tsa_clrsetbits32(void __iomem *addr, u32 clr, u32 set)
{
tsa_write32(addr, (tsa_read32(addr) & ~clr) | set);
}
-int tsa_serial_connect(struct tsa_serial *tsa_serial)
+static bool tsa_is_qe(const struct tsa *tsa)
+{
+ if (IS_ENABLED(CONFIG_QUICC_ENGINE) && IS_ENABLED(CONFIG_CPM))
+ return tsa->version == TSA_QE;
+
+ return IS_ENABLED(CONFIG_QUICC_ENGINE);
+}
+
+static int tsa_qe_serial_get_num(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ switch (tsa_serial->id) {
+ case FSL_QE_TSA_UCC1: return 0;
+ case FSL_QE_TSA_UCC2: return 1;
+ case FSL_QE_TSA_UCC3: return 2;
+ case FSL_QE_TSA_UCC4: return 3;
+ case FSL_QE_TSA_UCC5: return 4;
+ default:
+ break;
+ }
+
+ dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id);
+ return -EINVAL;
+}
+
+int tsa_serial_get_num(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ /*
+ * There is no need to get the serial num out of the TSA driver in the
+ * CPM case.
+ * Further more, in CPM, we can have 2 types of serial SCCs and FCCs.
+ * What kind of numbering to use that can be global to both SCCs and
+ * FCCs ?
+ */
+ return tsa_is_qe(tsa) ? tsa_qe_serial_get_num(tsa_serial) : -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(tsa_serial_get_num);
+
+static int tsa_cpm1_serial_connect(struct tsa_serial *tsa_serial, bool connect)
{
struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
unsigned long flags;
@@ -169,16 +273,16 @@ int tsa_serial_connect(struct tsa_serial *tsa_serial)
switch (tsa_serial->id) {
case FSL_CPM_TSA_SCC2:
- clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK);
- set = TSA_SICR_SCC2(TSA_SICR_SCC_SCX_TSA);
+ clear = TSA_CPM1_SICR_SCC2(TSA_CPM1_SICR_SCC_MASK);
+ set = TSA_CPM1_SICR_SCC2(TSA_CPM1_SICR_SCC_SCX_TSA);
break;
case FSL_CPM_TSA_SCC3:
- clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK);
- set = TSA_SICR_SCC3(TSA_SICR_SCC_SCX_TSA);
+ clear = TSA_CPM1_SICR_SCC3(TSA_CPM1_SICR_SCC_MASK);
+ set = TSA_CPM1_SICR_SCC3(TSA_CPM1_SICR_SCC_SCX_TSA);
break;
case FSL_CPM_TSA_SCC4:
- clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK);
- set = TSA_SICR_SCC4(TSA_SICR_SCC_SCX_TSA);
+ clear = TSA_CPM1_SICR_SCC4(TSA_CPM1_SICR_SCC_MASK);
+ set = TSA_CPM1_SICR_SCC4(TSA_CPM1_SICR_SCC_SCX_TSA);
break;
default:
dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id);
@@ -186,40 +290,53 @@ int tsa_serial_connect(struct tsa_serial *tsa_serial)
}
spin_lock_irqsave(&tsa->lock, flags);
- tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, set);
+ tsa_clrsetbits32(tsa->si_regs + TSA_CPM1_SICR, clear,
+ connect ? set : 0);
spin_unlock_irqrestore(&tsa->lock, flags);
return 0;
}
-EXPORT_SYMBOL(tsa_serial_connect);
-int tsa_serial_disconnect(struct tsa_serial *tsa_serial)
+static int tsa_qe_serial_connect(struct tsa_serial *tsa_serial, bool connect)
{
struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
unsigned long flags;
- u32 clear;
+ int ucc_num;
+ int ret;
- switch (tsa_serial->id) {
- case FSL_CPM_TSA_SCC2:
- clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK);
- break;
- case FSL_CPM_TSA_SCC3:
- clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK);
- break;
- case FSL_CPM_TSA_SCC4:
- clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK);
- break;
- default:
- dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id);
- return -EINVAL;
- }
+ ucc_num = tsa_qe_serial_get_num(tsa_serial);
+ if (ucc_num < 0)
+ return ucc_num;
spin_lock_irqsave(&tsa->lock, flags);
- tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, 0);
+ ret = ucc_set_qe_mux_tsa(ucc_num, connect);
spin_unlock_irqrestore(&tsa->lock, flags);
-
+ if (ret) {
+ dev_err(tsa->dev, "Connect serial id %u to TSA failed (%d)\n",
+ tsa_serial->id, ret);
+ return ret;
+ }
return 0;
}
+
+int tsa_serial_connect(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ return tsa_is_qe(tsa) ?
+ tsa_qe_serial_connect(tsa_serial, true) :
+ tsa_cpm1_serial_connect(tsa_serial, true);
+}
+EXPORT_SYMBOL(tsa_serial_connect);
+
+int tsa_serial_disconnect(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ return tsa_is_qe(tsa) ?
+ tsa_qe_serial_connect(tsa_serial, false) :
+ tsa_cpm1_serial_connect(tsa_serial, false);
+}
EXPORT_SYMBOL(tsa_serial_disconnect);
int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info)
@@ -229,14 +346,14 @@ int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *i
}
EXPORT_SYMBOL(tsa_serial_get_info);
-static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
- u32 tdms, u32 tdm_id, bool is_rx)
+static void tsa_cpm1_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 tdms, u32 tdm_id, bool is_rx)
{
resource_size_t quarter;
resource_size_t half;
- quarter = tsa->si_ram_sz/4;
- half = tsa->si_ram_sz/2;
+ quarter = tsa->si_ram_sz / 4;
+ half = tsa->si_ram_sz / 2;
if (tdms == BIT(TSA_TDMA)) {
/* Only TDMA */
@@ -281,7 +398,42 @@ static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area
}
}
-static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id)
+static void tsa_qe_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 tdms, u32 tdm_id, bool is_rx)
+{
+ resource_size_t eighth;
+ resource_size_t half;
+
+ eighth = tsa->si_ram_sz / 8;
+ half = tsa->si_ram_sz / 2;
+
+ /*
+ * One half of the SI RAM used for Tx, the other one for Rx.
+ * In each half, 1/4 of the area is assigned to each TDM.
+ */
+ if (is_rx) {
+ /* Rx: Second half of si_ram */
+ area->entries_start = tsa->si_ram + half + (eighth * tdm_id);
+ area->entries_next = area->entries_start + eighth;
+ area->last_entry = NULL;
+ } else {
+ /* Tx: First half of si_ram */
+ area->entries_start = tsa->si_ram + (eighth * tdm_id);
+ area->entries_next = area->entries_start + eighth;
+ area->last_entry = NULL;
+ }
+}
+
+static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 tdms, u32 tdm_id, bool is_rx)
+{
+ if (tsa_is_qe(tsa))
+ tsa_qe_init_entries_area(tsa, area, tdms, tdm_id, is_rx);
+ else
+ tsa_cpm1_init_entries_area(tsa, area, tdms, tdm_id, is_rx);
+}
+
+static const char *tsa_cpm1_serial_id2name(struct tsa *tsa, u32 serial_id)
{
switch (serial_id) {
case FSL_CPM_TSA_NU: return "Not used";
@@ -296,22 +448,44 @@ static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id)
return NULL;
}
-static u32 tsa_serial_id2csel(struct tsa *tsa, u32 serial_id)
+static const char *tsa_qe_serial_id2name(struct tsa *tsa, u32 serial_id)
{
switch (serial_id) {
- case FSL_CPM_TSA_SCC2: return TSA_SIRAM_ENTRY_CSEL_SCC2;
- case FSL_CPM_TSA_SCC3: return TSA_SIRAM_ENTRY_CSEL_SCC3;
- case FSL_CPM_TSA_SCC4: return TSA_SIRAM_ENTRY_CSEL_SCC4;
- case FSL_CPM_TSA_SMC1: return TSA_SIRAM_ENTRY_CSEL_SMC1;
- case FSL_CPM_TSA_SMC2: return TSA_SIRAM_ENTRY_CSEL_SMC2;
+ case FSL_QE_TSA_NU: return "Not used";
+ case FSL_QE_TSA_UCC1: return "UCC1";
+ case FSL_QE_TSA_UCC2: return "UCC2";
+ case FSL_QE_TSA_UCC3: return "UCC3";
+ case FSL_QE_TSA_UCC4: return "UCC4";
+ case FSL_QE_TSA_UCC5: return "UCC5";
default:
break;
}
- return TSA_SIRAM_ENTRY_CSEL_NU;
+ return NULL;
}
-static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
- u32 count, u32 serial_id)
+static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id)
+{
+ return tsa_is_qe(tsa) ?
+ tsa_qe_serial_id2name(tsa, serial_id) :
+ tsa_cpm1_serial_id2name(tsa, serial_id);
+}
+
+static u32 tsa_cpm1_serial_id2csel(struct tsa *tsa, u32 serial_id)
+{
+ switch (serial_id) {
+ case FSL_CPM_TSA_SCC2: return TSA_CPM1_SIRAM_ENTRY_CSEL_SCC2;
+ case FSL_CPM_TSA_SCC3: return TSA_CPM1_SIRAM_ENTRY_CSEL_SCC3;
+ case FSL_CPM_TSA_SCC4: return TSA_CPM1_SIRAM_ENTRY_CSEL_SCC4;
+ case FSL_CPM_TSA_SMC1: return TSA_CPM1_SIRAM_ENTRY_CSEL_SMC1;
+ case FSL_CPM_TSA_SMC2: return TSA_CPM1_SIRAM_ENTRY_CSEL_SMC2;
+ default:
+ break;
+ }
+ return TSA_CPM1_SIRAM_ENTRY_CSEL_NU;
+}
+
+static int tsa_cpm1_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 count, u32 serial_id)
{
void __iomem *addr;
u32 left;
@@ -329,21 +503,21 @@ static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
if (area->last_entry) {
/* Clear last flag */
- tsa_clrbits32(area->last_entry, TSA_SIRAM_ENTRY_LAST);
+ tsa_clrbits32(area->last_entry, TSA_CPM1_SIRAM_ENTRY_LAST);
}
left = count;
while (left) {
- val = TSA_SIRAM_ENTRY_BYTE | tsa_serial_id2csel(tsa, serial_id);
+ val = TSA_CPM1_SIRAM_ENTRY_BYTE | tsa_cpm1_serial_id2csel(tsa, serial_id);
if (left > 16) {
cnt = 16;
} else {
cnt = left;
- val |= TSA_SIRAM_ENTRY_LAST;
+ val |= TSA_CPM1_SIRAM_ENTRY_LAST;
area->last_entry = addr;
}
- val |= TSA_SIRAM_ENTRY_CNT(cnt - 1);
+ val |= TSA_CPM1_SIRAM_ENTRY_CNT(cnt - 1);
tsa_write32(addr, val);
addr += 4;
@@ -353,6 +527,71 @@ static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
return 0;
}
+static u32 tsa_qe_serial_id2csel(struct tsa *tsa, u32 serial_id)
+{
+ switch (serial_id) {
+ case FSL_QE_TSA_UCC1: return TSA_QE_SIRAM_ENTRY_CSEL_UCC1;
+ case FSL_QE_TSA_UCC2: return TSA_QE_SIRAM_ENTRY_CSEL_UCC2;
+ case FSL_QE_TSA_UCC3: return TSA_QE_SIRAM_ENTRY_CSEL_UCC3;
+ case FSL_QE_TSA_UCC4: return TSA_QE_SIRAM_ENTRY_CSEL_UCC4;
+ case FSL_QE_TSA_UCC5: return TSA_QE_SIRAM_ENTRY_CSEL_UCC5;
+ default:
+ break;
+ }
+ return TSA_QE_SIRAM_ENTRY_CSEL_NU;
+}
+
+static int tsa_qe_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 count, u32 serial_id)
+{
+ void __iomem *addr;
+ u32 left;
+ u32 val;
+ u32 cnt;
+ u32 nb;
+
+ addr = area->last_entry ? area->last_entry + 2 : area->entries_start;
+
+ nb = DIV_ROUND_UP(count, 8);
+ if ((addr + (nb * 2)) > area->entries_next) {
+ dev_err(tsa->dev, "si ram area full\n");
+ return -ENOSPC;
+ }
+
+ if (area->last_entry) {
+ /* Clear last flag */
+ tsa_clrbits16(area->last_entry, TSA_QE_SIRAM_ENTRY_LAST);
+ }
+
+ left = count;
+ while (left) {
+ val = TSA_QE_SIRAM_ENTRY_BYTE | tsa_qe_serial_id2csel(tsa, serial_id);
+
+ if (left > 8) {
+ cnt = 8;
+ } else {
+ cnt = left;
+ val |= TSA_QE_SIRAM_ENTRY_LAST;
+ area->last_entry = addr;
+ }
+ val |= TSA_QE_SIRAM_ENTRY_CNT(cnt - 1);
+
+ tsa_write16(addr, val);
+ addr += 2;
+ left -= cnt;
+ }
+
+ return 0;
+}
+
+static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 count, u32 serial_id)
+{
+ return tsa_is_qe(tsa) ?
+ tsa_qe_add_entry(tsa, area, count, serial_id) :
+ tsa_cpm1_add_entry(tsa, area, count, serial_id);
+}
+
static int tsa_of_parse_tdm_route(struct tsa *tsa, struct device_node *tdm_np,
u32 tdms, u32 tdm_id, bool is_rx)
{
@@ -399,7 +638,7 @@ static int tsa_of_parse_tdm_route(struct tsa *tsa, struct device_node *tdm_np,
}
dev_dbg(tsa->dev, "tdm_id=%u, %s ts %u..%u -> %s\n",
- tdm_id, route_name, ts, ts+count-1, serial_name);
+ tdm_id, route_name, ts, ts + count - 1, serial_name);
ts += count;
ret = tsa_add_entry(tsa, &area, count, serial_id);
@@ -441,7 +680,6 @@ static inline int tsa_of_parse_tdm_tx_route(struct tsa *tsa,
static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
{
- struct device_node *tdm_np;
struct tsa_tdm *tdm;
struct clk *clk;
u32 tdm_id, val;
@@ -449,14 +687,13 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
int i;
tsa->tdms = 0;
- tsa->tdm[0].is_enable = false;
- tsa->tdm[1].is_enable = false;
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++)
+ tsa->tdm[i].is_enable = false;
- for_each_available_child_of_node(np, tdm_np) {
+ for_each_available_child_of_node_scoped(np, tdm_np) {
ret = of_property_read_u32(tdm_np, "reg", &tdm_id);
if (ret) {
dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np);
- of_node_put(tdm_np);
return ret;
}
switch (tdm_id) {
@@ -466,19 +703,28 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
case 1:
tsa->tdms |= BIT(TSA_TDMB);
break;
+ case 2:
+ if (!tsa_is_qe(tsa))
+ goto invalid_tdm; /* Not available on CPM1 */
+ tsa->tdms |= BIT(TSA_TDMC);
+ break;
+ case 3:
+ if (!tsa_is_qe(tsa))
+ goto invalid_tdm; /* Not available on CPM1 */
+ tsa->tdms |= BIT(TSA_TDMD);
+ break;
default:
+invalid_tdm:
dev_err(tsa->dev, "%pOF: Invalid tdm_id (%u)\n", tdm_np,
tdm_id);
- of_node_put(tdm_np);
return -EINVAL;
}
}
- for_each_available_child_of_node(np, tdm_np) {
+ for_each_available_child_of_node_scoped(np, tdm_np) {
ret = of_property_read_u32(tdm_np, "reg", &tdm_id);
if (ret) {
dev_err(tsa->dev, "%pOF: failed to read reg\n", tdm_np);
- of_node_put(tdm_np);
return ret;
}
@@ -492,14 +738,12 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
dev_err(tsa->dev,
"%pOF: failed to read fsl,rx-frame-sync-delay-bits\n",
tdm_np);
- of_node_put(tdm_np);
return ret;
}
if (val > 3) {
dev_err(tsa->dev,
"%pOF: Invalid fsl,rx-frame-sync-delay-bits (%u)\n",
tdm_np, val);
- of_node_put(tdm_np);
return -EINVAL;
}
tdm->simode_tdm |= TSA_SIMODE_TDM_RFSD(val);
@@ -511,14 +755,12 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
dev_err(tsa->dev,
"%pOF: failed to read fsl,tx-frame-sync-delay-bits\n",
tdm_np);
- of_node_put(tdm_np);
return ret;
}
if (val > 3) {
dev_err(tsa->dev,
"%pOF: Invalid fsl,tx-frame-sync-delay-bits (%u)\n",
tdm_np, val);
- of_node_put(tdm_np);
return -EINVAL;
}
tdm->simode_tdm |= TSA_SIMODE_TDM_TFSD(val);
@@ -532,85 +774,88 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
if (of_property_read_bool(tdm_np, "fsl,fsync-rising-edge"))
tdm->simode_tdm |= TSA_SIMODE_TDM_FE;
+ if (tsa_is_qe(tsa) &&
+ of_property_read_bool(tdm_np, "fsl,fsync-active-low"))
+ tdm->simode_tdm |= TSA_QE_SIMODE_TDM_SL;
+
if (of_property_read_bool(tdm_np, "fsl,double-speed-clock"))
tdm->simode_tdm |= TSA_SIMODE_TDM_DSC;
- clk = of_clk_get_by_name(tdm_np, "l1rsync");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rsync" : "l1rsync");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
- of_node_put(tdm_np);
goto err;
}
ret = clk_prepare_enable(clk);
if (ret) {
clk_put(clk);
- of_node_put(tdm_np);
goto err;
}
tdm->l1rsync_clk = clk;
- clk = of_clk_get_by_name(tdm_np, "l1rclk");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rclk" : "l1rclk");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
- of_node_put(tdm_np);
goto err;
}
ret = clk_prepare_enable(clk);
if (ret) {
clk_put(clk);
- of_node_put(tdm_np);
goto err;
}
tdm->l1rclk_clk = clk;
if (!(tdm->simode_tdm & TSA_SIMODE_TDM_CRT)) {
- clk = of_clk_get_by_name(tdm_np, "l1tsync");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tsync" : "l1tsync");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
- of_node_put(tdm_np);
goto err;
}
ret = clk_prepare_enable(clk);
if (ret) {
clk_put(clk);
- of_node_put(tdm_np);
goto err;
}
tdm->l1tsync_clk = clk;
- clk = of_clk_get_by_name(tdm_np, "l1tclk");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tclk" : "l1tclk");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
- of_node_put(tdm_np);
goto err;
}
ret = clk_prepare_enable(clk);
if (ret) {
clk_put(clk);
- of_node_put(tdm_np);
goto err;
}
tdm->l1tclk_clk = clk;
}
+ if (tsa_is_qe(tsa)) {
+ /*
+ * The starting address for TSA table must be set.
+ * 512 entries for Tx and 512 entries for Rx are
+ * available for 4 TDMs.
+ * We assign entries equally -> 128 Rx/Tx entries per
+ * TDM. In other words, 4 blocks of 32 entries per TDM.
+ */
+ tdm->simode_tdm |= TSA_QE_SIMODE_TDM_SAD(4 * tdm_id);
+ }
+
ret = tsa_of_parse_tdm_rx_route(tsa, tdm_np, tsa->tdms, tdm_id);
- if (ret) {
- of_node_put(tdm_np);
+ if (ret)
goto err;
- }
ret = tsa_of_parse_tdm_tx_route(tsa, tdm_np, tsa->tdms, tdm_id);
- if (ret) {
- of_node_put(tdm_np);
+ if (ret)
goto err;
- }
tdm->is_enable = true;
}
return 0;
err:
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) {
if (tsa->tdm[i].l1rsync_clk) {
clk_disable_unprepare(tsa->tdm[i].l1rsync_clk);
clk_put(tsa->tdm[i].l1rsync_clk);
@@ -636,8 +881,87 @@ static void tsa_init_si_ram(struct tsa *tsa)
resource_size_t i;
/* Fill all entries as the last one */
- for (i = 0; i < tsa->si_ram_sz; i += 4)
- tsa_write32(tsa->si_ram + i, TSA_SIRAM_ENTRY_LAST);
+ if (tsa_is_qe(tsa)) {
+ for (i = 0; i < tsa->si_ram_sz; i += 2)
+ tsa_write16(tsa->si_ram + i, TSA_QE_SIRAM_ENTRY_LAST);
+ } else {
+ for (i = 0; i < tsa->si_ram_sz; i += 4)
+ tsa_write32(tsa->si_ram + i, TSA_CPM1_SIRAM_ENTRY_LAST);
+ }
+}
+
+static int tsa_cpm1_setup(struct tsa *tsa)
+{
+ u32 val;
+
+ /* Set SIMODE */
+ val = 0;
+ if (tsa->tdm[0].is_enable)
+ val |= TSA_CPM1_SIMODE_TDMA(tsa->tdm[0].simode_tdm);
+ if (tsa->tdm[1].is_enable)
+ val |= TSA_CPM1_SIMODE_TDMB(tsa->tdm[1].simode_tdm);
+
+ tsa_clrsetbits32(tsa->si_regs + TSA_CPM1_SIMODE,
+ TSA_CPM1_SIMODE_TDMA(TSA_CPM1_SIMODE_TDM_MASK) |
+ TSA_CPM1_SIMODE_TDMB(TSA_CPM1_SIMODE_TDM_MASK),
+ val);
+
+ /* Set SIGMR */
+ val = (tsa->tdms == BIT(TSA_TDMA)) ?
+ TSA_CPM1_SIGMR_RDM_STATIC_TDMA : TSA_CPM1_SIGMR_RDM_STATIC_TDMAB;
+ if (tsa->tdms & BIT(TSA_TDMA))
+ val |= TSA_CPM1_SIGMR_ENA;
+ if (tsa->tdms & BIT(TSA_TDMB))
+ val |= TSA_CPM1_SIGMR_ENB;
+ tsa_write8(tsa->si_regs + TSA_CPM1_SIGMR, val);
+
+ return 0;
+}
+
+static int tsa_qe_setup(struct tsa *tsa)
+{
+ unsigned int sixmr;
+ u8 siglmrh = 0;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) {
+ if (!tsa->tdm[i].is_enable)
+ continue;
+
+ switch (i) {
+ case 0:
+ sixmr = TSA_QE_SIAMR;
+ siglmrh |= TSA_QE_SIGLMRH_ENA;
+ break;
+ case 1:
+ sixmr = TSA_QE_SIBMR;
+ siglmrh |= TSA_QE_SIGLMRH_ENB;
+ break;
+ case 2:
+ sixmr = TSA_QE_SICMR;
+ siglmrh |= TSA_QE_SIGLMRH_ENC;
+ break;
+ case 3:
+ sixmr = TSA_QE_SIDMR;
+ siglmrh |= TSA_QE_SIGLMRH_END;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Set SI mode register */
+ tsa_write16(tsa->si_regs + sixmr, tsa->tdm[i].simode_tdm);
+ }
+
+ /* Enable TDMs */
+ tsa_write8(tsa->si_regs + TSA_QE_SIGLMRH, siglmrh);
+
+ return 0;
+}
+
+static int tsa_setup(struct tsa *tsa)
+{
+ return tsa_is_qe(tsa) ? tsa_qe_setup(tsa) : tsa_cpm1_setup(tsa);
}
static int tsa_probe(struct platform_device *pdev)
@@ -646,7 +970,6 @@ static int tsa_probe(struct platform_device *pdev)
struct resource *res;
struct tsa *tsa;
unsigned int i;
- u32 val;
int ret;
tsa = devm_kzalloc(&pdev->dev, sizeof(*tsa), GFP_KERNEL);
@@ -654,6 +977,18 @@ static int tsa_probe(struct platform_device *pdev)
return -ENOMEM;
tsa->dev = &pdev->dev;
+ tsa->version = (enum tsa_version)(uintptr_t)of_device_get_match_data(&pdev->dev);
+ switch (tsa->version) {
+ case TSA_CPM1:
+ dev_info(tsa->dev, "CPM1 version\n");
+ break;
+ case TSA_QE:
+ dev_info(tsa->dev, "QE version\n");
+ break;
+ default:
+ dev_err(tsa->dev, "Unknown version (%d)\n", tsa->version);
+ return -EINVAL;
+ }
for (i = 0; i < ARRAY_SIZE(tsa->serials); i++)
tsa->serials[i].id = i;
@@ -680,26 +1015,9 @@ static int tsa_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* Set SIMODE */
- val = 0;
- if (tsa->tdm[0].is_enable)
- val |= TSA_SIMODE_TDMA(tsa->tdm[0].simode_tdm);
- if (tsa->tdm[1].is_enable)
- val |= TSA_SIMODE_TDMB(tsa->tdm[1].simode_tdm);
-
- tsa_clrsetbits32(tsa->si_regs + TSA_SIMODE,
- TSA_SIMODE_TDMA(TSA_SIMODE_TDM_MASK) |
- TSA_SIMODE_TDMB(TSA_SIMODE_TDM_MASK),
- val);
-
- /* Set SIGMR */
- val = (tsa->tdms == BIT(TSA_TDMA)) ?
- TSA_SIGMR_RDM_STATIC_TDMA : TSA_SIGMR_RDM_STATIC_TDMAB;
- if (tsa->tdms & BIT(TSA_TDMA))
- val |= TSA_SIGMR_ENA;
- if (tsa->tdms & BIT(TSA_TDMB))
- val |= TSA_SIGMR_ENB;
- tsa_write8(tsa->si_regs + TSA_SIGMR, val);
+ ret = tsa_setup(tsa);
+ if (ret)
+ return ret;
platform_set_drvdata(pdev, tsa);
@@ -711,7 +1029,7 @@ static void tsa_remove(struct platform_device *pdev)
struct tsa *tsa = platform_get_drvdata(pdev);
int i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) {
if (tsa->tdm[i].l1rsync_clk) {
clk_disable_unprepare(tsa->tdm[i].l1rsync_clk);
clk_put(tsa->tdm[i].l1rsync_clk);
@@ -732,7 +1050,12 @@ static void tsa_remove(struct platform_device *pdev)
}
static const struct of_device_id tsa_id_table[] = {
- { .compatible = "fsl,cpm1-tsa" },
+#if IS_ENABLED(CONFIG_CPM1)
+ { .compatible = "fsl,cpm1-tsa", .data = (void *)TSA_CPM1 },
+#endif
+#if IS_ENABLED(CONFIG_QUICC_ENGINE)
+ { .compatible = "fsl,qe-tsa", .data = (void *)TSA_QE },
+#endif
{} /* sentinel */
};
MODULE_DEVICE_TABLE(of, tsa_id_table);
@@ -743,7 +1066,7 @@ static struct platform_driver tsa_driver = {
.of_match_table = of_match_ptr(tsa_id_table),
},
.probe = tsa_probe,
- .remove_new = tsa_remove,
+ .remove = tsa_remove,
};
module_platform_driver(tsa_driver);
@@ -841,5 +1164,5 @@ struct tsa_serial *devm_tsa_serial_get_byphandle(struct device *dev,
EXPORT_SYMBOL(devm_tsa_serial_get_byphandle);
MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
-MODULE_DESCRIPTION("CPM TSA driver");
+MODULE_DESCRIPTION("CPM/QE TSA driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/soc/fsl/qe/tsa.h b/drivers/soc/fsl/qe/tsa.h
index d9df89b6da3e..da137bc0f49b 100644
--- a/drivers/soc/fsl/qe/tsa.h
+++ b/drivers/soc/fsl/qe/tsa.h
@@ -39,4 +39,7 @@ struct tsa_serial_info {
/* Get information */
int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info);
+/* Get serial number */
+int tsa_serial_get_num(struct tsa_serial *tsa_serial);
+
#endif /* __SOC_FSL_TSA_H__ */
diff --git a/drivers/soc/fsl/qe/ucc.c b/drivers/soc/fsl/qe/ucc.c
index 21dbcd787cd5..892aa5931d5b 100644
--- a/drivers/soc/fsl/qe/ucc.c
+++ b/drivers/soc/fsl/qe/ucc.c
@@ -114,6 +114,7 @@ int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
return 0;
}
+EXPORT_SYMBOL(ucc_mux_set_grant_tsa_bkpt);
int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
enum comm_dir mode)
diff --git a/drivers/soc/fsl/rcpm.c b/drivers/soc/fsl/rcpm.c
index 3d0cae30c769..06bd94b29fb3 100644
--- a/drivers/soc/fsl/rcpm.c
+++ b/drivers/soc/fsl/rcpm.c
@@ -36,6 +36,7 @@ static void copy_ippdexpcr1_setting(u32 val)
return;
regs = of_iomap(np, 0);
+ of_node_put(np);
if (!regs)
return;
diff --git a/drivers/soc/fujitsu/a64fx-diag.c b/drivers/soc/fujitsu/a64fx-diag.c
index 330901893577..76cb0b6a221c 100644
--- a/drivers/soc/fujitsu/a64fx-diag.c
+++ b/drivers/soc/fujitsu/a64fx-diag.c
@@ -142,7 +142,7 @@ static struct platform_driver a64fx_diag_driver = {
.acpi_match_table = ACPI_PTR(a64fx_diag_acpi_match),
},
.probe = a64fx_diag_probe,
- .remove_new = a64fx_diag_remove,
+ .remove = a64fx_diag_remove,
};
module_platform_driver(a64fx_diag_driver);
diff --git a/drivers/soc/hisilicon/Kconfig b/drivers/soc/hisilicon/Kconfig
index 0ab688af308f..6d7c244d2e78 100644
--- a/drivers/soc/hisilicon/Kconfig
+++ b/drivers/soc/hisilicon/Kconfig
@@ -6,16 +6,19 @@ menu "Hisilicon SoC drivers"
config KUNPENG_HCCS
tristate "HCCS driver on Kunpeng SoC"
depends on ACPI
- depends on MAILBOX
+ depends on PCC
depends on ARM64 || COMPILE_TEST
help
The Huawei Cache Coherence System (HCCS) is a multi-chip
interconnection bus protocol.
The performance of application may be affected if some HCCS
ports are not in full lane status, have a large number of CRC
- errors and so on.
+ errors and so on. This may support for reducing system power
+ consumption if there are HCCS ports supported low power feature
+ on platform.
Say M here if you want to include support for querying the
- health status and port information of HCCS on Kunpeng SoC.
+ health status and port information of HCCS, or reducing system
+ power consumption on Kunpeng SoC.
endmenu
diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 9ff70b38e5e9..7fc353732d55 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -21,11 +21,22 @@
* - if all enabled ports are in linked
* - if all linked ports are in full lane
* - CRC error count sum
+ *
+ * - Retrieve all HCCS types used on the platform.
+ *
+ * - Support low power feature for all specified HCCS type ports, and
+ * provide the following interface:
+ * - query HCCS types supported increasing and decreasing lane number.
+ * - decrease lane number of all specified HCCS type ports on idle state.
+ * - increase lane number of all specified HCCS type ports.
*/
#include <linux/acpi.h>
+#include <linux/delay.h>
#include <linux/iopoll.h>
#include <linux/platform_device.h>
+#include <linux/stringify.h>
#include <linux/sysfs.h>
+#include <linux/types.h>
#include <acpi/pcc.h>
@@ -53,6 +64,42 @@ static struct hccs_chip_info *kobj_to_chip_info(struct kobject *k)
return container_of(k, struct hccs_chip_info, kobj);
}
+static struct hccs_dev *device_kobj_to_hccs_dev(struct kobject *k)
+{
+ struct device *dev = container_of(k, struct device, kobj);
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+
+ return platform_get_drvdata(pdev);
+}
+
+static char *hccs_port_type_to_name(struct hccs_dev *hdev, u8 type)
+{
+ u16 i;
+
+ for (i = 0; i < hdev->used_type_num; i++) {
+ if (hdev->type_name_maps[i].type == type)
+ return hdev->type_name_maps[i].name;
+ }
+
+ return NULL;
+}
+
+static int hccs_name_to_port_type(struct hccs_dev *hdev,
+ const char *name, u8 *type)
+{
+ u16 i;
+
+ for (i = 0; i < hdev->used_type_num; i++) {
+ if (strcmp(hdev->type_name_maps[i].name, name) == 0) {
+ *type = hdev->type_name_maps[i].type;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
struct hccs_register_ctx {
struct device *dev;
u8 chan_id;
@@ -120,10 +167,6 @@ static void hccs_pcc_rx_callback(struct mbox_client *cl, void *mssg)
static void hccs_unregister_pcc_channel(struct hccs_dev *hdev)
{
- struct hccs_mbox_client_info *cl_info = &hdev->cl_info;
-
- if (cl_info->pcc_comm_addr)
- iounmap(cl_info->pcc_comm_addr);
pcc_mbox_free_channel(hdev->cl_info.pcc_chan);
}
@@ -132,6 +175,7 @@ static int hccs_register_pcc_channel(struct hccs_dev *hdev)
struct hccs_mbox_client_info *cl_info = &hdev->cl_info;
struct mbox_client *cl = &cl_info->client;
struct pcc_mbox_chan *pcc_chan;
+ struct mbox_chan *mbox_chan;
struct device *dev = hdev->dev;
int rc;
@@ -144,12 +188,12 @@ static int hccs_register_pcc_channel(struct hccs_dev *hdev)
pcc_chan = pcc_mbox_request_channel(cl, hdev->chan_id);
if (IS_ERR(pcc_chan)) {
- dev_err(dev, "PPC channel request failed.\n");
+ dev_err(dev, "PCC channel request failed.\n");
rc = -ENODEV;
goto out;
}
cl_info->pcc_chan = pcc_chan;
- cl_info->mbox_chan = pcc_chan->mchan;
+ mbox_chan = pcc_chan->mchan;
/*
* pcc_chan->latency is just a nominal value. In reality the remote
@@ -159,26 +203,22 @@ static int hccs_register_pcc_channel(struct hccs_dev *hdev)
cl_info->deadline_us =
HCCS_PCC_CMD_WAIT_RETRIES_NUM * pcc_chan->latency;
if (!hdev->verspec_data->has_txdone_irq &&
- cl_info->mbox_chan->mbox->txdone_irq) {
+ mbox_chan->mbox->txdone_irq) {
dev_err(dev, "PCC IRQ in PCCT is enabled.\n");
rc = -EINVAL;
goto err_mbx_channel_free;
} else if (hdev->verspec_data->has_txdone_irq &&
- !cl_info->mbox_chan->mbox->txdone_irq) {
+ !mbox_chan->mbox->txdone_irq) {
dev_err(dev, "PCC IRQ in PCCT isn't supported.\n");
rc = -EINVAL;
goto err_mbx_channel_free;
}
- if (pcc_chan->shmem_base_addr) {
- cl_info->pcc_comm_addr = ioremap(pcc_chan->shmem_base_addr,
- pcc_chan->shmem_size);
- if (!cl_info->pcc_comm_addr) {
- dev_err(dev, "Failed to ioremap PCC communication region for channel-%u.\n",
- hdev->chan_id);
- rc = -ENOMEM;
- goto err_mbx_channel_free;
- }
+ if (pcc_chan->shmem_size != HCCS_PCC_SHARE_MEM_BYTES) {
+ dev_err(dev, "Base size (%llu) of PCC communication region must be %d bytes.\n",
+ pcc_chan->shmem_size, HCCS_PCC_SHARE_MEM_BYTES);
+ rc = -EINVAL;
+ goto err_mbx_channel_free;
}
return 0;
@@ -193,7 +233,7 @@ static int hccs_wait_cmd_complete_by_poll(struct hccs_dev *hdev)
{
struct hccs_mbox_client_info *cl_info = &hdev->cl_info;
struct acpi_pcct_shared_memory __iomem *comm_base =
- cl_info->pcc_comm_addr;
+ cl_info->pcc_chan->shmem;
u16 status;
int ret;
@@ -236,7 +276,7 @@ static inline void hccs_fill_pcc_shared_mem_region(struct hccs_dev *hdev,
.status = 0,
};
- memcpy_toio(hdev->cl_info.pcc_comm_addr, (void *)&tmp,
+ memcpy_toio(hdev->cl_info.pcc_chan->shmem, (void *)&tmp,
sizeof(struct acpi_pcct_shared_memory));
/* Copy the message to the PCC comm space */
@@ -256,7 +296,7 @@ static inline void hccs_fill_ext_pcc_shared_mem_region(struct hccs_dev *hdev,
.command = cmd,
};
- memcpy_toio(hdev->cl_info.pcc_comm_addr, (void *)&tmp,
+ memcpy_toio(hdev->cl_info.pcc_chan->shmem, (void *)&tmp,
sizeof(struct acpi_pcct_ext_pcc_shared_memory));
/* Copy the message to the PCC comm space */
@@ -268,12 +308,13 @@ static int hccs_pcc_cmd_send(struct hccs_dev *hdev, u8 cmd,
{
const struct hccs_verspecific_data *verspec_data = hdev->verspec_data;
struct hccs_mbox_client_info *cl_info = &hdev->cl_info;
+ struct mbox_chan *mbox_chan = cl_info->pcc_chan->mchan;
struct hccs_fw_inner_head *fw_inner_head;
void __iomem *comm_space;
u16 space_size;
int ret;
- comm_space = cl_info->pcc_comm_addr + verspec_data->shared_mem_size;
+ comm_space = cl_info->pcc_chan->shmem + verspec_data->shared_mem_size;
space_size = HCCS_PCC_SHARE_MEM_BYTES - verspec_data->shared_mem_size;
verspec_data->fill_pcc_shared_mem(hdev, cmd, desc,
comm_space, space_size);
@@ -281,7 +322,7 @@ static int hccs_pcc_cmd_send(struct hccs_dev *hdev, u8 cmd,
reinit_completion(&cl_info->done);
/* Ring doorbell */
- ret = mbox_send_message(cl_info->mbox_chan, &cmd);
+ ret = mbox_send_message(mbox_chan, &cmd);
if (ret < 0) {
dev_err(hdev->dev, "Send PCC mbox message failed, ret = %d.\n",
ret);
@@ -303,9 +344,9 @@ static int hccs_pcc_cmd_send(struct hccs_dev *hdev, u8 cmd,
end:
if (verspec_data->has_txdone_irq)
- mbox_chan_txdone(cl_info->mbox_chan, ret);
+ mbox_chan_txdone(mbox_chan, ret);
else
- mbox_client_txdone(cl_info->mbox_chan, ret);
+ mbox_client_txdone(mbox_chan, ret);
return ret;
}
@@ -451,6 +492,7 @@ static int hccs_query_all_die_info_on_platform(struct hccs_dev *hdev)
struct device *dev = hdev->dev;
struct hccs_chip_info *chip;
struct hccs_die_info *die;
+ bool has_die_info = false;
u8 i, j;
int ret;
@@ -459,6 +501,7 @@ static int hccs_query_all_die_info_on_platform(struct hccs_dev *hdev)
if (!chip->die_num)
continue;
+ has_die_info = true;
chip->dies = devm_kzalloc(hdev->dev,
chip->die_num * sizeof(struct hccs_die_info),
GFP_KERNEL);
@@ -480,7 +523,7 @@ static int hccs_query_all_die_info_on_platform(struct hccs_dev *hdev)
}
}
- return 0;
+ return has_die_info ? 0 : -EINVAL;
}
static int hccs_get_bd_info(struct hccs_dev *hdev, u8 opcode,
@@ -556,6 +599,12 @@ static int hccs_get_all_port_attr(struct hccs_dev *hdev,
start_id = rsp_head.next_id;
}
+ if (left_buf_len != 0) {
+ dev_err(hdev->dev, "failed to get the expected port number(%u) attribute.\n",
+ size);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -580,7 +629,7 @@ static int hccs_get_all_port_info_on_die(struct hccs_dev *hdev,
port = &die->ports[i];
port->port_id = attrs[i].port_id;
port->port_type = attrs[i].port_type;
- port->lane_mode = attrs[i].lane_mode;
+ port->max_lane_num = attrs[i].max_lane_num;
port->enable = attrs[i].enable;
port->die = die;
}
@@ -595,6 +644,7 @@ static int hccs_query_all_port_info_on_platform(struct hccs_dev *hdev)
struct device *dev = hdev->dev;
struct hccs_chip_info *chip;
struct hccs_die_info *die;
+ bool has_port_info = false;
u8 i, j;
int ret;
@@ -605,6 +655,7 @@ static int hccs_query_all_port_info_on_platform(struct hccs_dev *hdev)
if (!die->port_num)
continue;
+ has_port_info = true;
die->ports = devm_kzalloc(dev,
die->port_num * sizeof(struct hccs_port_info),
GFP_KERNEL);
@@ -623,7 +674,7 @@ static int hccs_query_all_port_info_on_platform(struct hccs_dev *hdev)
}
}
- return 0;
+ return has_port_info ? 0 : -EINVAL;
}
static int hccs_get_hw_info(struct hccs_dev *hdev)
@@ -654,6 +705,55 @@ static int hccs_get_hw_info(struct hccs_dev *hdev)
return 0;
}
+static u16 hccs_calc_used_type_num(struct hccs_dev *hdev,
+ unsigned long *hccs_ver)
+{
+ struct hccs_chip_info *chip;
+ struct hccs_port_info *port;
+ struct hccs_die_info *die;
+ u16 used_type_num = 0;
+ u16 i, j, k;
+
+ for (i = 0; i < hdev->chip_num; i++) {
+ chip = &hdev->chips[i];
+ for (j = 0; j < chip->die_num; j++) {
+ die = &chip->dies[j];
+ for (k = 0; k < die->port_num; k++) {
+ port = &die->ports[k];
+ set_bit(port->port_type, hccs_ver);
+ }
+ }
+ }
+
+ for_each_set_bit(i, hccs_ver, HCCS_IP_MAX + 1)
+ used_type_num++;
+
+ return used_type_num;
+}
+
+static int hccs_init_type_name_maps(struct hccs_dev *hdev)
+{
+ DECLARE_BITMAP(hccs_ver, HCCS_IP_MAX + 1) = {};
+ unsigned int i;
+ u16 idx = 0;
+
+ hdev->used_type_num = hccs_calc_used_type_num(hdev, hccs_ver);
+ hdev->type_name_maps = devm_kcalloc(hdev->dev, hdev->used_type_num,
+ sizeof(struct hccs_type_name_map),
+ GFP_KERNEL);
+ if (!hdev->type_name_maps)
+ return -ENOMEM;
+
+ for_each_set_bit(i, hccs_ver, HCCS_IP_MAX + 1) {
+ hdev->type_name_maps[idx].type = i;
+ sprintf(hdev->type_name_maps[idx].name,
+ "%s%u", HCCS_IP_PREFIX, i);
+ idx++;
+ }
+
+ return 0;
+}
+
static int hccs_query_port_link_status(struct hccs_dev *hdev,
const struct hccs_port_info *port,
struct hccs_link_status *link_status)
@@ -814,7 +914,7 @@ static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
{
const struct hccs_port_info *port = kobj_to_port_info(kobj);
- return sysfs_emit(buf, "HCCS-v%u\n", port->port_type);
+ return sysfs_emit(buf, "%s%u\n", HCCS_IP_PREFIX, port->port_type);
}
static struct kobj_attribute hccs_type_attr = __ATTR_RO(type);
@@ -823,7 +923,7 @@ static ssize_t lane_mode_show(struct kobject *kobj, struct kobj_attribute *attr,
{
const struct hccs_port_info *port = kobj_to_port_info(kobj);
- return sysfs_emit(buf, "x%u\n", port->lane_mode);
+ return sysfs_emit(buf, "x%u\n", port->max_lane_num);
}
static struct kobj_attribute lane_mode_attr = __ATTR_RO(lane_mode);
@@ -1118,6 +1218,372 @@ static const struct kobj_type hccs_chip_type = {
.default_groups = hccs_chip_default_groups,
};
+static int hccs_parse_pm_port_type(struct hccs_dev *hdev, const char *buf,
+ u8 *port_type)
+{
+ char hccs_name[HCCS_NAME_MAX_LEN + 1] = "";
+ u8 type;
+ int ret;
+
+ ret = sscanf(buf, "%" __stringify(HCCS_NAME_MAX_LEN) "s", hccs_name);
+ if (ret != 1)
+ return -EINVAL;
+
+ ret = hccs_name_to_port_type(hdev, hccs_name, &type);
+ if (ret) {
+ dev_dbg(hdev->dev, "input invalid, please get the available types from 'used_types'.\n");
+ return ret;
+ }
+
+ if (type == HCCS_V2 && hdev->caps & HCCS_CAPS_HCCS_V2_PM) {
+ *port_type = type;
+ return 0;
+ }
+
+ dev_dbg(hdev->dev, "%s doesn't support for increasing and decreasing lane.\n",
+ hccs_name);
+
+ return -EOPNOTSUPP;
+}
+
+static int hccs_query_port_idle_status(struct hccs_dev *hdev,
+ struct hccs_port_info *port, u8 *idle)
+{
+ const struct hccs_die_info *die = port->die;
+ const struct hccs_chip_info *chip = die->chip;
+ struct hccs_port_comm_req_param *req_param;
+ struct hccs_desc desc;
+ int ret;
+
+ hccs_init_req_desc(&desc);
+ req_param = (struct hccs_port_comm_req_param *)desc.req.data;
+ req_param->chip_id = chip->chip_id;
+ req_param->die_id = die->die_id;
+ req_param->port_id = port->port_id;
+ ret = hccs_pcc_cmd_send(hdev, HCCS_GET_PORT_IDLE_STATUS, &desc);
+ if (ret) {
+ dev_err(hdev->dev,
+ "get port idle status failed, ret = %d.\n", ret);
+ return ret;
+ }
+
+ *idle = *((u8 *)desc.rsp.data);
+ return 0;
+}
+
+static int hccs_get_all_spec_port_idle_sta(struct hccs_dev *hdev, u8 port_type,
+ bool *all_idle)
+{
+ struct hccs_chip_info *chip;
+ struct hccs_port_info *port;
+ struct hccs_die_info *die;
+ int ret = 0;
+ u8 i, j, k;
+ u8 idle;
+
+ *all_idle = false;
+ for (i = 0; i < hdev->chip_num; i++) {
+ chip = &hdev->chips[i];
+ for (j = 0; j < chip->die_num; j++) {
+ die = &chip->dies[j];
+ for (k = 0; k < die->port_num; k++) {
+ port = &die->ports[k];
+ if (port->port_type != port_type)
+ continue;
+ ret = hccs_query_port_idle_status(hdev, port,
+ &idle);
+ if (ret) {
+ dev_err(hdev->dev,
+ "hccs%u on chip%u/die%u get idle status failed, ret = %d.\n",
+ k, i, j, ret);
+ return ret;
+ } else if (idle == 0) {
+ dev_info(hdev->dev, "hccs%u on chip%u/die%u is busy.\n",
+ k, i, j);
+ return 0;
+ }
+ }
+ }
+ }
+ *all_idle = true;
+
+ return 0;
+}
+
+static int hccs_get_all_spec_port_full_lane_sta(struct hccs_dev *hdev,
+ u8 port_type, bool *full_lane)
+{
+ struct hccs_link_status status = {0};
+ struct hccs_chip_info *chip;
+ struct hccs_port_info *port;
+ struct hccs_die_info *die;
+ u8 i, j, k;
+ int ret;
+
+ *full_lane = false;
+ for (i = 0; i < hdev->chip_num; i++) {
+ chip = &hdev->chips[i];
+ for (j = 0; j < chip->die_num; j++) {
+ die = &chip->dies[j];
+ for (k = 0; k < die->port_num; k++) {
+ port = &die->ports[k];
+ if (port->port_type != port_type)
+ continue;
+ ret = hccs_query_port_link_status(hdev, port,
+ &status);
+ if (ret)
+ return ret;
+ if (status.lane_num != port->max_lane_num)
+ return 0;
+ }
+ }
+ }
+ *full_lane = true;
+
+ return 0;
+}
+
+static int hccs_prepare_inc_lane(struct hccs_dev *hdev, u8 type)
+{
+ struct hccs_inc_lane_req_param *req_param;
+ struct hccs_desc desc;
+ int ret;
+
+ hccs_init_req_desc(&desc);
+ req_param = (struct hccs_inc_lane_req_param *)desc.req.data;
+ req_param->port_type = type;
+ req_param->opt_type = HCCS_PREPARE_INC_LANE;
+ ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc);
+ if (ret)
+ dev_err(hdev->dev, "prepare for increasing lane failed, ret = %d.\n",
+ ret);
+
+ return ret;
+}
+
+static int hccs_wait_serdes_adapt_completed(struct hccs_dev *hdev, u8 type)
+{
+#define HCCS_MAX_WAIT_CNT_FOR_ADAPT 10
+#define HCCS_QUERY_ADAPT_RES_DELAY_MS 100
+#define HCCS_SERDES_ADAPT_OK 0
+
+ struct hccs_inc_lane_req_param *req_param;
+ u8 wait_cnt = HCCS_MAX_WAIT_CNT_FOR_ADAPT;
+ struct hccs_desc desc;
+ u8 adapt_res;
+ int ret;
+
+ do {
+ hccs_init_req_desc(&desc);
+ req_param = (struct hccs_inc_lane_req_param *)desc.req.data;
+ req_param->port_type = type;
+ req_param->opt_type = HCCS_GET_ADAPT_RES;
+ ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc);
+ if (ret) {
+ dev_err(hdev->dev, "query adapting result failed, ret = %d.\n",
+ ret);
+ return ret;
+ }
+ adapt_res = *((u8 *)&desc.rsp.data);
+ if (adapt_res == HCCS_SERDES_ADAPT_OK)
+ return 0;
+
+ msleep(HCCS_QUERY_ADAPT_RES_DELAY_MS);
+ } while (--wait_cnt);
+
+ dev_err(hdev->dev, "wait for adapting completed timeout.\n");
+
+ return -ETIMEDOUT;
+}
+
+static int hccs_start_hpcs_retraining(struct hccs_dev *hdev, u8 type)
+{
+ struct hccs_inc_lane_req_param *req_param;
+ struct hccs_desc desc;
+ int ret;
+
+ hccs_init_req_desc(&desc);
+ req_param = (struct hccs_inc_lane_req_param *)desc.req.data;
+ req_param->port_type = type;
+ req_param->opt_type = HCCS_START_RETRAINING;
+ ret = hccs_pcc_cmd_send(hdev, HCCS_PM_INC_LANE, &desc);
+ if (ret)
+ dev_err(hdev->dev, "start hpcs retraining failed, ret = %d.\n",
+ ret);
+
+ return ret;
+}
+
+static int hccs_start_inc_lane(struct hccs_dev *hdev, u8 type)
+{
+ int ret;
+
+ ret = hccs_prepare_inc_lane(hdev, type);
+ if (ret)
+ return ret;
+
+ ret = hccs_wait_serdes_adapt_completed(hdev, type);
+ if (ret)
+ return ret;
+
+ return hccs_start_hpcs_retraining(hdev, type);
+}
+
+static int hccs_start_dec_lane(struct hccs_dev *hdev, u8 type)
+{
+ struct hccs_desc desc;
+ u8 *port_type;
+ int ret;
+
+ hccs_init_req_desc(&desc);
+ port_type = (u8 *)desc.req.data;
+ *port_type = type;
+ ret = hccs_pcc_cmd_send(hdev, HCCS_PM_DEC_LANE, &desc);
+ if (ret)
+ dev_err(hdev->dev, "start to decrease lane failed, ret = %d.\n",
+ ret);
+
+ return ret;
+}
+
+static ssize_t dec_lane_of_type_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
+ bool all_in_idle;
+ u8 port_type;
+ int ret;
+
+ ret = hccs_parse_pm_port_type(hdev, buf, &port_type);
+ if (ret)
+ return ret;
+
+ mutex_lock(&hdev->lock);
+ ret = hccs_get_all_spec_port_idle_sta(hdev, port_type, &all_in_idle);
+ if (ret)
+ goto out;
+ if (!all_in_idle) {
+ ret = -EBUSY;
+ dev_err(hdev->dev, "please don't decrese lanes on high load with %s, ret = %d.\n",
+ hccs_port_type_to_name(hdev, port_type), ret);
+ goto out;
+ }
+
+ ret = hccs_start_dec_lane(hdev, port_type);
+out:
+ mutex_unlock(&hdev->lock);
+
+ return ret == 0 ? count : ret;
+}
+static struct kobj_attribute dec_lane_of_type_attr =
+ __ATTR(dec_lane_of_type, 0200, NULL, dec_lane_of_type_store);
+
+static ssize_t inc_lane_of_type_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
+ bool full_lane;
+ u8 port_type;
+ int ret;
+
+ ret = hccs_parse_pm_port_type(hdev, buf, &port_type);
+ if (ret)
+ return ret;
+
+ mutex_lock(&hdev->lock);
+ ret = hccs_get_all_spec_port_full_lane_sta(hdev, port_type, &full_lane);
+ if (ret || full_lane)
+ goto out;
+
+ ret = hccs_start_inc_lane(hdev, port_type);
+out:
+ mutex_unlock(&hdev->lock);
+ return ret == 0 ? count : ret;
+}
+static struct kobj_attribute inc_lane_of_type_attr =
+ __ATTR(inc_lane_of_type, 0200, NULL, inc_lane_of_type_store);
+
+static ssize_t available_inc_dec_lane_types_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
+
+ if (hdev->caps & HCCS_CAPS_HCCS_V2_PM)
+ return sysfs_emit(buf, "%s\n",
+ hccs_port_type_to_name(hdev, HCCS_V2));
+
+ return -EINVAL;
+}
+static struct kobj_attribute available_inc_dec_lane_types_attr =
+ __ATTR(available_inc_dec_lane_types, 0444,
+ available_inc_dec_lane_types_show, NULL);
+
+static ssize_t used_types_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ struct hccs_dev *hdev = device_kobj_to_hccs_dev(kobj);
+ int len = 0;
+ u16 i;
+
+ for (i = 0; i < hdev->used_type_num - 1; i++)
+ len += sysfs_emit_at(buf, len, "%s ", hdev->type_name_maps[i].name);
+ len += sysfs_emit_at(buf, len, "%s\n", hdev->type_name_maps[i].name);
+
+ return len;
+}
+static struct kobj_attribute used_types_attr =
+ __ATTR(used_types, 0444, used_types_show, NULL);
+
+static void hccs_remove_misc_sysfs(struct hccs_dev *hdev)
+{
+ sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr);
+
+ if (!(hdev->caps & HCCS_CAPS_HCCS_V2_PM))
+ return;
+
+ sysfs_remove_file(&hdev->dev->kobj,
+ &available_inc_dec_lane_types_attr.attr);
+ sysfs_remove_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr);
+ sysfs_remove_file(&hdev->dev->kobj, &inc_lane_of_type_attr.attr);
+}
+
+static int hccs_add_misc_sysfs(struct hccs_dev *hdev)
+{
+ int ret;
+
+ ret = sysfs_create_file(&hdev->dev->kobj, &used_types_attr.attr);
+ if (ret)
+ return ret;
+
+ if (!(hdev->caps & HCCS_CAPS_HCCS_V2_PM))
+ return 0;
+
+ ret = sysfs_create_file(&hdev->dev->kobj,
+ &available_inc_dec_lane_types_attr.attr);
+ if (ret)
+ goto used_types_remove;
+
+ ret = sysfs_create_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr);
+ if (ret)
+ goto inc_dec_lane_types_remove;
+
+ ret = sysfs_create_file(&hdev->dev->kobj, &inc_lane_of_type_attr.attr);
+ if (ret)
+ goto dec_lane_of_type_remove;
+
+ return 0;
+
+dec_lane_of_type_remove:
+ sysfs_remove_file(&hdev->dev->kobj, &dec_lane_of_type_attr.attr);
+inc_dec_lane_types_remove:
+ sysfs_remove_file(&hdev->dev->kobj,
+ &available_inc_dec_lane_types_attr.attr);
+used_types_remove:
+ sysfs_remove_file(&hdev->dev->kobj, &used_types_attr.attr);
+ return ret;
+}
+
static void hccs_remove_die_dir(struct hccs_die_info *die)
{
struct hccs_port_info *port;
@@ -1152,6 +1618,8 @@ static void hccs_remove_topo_dirs(struct hccs_dev *hdev)
for (i = 0; i < hdev->chip_num; i++)
hccs_remove_chip_dir(&hdev->chips[i]);
+
+ hccs_remove_misc_sysfs(hdev);
}
static int hccs_create_hccs_dir(struct hccs_dev *hdev,
@@ -1247,6 +1715,12 @@ static int hccs_create_topo_dirs(struct hccs_dev *hdev)
}
}
+ ret = hccs_add_misc_sysfs(hdev);
+ if (ret) {
+ dev_err(hdev->dev, "create misc sysfs interface failed, ret = %d\n", ret);
+ goto err;
+ }
+
return 0;
err:
for (k = 0; k < id; k++)
@@ -1297,6 +1771,10 @@ static int hccs_probe(struct platform_device *pdev)
if (rc)
goto unregister_pcc_chan;
+ rc = hccs_init_type_name_maps(hdev);
+ if (rc)
+ goto unregister_pcc_chan;
+
rc = hccs_create_topo_dirs(hdev);
if (rc)
goto unregister_pcc_chan;
@@ -1342,7 +1820,7 @@ MODULE_DEVICE_TABLE(acpi, hccs_acpi_match);
static struct platform_driver hccs_driver = {
.probe = hccs_probe,
- .remove_new = hccs_remove,
+ .remove = hccs_remove,
.driver = {
.name = "kunpeng_hccs",
.acpi_match_table = hccs_acpi_match,
diff --git a/drivers/soc/hisilicon/kunpeng_hccs.h b/drivers/soc/hisilicon/kunpeng_hccs.h
index c3adbc01b471..f0a9a5618d97 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.h
+++ b/drivers/soc/hisilicon/kunpeng_hccs.h
@@ -10,6 +10,19 @@
* | P0 | P1 | P2 | P3 | P0 | P1 | P2 | P3 | P0 | P1 | P2 | P3 |P0 | P1 | P2 | P3 |
*/
+enum hccs_port_type {
+ HCCS_V1 = 1,
+ HCCS_V2,
+};
+
+#define HCCS_IP_PREFIX "HCCS-v"
+#define HCCS_IP_MAX 255
+#define HCCS_NAME_MAX_LEN 9
+struct hccs_type_name_map {
+ u8 type;
+ char name[HCCS_NAME_MAX_LEN + 1];
+};
+
/*
* This value cannot be 255, otherwise the loop of the multi-BD communication
* case cannot end.
@@ -19,7 +32,7 @@
struct hccs_port_info {
u8 port_id;
u8 port_type;
- u8 lane_mode;
+ u8 max_lane_num;
bool enable; /* if the port is enabled */
struct kobject kobj;
bool dir_created;
@@ -47,10 +60,8 @@ struct hccs_chip_info {
struct hccs_mbox_client_info {
struct mbox_client client;
- struct mbox_chan *mbox_chan;
struct pcc_mbox_chan *pcc_chan;
u64 deadline_us;
- void __iomem *pcc_comm_addr;
struct completion done;
};
@@ -67,13 +78,18 @@ struct hccs_verspecific_data {
bool has_txdone_irq;
};
+#define HCCS_CAPS_HCCS_V2_PM BIT_ULL(0)
+
struct hccs_dev {
struct device *dev;
struct acpi_device *acpi_dev;
const struct hccs_verspecific_data *verspec_data;
+ /* device capabilities from firmware, like HCCS_CAPS_xxx. */
u64 caps;
u8 chip_num;
struct hccs_chip_info *chips;
+ u16 used_type_num;
+ struct hccs_type_name_map *type_name_maps;
u8 chan_id;
struct mutex lock;
struct hccs_mbox_client_info cl_info;
@@ -91,6 +107,9 @@ enum hccs_subcmd_type {
HCCS_GET_DIE_PORTS_LANE_STA,
HCCS_GET_DIE_PORTS_LINK_STA,
HCCS_GET_DIE_PORTS_CRC_ERR_CNT,
+ HCCS_GET_PORT_IDLE_STATUS,
+ HCCS_PM_DEC_LANE,
+ HCCS_PM_INC_LANE,
HCCS_SUB_CMD_MAX = 255,
};
@@ -113,7 +132,7 @@ struct hccs_die_info_rsp_data {
struct hccs_port_attr {
u8 port_id;
u8 port_type;
- u8 lane_mode;
+ u8 max_lane_num;
u8 enable : 1; /* if the port is enabled */
u16 rsv[2];
};
@@ -134,6 +153,14 @@ struct hccs_port_comm_req_param {
u8 port_id;
};
+#define HCCS_PREPARE_INC_LANE 1
+#define HCCS_GET_ADAPT_RES 2
+#define HCCS_START_RETRAINING 3
+struct hccs_inc_lane_req_param {
+ u8 port_type;
+ u8 opt_type;
+};
+
#define HCCS_PORT_RESET 1
#define HCCS_PORT_SETUP 2
#define HCCS_PORT_CONFIG 3
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
index 3ad321ca608a..ca6a5fa1618f 100644
--- a/drivers/soc/imx/Makefile
+++ b/drivers/soc/imx/Makefile
@@ -3,4 +3,4 @@ ifeq ($(CONFIG_ARM),y)
obj-$(CONFIG_ARCH_MXC) += soc-imx.o
endif
obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
-obj-$(CONFIG_SOC_IMX9) += imx93-src.o
+obj-$(CONFIG_SOC_IMX9) += imx93-src.o soc-imx9.o
diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
index ec87d9d878f3..04a1b60f2f2b 100644
--- a/drivers/soc/imx/soc-imx8m.c
+++ b/drivers/soc/imx/soc-imx8m.c
@@ -24,16 +24,22 @@
#define OCOTP_UID_HIGH 0x420
#define IMX8MP_OCOTP_UID_OFFSET 0x10
+#define IMX8MP_OCOTP_UID_HIGH 0xE00
/* Same as ANADIG_DIGPROG_IMX7D */
#define ANADIG_DIGPROG_IMX8MM 0x800
struct imx8_soc_data {
char *name;
- u32 (*soc_revision)(void);
+ const char *ocotp_compatible;
+ int (*soc_revision)(struct platform_device *pdev, u32 *socrev);
+ int (*soc_uid)(struct platform_device *pdev, u64 *socuid);
};
-static u64 soc_uid;
+struct imx8_soc_drvdata {
+ void __iomem *ocotp_base;
+ struct clk *clk;
+};
#ifdef CONFIG_HAVE_ARM_SMCCC
static u32 imx8mq_soc_revision_from_atf(void)
@@ -51,27 +57,24 @@ static u32 imx8mq_soc_revision_from_atf(void)
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
#endif
-static u32 __init imx8mq_soc_revision(void)
+static int imx8m_soc_uid(struct platform_device *pdev, u64 *socuid)
{
- struct device_node *np;
- void __iomem *ocotp_base;
- u32 magic;
- u32 rev;
- struct clk *clk;
+ struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
+ void __iomem *ocotp_base = drvdata->ocotp_base;
- np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
- if (!np)
- return 0;
+ *socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
+ *socuid <<= 32;
+ *socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
- ocotp_base = of_iomap(np, 0);
- WARN_ON(!ocotp_base);
- clk = of_clk_get_by_name(np, NULL);
- if (IS_ERR(clk)) {
- WARN_ON(IS_ERR(clk));
- return 0;
- }
+ return 0;
+}
- clk_prepare_enable(clk);
+static int imx8mq_soc_revision(struct platform_device *pdev, u32 *socrev)
+{
+ struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
+ void __iomem *ocotp_base = drvdata->ocotp_base;
+ u32 magic;
+ u32 rev;
/*
* SOC revision on older imx8mq is not available in fuses so query
@@ -84,91 +87,109 @@ static u32 __init imx8mq_soc_revision(void)
rev = REV_B1;
}
- soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
- soc_uid <<= 32;
- soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
-
- clk_disable_unprepare(clk);
- clk_put(clk);
- iounmap(ocotp_base);
- of_node_put(np);
+ *socrev = rev;
- return rev;
+ return 0;
}
-static void __init imx8mm_soc_uid(void)
+static int imx8mp_soc_uid(struct platform_device *pdev, u64 *socuid)
{
- void __iomem *ocotp_base;
- struct device_node *np;
- struct clk *clk;
- u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
- IMX8MP_OCOTP_UID_OFFSET : 0;
+ struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
+ void __iomem *ocotp_base = drvdata->ocotp_base;
- np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
- if (!np)
- return;
-
- ocotp_base = of_iomap(np, 0);
- WARN_ON(!ocotp_base);
- clk = of_clk_get_by_name(np, NULL);
- if (IS_ERR(clk)) {
- WARN_ON(IS_ERR(clk));
- return;
- }
-
- clk_prepare_enable(clk);
+ socuid[0] = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + IMX8MP_OCOTP_UID_OFFSET);
+ socuid[0] <<= 32;
+ socuid[0] |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + IMX8MP_OCOTP_UID_OFFSET);
- soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
- soc_uid <<= 32;
- soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
+ socuid[1] = readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH + 0x10);
+ socuid[1] <<= 32;
+ socuid[1] |= readl_relaxed(ocotp_base + IMX8MP_OCOTP_UID_HIGH);
- clk_disable_unprepare(clk);
- clk_put(clk);
- iounmap(ocotp_base);
- of_node_put(np);
+ return 0;
}
-static u32 __init imx8mm_soc_revision(void)
+static int imx8mm_soc_revision(struct platform_device *pdev, u32 *socrev)
{
- struct device_node *np;
+ struct device_node *np __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
void __iomem *anatop_base;
- u32 rev;
- np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
if (!np)
- return 0;
+ return -EINVAL;
anatop_base = of_iomap(np, 0);
- WARN_ON(!anatop_base);
+ if (!anatop_base)
+ return -EINVAL;
- rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
+ *socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
iounmap(anatop_base);
- of_node_put(np);
- imx8mm_soc_uid();
+ return 0;
+}
+
+static int imx8m_soc_prepare(struct platform_device *pdev, const char *ocotp_compatible)
+{
+ struct device_node *np __free(device_node) =
+ of_find_compatible_node(NULL, NULL, ocotp_compatible);
+ struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
+ int ret = 0;
+
+ if (!np)
+ return -EINVAL;
+
+ drvdata->ocotp_base = of_iomap(np, 0);
+ if (!drvdata->ocotp_base)
+ return -EINVAL;
+
+ drvdata->clk = of_clk_get_by_name(np, NULL);
+ if (IS_ERR(drvdata->clk)) {
+ ret = PTR_ERR(drvdata->clk);
+ goto err_clk;
+ }
+
+ return clk_prepare_enable(drvdata->clk);
+
+err_clk:
+ iounmap(drvdata->ocotp_base);
+ return ret;
+}
+
+static void imx8m_soc_unprepare(struct platform_device *pdev)
+{
+ struct imx8_soc_drvdata *drvdata = platform_get_drvdata(pdev);
- return rev;
+ clk_disable_unprepare(drvdata->clk);
+ clk_put(drvdata->clk);
+ iounmap(drvdata->ocotp_base);
}
static const struct imx8_soc_data imx8mq_soc_data = {
.name = "i.MX8MQ",
+ .ocotp_compatible = "fsl,imx8mq-ocotp",
.soc_revision = imx8mq_soc_revision,
+ .soc_uid = imx8m_soc_uid,
};
static const struct imx8_soc_data imx8mm_soc_data = {
.name = "i.MX8MM",
+ .ocotp_compatible = "fsl,imx8mm-ocotp",
.soc_revision = imx8mm_soc_revision,
+ .soc_uid = imx8m_soc_uid,
};
static const struct imx8_soc_data imx8mn_soc_data = {
.name = "i.MX8MN",
+ .ocotp_compatible = "fsl,imx8mm-ocotp",
.soc_revision = imx8mm_soc_revision,
+ .soc_uid = imx8m_soc_uid,
};
static const struct imx8_soc_data imx8mp_soc_data = {
.name = "i.MX8MP",
+ .ocotp_compatible = "fsl,imx8mm-ocotp",
.soc_revision = imx8mm_soc_revision,
+ .soc_uid = imx8mp_soc_uid,
};
static __maybe_unused const struct of_device_id imx8_soc_match[] = {
@@ -179,77 +200,146 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = {
{ }
};
-#define imx8_revision(soc_rev) \
- soc_rev ? \
- kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \
+#define imx8_revision(dev, soc_rev) \
+ (soc_rev) ? \
+ devm_kasprintf((dev), GFP_KERNEL, "%d.%d", ((soc_rev) >> 4) & 0xf, (soc_rev) & 0xf) : \
"unknown"
-static int __init imx8_soc_init(void)
+static void imx8m_unregister_soc(void *data)
+{
+ soc_device_unregister(data);
+}
+
+static void imx8m_unregister_cpufreq(void *data)
+{
+ platform_device_unregister(data);
+}
+
+static int imx8m_soc_probe(struct platform_device *pdev)
{
struct soc_device_attribute *soc_dev_attr;
- struct soc_device *soc_dev;
+ struct platform_device *cpufreq_dev;
+ const struct imx8_soc_data *data;
+ struct imx8_soc_drvdata *drvdata;
+ struct device *dev = &pdev->dev;
const struct of_device_id *id;
+ struct soc_device *soc_dev;
u32 soc_rev = 0;
- const struct imx8_soc_data *data;
+ u64 soc_uid[2] = {0, 0};
int ret;
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, drvdata);
+
soc_dev_attr->family = "Freescale i.MX";
ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
if (ret)
- goto free_soc;
+ return ret;
id = of_match_node(imx8_soc_match, of_root);
- if (!id) {
- ret = -ENODEV;
- goto free_soc;
- }
+ if (!id)
+ return -ENODEV;
data = id->data;
if (data) {
soc_dev_attr->soc_id = data->name;
- if (data->soc_revision)
- soc_rev = data->soc_revision();
+ ret = imx8m_soc_prepare(pdev, data->ocotp_compatible);
+ if (ret)
+ return ret;
+
+ if (data->soc_revision) {
+ ret = data->soc_revision(pdev, &soc_rev);
+ if (ret) {
+ imx8m_soc_unprepare(pdev);
+ return ret;
+ }
+ }
+ if (data->soc_uid) {
+ ret = data->soc_uid(pdev, soc_uid);
+ if (ret) {
+ imx8m_soc_unprepare(pdev);
+ return ret;
+ }
+ }
+ imx8m_soc_unprepare(pdev);
}
- soc_dev_attr->revision = imx8_revision(soc_rev);
- if (!soc_dev_attr->revision) {
- ret = -ENOMEM;
- goto free_soc;
- }
+ soc_dev_attr->revision = imx8_revision(dev, soc_rev);
+ if (!soc_dev_attr->revision)
+ return -ENOMEM;
- soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);
- if (!soc_dev_attr->serial_number) {
- ret = -ENOMEM;
- goto free_rev;
- }
+ if (soc_uid[1])
+ soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX%016llX",
+ soc_uid[1], soc_uid[0]);
+ else
+ soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX",
+ soc_uid[0]);
+ if (!soc_dev_attr->serial_number)
+ return -ENOMEM;
soc_dev = soc_device_register(soc_dev_attr);
- if (IS_ERR(soc_dev)) {
- ret = PTR_ERR(soc_dev);
- goto free_serial_number;
- }
+ if (IS_ERR(soc_dev))
+ return PTR_ERR(soc_dev);
+
+ ret = devm_add_action(dev, imx8m_unregister_soc, soc_dev);
+ if (ret)
+ return ret;
pr_info("SoC: %s revision %s\n", soc_dev_attr->soc_id,
soc_dev_attr->revision);
- if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT))
- platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
+ if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) {
+ cpufreq_dev = platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
+ if (IS_ERR(cpufreq_dev))
+ return dev_err_probe(dev, PTR_ERR(cpufreq_dev),
+ "Failed to register imx-cpufreq-dev device\n");
+ ret = devm_add_action(dev, imx8m_unregister_cpufreq, cpufreq_dev);
+ if (ret)
+ return ret;
+ }
return 0;
+}
-free_serial_number:
- kfree(soc_dev_attr->serial_number);
-free_rev:
- if (strcmp(soc_dev_attr->revision, "unknown"))
- kfree(soc_dev_attr->revision);
-free_soc:
- kfree(soc_dev_attr);
- return ret;
+static struct platform_driver imx8m_soc_driver = {
+ .probe = imx8m_soc_probe,
+ .driver = {
+ .name = "imx8m-soc",
+ },
+};
+
+static int __init imx8_soc_init(void)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ /* No match means this is non-i.MX8M hardware, do nothing. */
+ if (!of_match_node(imx8_soc_match, of_root))
+ return 0;
+
+ ret = platform_driver_register(&imx8m_soc_driver);
+ if (ret) {
+ pr_err("Failed to register imx8m-soc platform driver: %d\n", ret);
+ return ret;
+ }
+
+ pdev = platform_device_register_simple("imx8m-soc", -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ pr_err("Failed to register imx8m-soc platform device: %ld\n", PTR_ERR(pdev));
+ platform_driver_unregister(&imx8m_soc_driver);
+ return PTR_ERR(pdev);
+ }
+
+ return 0;
}
device_initcall(imx8_soc_init);
+MODULE_DESCRIPTION("NXP i.MX8M SoC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/soc/imx/soc-imx9.c b/drivers/soc/imx/soc-imx9.c
new file mode 100644
index 000000000000..b46d22cf0212
--- /dev/null
+++ b/drivers/soc/imx/soc-imx9.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2024 NXP
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#define IMX_SIP_GET_SOC_INFO 0xc2000006
+#define SOC_ID(x) (((x) & 0xFFFF) >> 8)
+#define SOC_REV_MAJOR(x) ((((x) >> 28) & 0xF) - 0x9)
+#define SOC_REV_MINOR(x) (((x) >> 24) & 0xF)
+
+static int imx9_soc_probe(struct platform_device *pdev)
+{
+ struct soc_device_attribute *attr;
+ struct arm_smccc_res res;
+ struct soc_device *sdev;
+ u32 soc_id, rev_major, rev_minor;
+ u64 uid127_64, uid63_0;
+ int err;
+
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr)
+ return -ENOMEM;
+
+ err = of_property_read_string(of_root, "model", &attr->machine);
+ if (err) {
+ pr_err("%s: missing model property: %d\n", __func__, err);
+ goto attr;
+ }
+
+ attr->family = kasprintf(GFP_KERNEL, "Freescale i.MX");
+
+ /*
+ * Retrieve the soc id, rev & uid info:
+ * res.a1[31:16]: soc revision;
+ * res.a1[15:0]: soc id;
+ * res.a2: uid[127:64];
+ * res.a3: uid[63:0];
+ */
+ arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res);
+ if (res.a0 != SMCCC_RET_SUCCESS) {
+ pr_err("%s: SMC failed: 0x%lx\n", __func__, res.a0);
+ err = -EINVAL;
+ goto family;
+ }
+
+ soc_id = SOC_ID(res.a1);
+ rev_major = SOC_REV_MAJOR(res.a1);
+ rev_minor = SOC_REV_MINOR(res.a1);
+
+ attr->soc_id = kasprintf(GFP_KERNEL, "i.MX%2x", soc_id);
+ attr->revision = kasprintf(GFP_KERNEL, "%d.%d", rev_major, rev_minor);
+
+ uid127_64 = res.a2;
+ uid63_0 = res.a3;
+ attr->serial_number = kasprintf(GFP_KERNEL, "%016llx%016llx", uid127_64, uid63_0);
+
+ sdev = soc_device_register(attr);
+ if (IS_ERR(sdev)) {
+ err = PTR_ERR(sdev);
+ pr_err("%s failed to register SoC as a device: %d\n", __func__, err);
+ goto serial_number;
+ }
+
+ return 0;
+
+serial_number:
+ kfree(attr->serial_number);
+ kfree(attr->revision);
+ kfree(attr->soc_id);
+family:
+ kfree(attr->family);
+attr:
+ kfree(attr);
+ return err;
+}
+
+static __maybe_unused const struct of_device_id imx9_soc_match[] = {
+ { .compatible = "fsl,imx93", },
+ { .compatible = "fsl,imx95", },
+ { }
+};
+
+#define IMX_SOC_DRIVER "imx9-soc"
+
+static struct platform_driver imx9_soc_driver = {
+ .probe = imx9_soc_probe,
+ .driver = {
+ .name = IMX_SOC_DRIVER,
+ },
+};
+
+static int __init imx9_soc_init(void)
+{
+ int ret;
+ struct platform_device *pdev;
+
+ /* No match means it is not an i.MX 9 series SoC, do nothing. */
+ if (!of_match_node(imx9_soc_match, of_root))
+ return 0;
+
+ ret = platform_driver_register(&imx9_soc_driver);
+ if (ret) {
+ pr_err("failed to register imx9_soc platform driver: %d\n", ret);
+ return ret;
+ }
+
+ pdev = platform_device_register_simple(IMX_SOC_DRIVER, -1, NULL, 0);
+ if (IS_ERR(pdev)) {
+ pr_err("failed to register imx9_soc platform device: %ld\n", PTR_ERR(pdev));
+ platform_driver_unregister(&imx9_soc_driver);
+ return PTR_ERR(pdev);
+ }
+
+ return 0;
+}
+device_initcall(imx9_soc_init);
+
+MODULE_AUTHOR("NXP");
+MODULE_DESCRIPTION("NXP i.MX9 SoC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c
index 35825ee95dff..33e2e0366f19 100644
--- a/drivers/soc/ixp4xx/ixp4xx-npe.c
+++ b/drivers/soc/ixp4xx/ixp4xx-npe.c
@@ -759,11 +759,12 @@ static struct platform_driver ixp4xx_npe_driver = {
.of_match_table = ixp4xx_npe_of_match,
},
.probe = ixp4xx_npe_probe,
- .remove_new = ixp4xx_npe_remove,
+ .remove = ixp4xx_npe_remove,
};
module_platform_driver(ixp4xx_npe_driver);
MODULE_AUTHOR("Krzysztof Halasa");
+MODULE_DESCRIPTION("Intel IXP4xx Network Processor Engine driver");
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(NPE_A_FIRMWARE);
MODULE_FIRMWARE(NPE_B_FIRMWARE);
diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c
index 244ad8d7e80b..475e229039e3 100644
--- a/drivers/soc/ixp4xx/ixp4xx-qmgr.c
+++ b/drivers/soc/ixp4xx/ixp4xx-qmgr.c
@@ -461,10 +461,11 @@ static struct platform_driver ixp4xx_qmgr_driver = {
.of_match_table = ixp4xx_qmgr_of_match,
},
.probe = ixp4xx_qmgr_probe,
- .remove_new = ixp4xx_qmgr_remove,
+ .remove = ixp4xx_qmgr_remove,
};
module_platform_driver(ixp4xx_qmgr_driver);
+MODULE_DESCRIPTION("Intel IXP4xx Queue Manager driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Krzysztof Halasa");
diff --git a/drivers/soc/litex/Kconfig b/drivers/soc/litex/Kconfig
index e6ba3573a772..f3f869639588 100644
--- a/drivers/soc/litex/Kconfig
+++ b/drivers/soc/litex/Kconfig
@@ -7,7 +7,7 @@ config LITEX
config LITEX_SOC_CONTROLLER
tristate "Enable LiteX SoC Controller driver"
- depends on OF || COMPILE_TEST
+ depends on OF
depends on HAS_IOMEM
select LITEX
help
diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c
index 10813299aa10..104a5f9bfd26 100644
--- a/drivers/soc/litex/litex_soc_ctrl.c
+++ b/drivers/soc/litex/litex_soc_ctrl.c
@@ -69,26 +69,21 @@ static int litex_check_csr_access(void __iomem *reg_addr)
struct litex_soc_ctrl_device {
void __iomem *base;
- struct notifier_block reset_nb;
};
-static int litex_reset_handler(struct notifier_block *this, unsigned long mode,
- void *cmd)
+static int litex_reset_handler(struct sys_off_data *data)
{
- struct litex_soc_ctrl_device *soc_ctrl_dev =
- container_of(this, struct litex_soc_ctrl_device, reset_nb);
+ struct litex_soc_ctrl_device *soc_ctrl_dev = data->cb_data;
litex_write32(soc_ctrl_dev->base + RESET_REG_OFF, RESET_REG_VALUE);
return NOTIFY_DONE;
}
-#ifdef CONFIG_OF
static const struct of_device_id litex_soc_ctrl_of_match[] = {
{.compatible = "litex,soc-controller"},
{},
};
MODULE_DEVICE_TABLE(of, litex_soc_ctrl_of_match);
-#endif /* CONFIG_OF */
static int litex_soc_ctrl_probe(struct platform_device *pdev)
{
@@ -107,11 +102,9 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev)
if (error)
return error;
- platform_set_drvdata(pdev, soc_ctrl_dev);
-
- soc_ctrl_dev->reset_nb.notifier_call = litex_reset_handler;
- soc_ctrl_dev->reset_nb.priority = 128;
- error = register_restart_handler(&soc_ctrl_dev->reset_nb);
+ error = devm_register_restart_handler(&pdev->dev,
+ litex_reset_handler,
+ soc_ctrl_dev);
if (error) {
dev_warn(&pdev->dev, "cannot register restart handler: %d\n",
error);
@@ -120,20 +113,12 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev)
return 0;
}
-static void litex_soc_ctrl_remove(struct platform_device *pdev)
-{
- struct litex_soc_ctrl_device *soc_ctrl_dev = platform_get_drvdata(pdev);
-
- unregister_restart_handler(&soc_ctrl_dev->reset_nb);
-}
-
static struct platform_driver litex_soc_ctrl_driver = {
.driver = {
.name = "litex-soc-controller",
- .of_match_table = of_match_ptr(litex_soc_ctrl_of_match)
+ .of_match_table = litex_soc_ctrl_of_match,
},
.probe = litex_soc_ctrl_probe,
- .remove_new = litex_soc_ctrl_remove,
};
module_platform_driver(litex_soc_ctrl_driver);
diff --git a/drivers/soc/loongson/loongson2_guts.c b/drivers/soc/loongson/loongson2_guts.c
index ef352a0f5022..16913c3ef65c 100644
--- a/drivers/soc/loongson/loongson2_guts.c
+++ b/drivers/soc/loongson/loongson2_guts.c
@@ -114,8 +114,11 @@ static int loongson2_guts_probe(struct platform_device *pdev)
if (of_property_read_string(root, "model", &machine))
of_property_read_string_index(root, "compatible", 0, &machine);
of_node_put(root);
- if (machine)
+ if (machine) {
soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL);
+ if (!soc_dev_attr.machine)
+ return -ENOMEM;
+ }
svr = loongson2_guts_get_svr();
soc_die = loongson2_soc_die_match(svr, loongson2_soc_die);
@@ -169,7 +172,7 @@ static struct platform_driver loongson2_guts_driver = {
.of_match_table = loongson2_guts_of_match,
},
.probe = loongson2_guts_probe,
- .remove_new = loongson2_guts_remove,
+ .remove = loongson2_guts_remove,
};
static int __init loongson2_guts_init(void)
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index 1b7afb19ccd6..d7293977f06e 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -26,6 +26,17 @@ config MTK_DEVAPC
The violation information is logged for further analysis or
countermeasures.
+config MTK_DVFSRC
+ tristate "MediaTek DVFSRC Support"
+ depends on ARCH_MEDIATEK
+ help
+ Say yes here to add support for the MediaTek Dynamic Voltage
+ and Frequency Scaling Resource Collector (DVFSRC): a HW
+ IP found on many MediaTek SoCs, which is responsible for
+ collecting DVFS requests from various SoC IPs, other than
+ software, and performing bandwidth scaling to provide the
+ best achievable performance-per-watt.
+
config MTK_INFRACFG
bool "MediaTek INFRACFG Support"
select REGMAP
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 6830512848fd..0665573e3c4b 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o
+obj-$(CONFIG_MTK_DVFSRC) += mtk-dvfsrc.o
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
obj-$(CONFIG_MTK_REGULATOR_COUPLER) += mtk-regulator-coupler.o
diff --git a/drivers/soc/mediatek/mt8167-mmsys.h b/drivers/soc/mediatek/mt8167-mmsys.h
index f7a35b3656bb..c468926561b4 100644
--- a/drivers/soc/mediatek/mt8167-mmsys.h
+++ b/drivers/soc/mediatek/mt8167-mmsys.h
@@ -14,22 +14,21 @@
#define MT8167_DSI0_SEL_IN_RDMA0 0x1
static const struct mtk_mmsys_routes mt8167_mmsys_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
- MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0,
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_RDMA0,
- MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_RDMA0
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
- MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI0,
- MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_RDMA0
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI0,
- MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_DSI0
- },
+ MMSYS_ROUTE(OVL0, COLOR0,
+ MT8167_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0,
+ OVL0_MOUT_EN_COLOR0),
+ MMSYS_ROUTE(DITHER0, RDMA0,
+ MT8167_DISP_REG_CONFIG_DISP_DITHER_MOUT_EN, MT8167_DITHER_MOUT_EN_RDMA0,
+ MT8167_DITHER_MOUT_EN_RDMA0),
+ MMSYS_ROUTE(OVL0, COLOR0,
+ MT8167_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0,
+ COLOR0_SEL_IN_OVL0),
+ MMSYS_ROUTE(RDMA0, DSI0,
+ MT8167_DISP_REG_CONFIG_DISP_DSI0_SEL_IN, MT8167_DSI0_SEL_IN_RDMA0,
+ MT8167_DSI0_SEL_IN_RDMA0),
+ MMSYS_ROUTE(RDMA0, DSI0,
+ MT8167_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8167_RDMA0_SOUT_DSI0,
+ MT8167_RDMA0_SOUT_DSI0),
};
#endif /* __SOC_MEDIATEK_MT8167_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8173-mmsys.h b/drivers/soc/mediatek/mt8173-mmsys.h
index 9d24e381271e..957876d7c166 100644
--- a/drivers/soc/mediatek/mt8173-mmsys.h
+++ b/drivers/soc/mediatek/mt8173-mmsys.h
@@ -33,63 +33,48 @@
#define MT8173_RDMA0_SOUT_COLOR0 BIT(0)
static const struct mtk_mmsys_routes mt8173_mmsys_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
- MT8173_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN,
- MT8173_OVL0_MOUT_EN_COLOR0, MT8173_OVL0_MOUT_EN_COLOR0
- }, {
- DDP_COMPONENT_OD0, DDP_COMPONENT_RDMA0,
- MT8173_DISP_REG_CONFIG_DISP_OD_MOUT_EN,
- MT8173_OD0_MOUT_EN_RDMA0, MT8173_OD0_MOUT_EN_RDMA0
- }, {
- DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
- MT8173_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN,
- MT8173_UFOE_MOUT_EN_DSI0, MT8173_UFOE_MOUT_EN_DSI0
- }, {
- DDP_COMPONENT_COLOR0, DDP_COMPONENT_AAL0,
- MT8173_DISP_REG_CONFIG_DISP_COLOR0_SOUT_SEL_IN,
- MT8173_COLOR0_SOUT_MERGE, 0 /* SOUT to AAL */
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_UFOE,
- MT8173_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN,
- MT8173_RDMA0_SOUT_COLOR0, 0 /* SOUT to UFOE */
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
- MT8173_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN,
- MT8173_COLOR0_SEL_IN_OVL0, MT8173_COLOR0_SEL_IN_OVL0
- }, {
- DDP_COMPONENT_AAL0, DDP_COMPONENT_COLOR0,
- MT8173_DISP_REG_CONFIG_DISP_AAL_SEL_IN,
- MT8173_AAL_SEL_IN_MERGE, 0 /* SEL_IN from COLOR0 */
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_UFOE,
- MT8173_DISP_REG_CONFIG_DISP_UFOE_SEL_IN,
- MT8173_UFOE_SEL_IN_RDMA0, 0 /* SEL_IN from RDMA0 */
- }, {
- DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
- MT8173_DISP_REG_CONFIG_DSI0_SEL_IN,
- MT8173_DSI0_SEL_IN_UFOE, 0, /* SEL_IN from UFOE */
- }, {
- DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
- MT8173_DISP_REG_CONFIG_DISP_OVL1_MOUT_EN,
- MT8173_OVL1_MOUT_EN_COLOR1, MT8173_OVL1_MOUT_EN_COLOR1
- }, {
- DDP_COMPONENT_GAMMA, DDP_COMPONENT_RDMA1,
- MT8173_DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN,
- MT8173_GAMMA_MOUT_EN_RDMA1, MT8173_GAMMA_MOUT_EN_RDMA1
- }, {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8173_DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN,
- RDMA1_SOUT_MASK, RDMA1_SOUT_DPI0
- }, {
- DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
- MT8173_DISP_REG_CONFIG_DISP_COLOR1_SEL_IN,
- COLOR1_SEL_IN_OVL1, COLOR1_SEL_IN_OVL1
- }, {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8173_DISP_REG_CONFIG_DPI_SEL_IN,
- MT8173_DPI0_SEL_IN_MASK, MT8173_DPI0_SEL_IN_RDMA1
- }
+ MMSYS_ROUTE(OVL0, COLOR0,
+ MT8173_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, MT8173_OVL0_MOUT_EN_COLOR0,
+ MT8173_OVL0_MOUT_EN_COLOR0),
+ MMSYS_ROUTE(OD0, RDMA0,
+ MT8173_DISP_REG_CONFIG_DISP_OD_MOUT_EN, MT8173_OD0_MOUT_EN_RDMA0,
+ MT8173_OD0_MOUT_EN_RDMA0),
+ MMSYS_ROUTE(UFOE, DSI0,
+ MT8173_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN, MT8173_UFOE_MOUT_EN_DSI0,
+ MT8173_UFOE_MOUT_EN_DSI0),
+ MMSYS_ROUTE(COLOR0, AAL0,
+ MT8173_DISP_REG_CONFIG_DISP_COLOR0_SOUT_SEL_IN, MT8173_COLOR0_SOUT_MERGE,
+ 0 /* SOUT to AAL */),
+ MMSYS_ROUTE(RDMA0, UFOE,
+ MT8173_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN, MT8173_RDMA0_SOUT_COLOR0,
+ 0 /* SOUT to UFOE */),
+ MMSYS_ROUTE(OVL0, COLOR0,
+ MT8173_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, MT8173_COLOR0_SEL_IN_OVL0,
+ MT8173_COLOR0_SEL_IN_OVL0),
+ MMSYS_ROUTE(AAL0, COLOR0,
+ MT8173_DISP_REG_CONFIG_DISP_AAL_SEL_IN, MT8173_AAL_SEL_IN_MERGE,
+ 0 /* SEL_IN from COLOR0 */),
+ MMSYS_ROUTE(RDMA0, UFOE,
+ MT8173_DISP_REG_CONFIG_DISP_UFOE_SEL_IN, MT8173_UFOE_SEL_IN_RDMA0,
+ 0 /* SEL_IN from RDMA0 */),
+ MMSYS_ROUTE(UFOE, DSI0,
+ MT8173_DISP_REG_CONFIG_DSI0_SEL_IN, MT8173_DSI0_SEL_IN_UFOE,
+ 0 /* SEL_IN from UFOE */),
+ MMSYS_ROUTE(OVL1, COLOR1,
+ MT8173_DISP_REG_CONFIG_DISP_OVL1_MOUT_EN, MT8173_OVL1_MOUT_EN_COLOR1,
+ MT8173_OVL1_MOUT_EN_COLOR1),
+ MMSYS_ROUTE(GAMMA, RDMA1,
+ MT8173_DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN, MT8173_GAMMA_MOUT_EN_RDMA1,
+ MT8173_GAMMA_MOUT_EN_RDMA1),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8173_DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_MASK,
+ RDMA1_SOUT_DPI0),
+ MMSYS_ROUTE(OVL1, COLOR1,
+ MT8173_DISP_REG_CONFIG_DISP_COLOR1_SEL_IN, COLOR1_SEL_IN_OVL1,
+ COLOR1_SEL_IN_OVL1),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8173_DISP_REG_CONFIG_DPI_SEL_IN, MT8173_DPI0_SEL_IN_MASK,
+ MT8173_DPI0_SEL_IN_RDMA1),
};
#endif /* __SOC_MEDIATEK_MT8173_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8183-mmsys.h b/drivers/soc/mediatek/mt8183-mmsys.h
index ff6be1703469..123384958c4b 100644
--- a/drivers/soc/mediatek/mt8183-mmsys.h
+++ b/drivers/soc/mediatek/mt8183-mmsys.h
@@ -28,35 +28,27 @@
#define MT8183_MMSYS_SW0_RST_B 0x140
static const struct mtk_mmsys_routes mmsys_mt8183_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0,
- MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L,
- MT8183_OVL0_MOUT_EN_OVL0_2L
- }, {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0,
- MT8183_OVL0_2L_MOUT_EN_DISP_PATH0
- }, {
- DDP_COMPONENT_OVL_2L1, DDP_COMPONENT_RDMA1,
- MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1,
- MT8183_OVL1_2L_MOUT_EN_RDMA1
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0,
- MT8183_DITHER0_MOUT_IN_DSI0
- }, {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L,
- MT8183_DISP_PATH0_SEL_IN_OVL0_2L
- }, {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1,
- MT8183_DPI0_SEL_IN_RDMA1
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0,
- MT8183_RDMA0_SOUT_COLOR0
- }
+ MMSYS_ROUTE(OVL0, OVL_2L0,
+ MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L,
+ MT8183_OVL0_MOUT_EN_OVL0_2L),
+ MMSYS_ROUTE(OVL_2L0, RDMA0,
+ MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0,
+ MT8183_OVL0_2L_MOUT_EN_DISP_PATH0),
+ MMSYS_ROUTE(OVL_2L1, RDMA1,
+ MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1,
+ MT8183_OVL1_2L_MOUT_EN_RDMA1),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0,
+ MT8183_DITHER0_MOUT_IN_DSI0),
+ MMSYS_ROUTE(OVL_2L0, RDMA0,
+ MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L,
+ MT8183_DISP_PATH0_SEL_IN_OVL0_2L),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1,
+ MT8183_DPI0_SEL_IN_RDMA1),
+ MMSYS_ROUTE(RDMA0, COLOR0,
+ MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0,
+ MT8183_RDMA0_SOUT_COLOR0),
};
#endif /* __SOC_MEDIATEK_MT8183_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8186-mmsys.h b/drivers/soc/mediatek/mt8186-mmsys.h
index 279d4138525b..354664be72bd 100644
--- a/drivers/soc/mediatek/mt8186-mmsys.h
+++ b/drivers/soc/mediatek/mt8186-mmsys.h
@@ -63,61 +63,39 @@
#define MT8186_MMSYS_SW0_RST_B 0x160
static const struct mtk_mmsys_routes mmsys_mt8186_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8186_DISP_OVL0_MOUT_EN, MT8186_OVL0_MOUT_EN_MASK,
- MT8186_OVL0_MOUT_TO_RDMA0
- },
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8186_DISP_RDMA0_SEL_IN, MT8186_RDMA0_SEL_IN_MASK,
- MT8186_RDMA0_FROM_OVL0
- },
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8186_MMSYS_OVL_CON, MT8186_MMSYS_OVL0_CON_MASK,
- MT8186_OVL0_GO_BLEND
- },
- {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8186_DISP_RDMA0_SOUT_SEL, MT8186_RDMA0_SOUT_SEL_MASK,
- MT8186_RDMA0_SOUT_TO_COLOR0
- },
- {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8186_DISP_DITHER0_MOUT_EN, MT8186_DITHER0_MOUT_EN_MASK,
- MT8186_DITHER0_MOUT_TO_DSI0,
- },
- {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8186_DISP_DSI0_SEL_IN, MT8186_DSI0_SEL_IN_MASK,
- MT8186_DSI0_FROM_DITHER0
- },
- {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA1,
- MT8186_DISP_OVL0_2L_MOUT_EN, MT8186_OVL0_2L_MOUT_EN_MASK,
- MT8186_OVL0_2L_MOUT_TO_RDMA1
- },
- {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA1,
- MT8186_DISP_RDMA1_SEL_IN, MT8186_RDMA1_SEL_IN_MASK,
- MT8186_RDMA1_FROM_OVL0_2L
- },
- {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA1,
- MT8186_MMSYS_OVL_CON, MT8186_MMSYS_OVL0_2L_CON_MASK,
- MT8186_OVL0_2L_GO_BLEND
- },
- {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8186_DISP_RDMA1_MOUT_EN, MT8186_RDMA1_MOUT_EN_MASK,
- MT8186_RDMA1_MOUT_TO_DPI0_SEL
- },
- {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8186_DISP_DPI0_SEL_IN, MT8186_DPI0_SEL_IN_MASK,
- MT8186_DPI0_FROM_RDMA1
- },
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8186_DISP_OVL0_MOUT_EN, MT8186_OVL0_MOUT_EN_MASK,
+ MT8186_OVL0_MOUT_TO_RDMA0),
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8186_DISP_RDMA0_SEL_IN, MT8186_RDMA0_SEL_IN_MASK,
+ MT8186_RDMA0_FROM_OVL0),
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8186_MMSYS_OVL_CON, MT8186_MMSYS_OVL0_CON_MASK,
+ MT8186_OVL0_GO_BLEND),
+ MMSYS_ROUTE(RDMA0, COLOR0,
+ MT8186_DISP_RDMA0_SOUT_SEL, MT8186_RDMA0_SOUT_SEL_MASK,
+ MT8186_RDMA0_SOUT_TO_COLOR0),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8186_DISP_DITHER0_MOUT_EN, MT8186_DITHER0_MOUT_EN_MASK,
+ MT8186_DITHER0_MOUT_TO_DSI0),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8186_DISP_DSI0_SEL_IN, MT8186_DSI0_SEL_IN_MASK,
+ MT8186_DSI0_FROM_DITHER0),
+ MMSYS_ROUTE(OVL_2L0, RDMA1,
+ MT8186_DISP_OVL0_2L_MOUT_EN, MT8186_OVL0_2L_MOUT_EN_MASK,
+ MT8186_OVL0_2L_MOUT_TO_RDMA1),
+ MMSYS_ROUTE(OVL_2L0, RDMA1,
+ MT8186_DISP_RDMA1_SEL_IN, MT8186_RDMA1_SEL_IN_MASK,
+ MT8186_RDMA1_FROM_OVL0_2L),
+ MMSYS_ROUTE(OVL_2L0, RDMA1,
+ MT8186_MMSYS_OVL_CON, MT8186_MMSYS_OVL0_2L_CON_MASK,
+ MT8186_OVL0_2L_GO_BLEND),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8186_DISP_RDMA1_MOUT_EN, MT8186_RDMA1_MOUT_EN_MASK,
+ MT8186_RDMA1_MOUT_TO_DPI0_SEL),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8186_DISP_DPI0_SEL_IN, MT8186_DPI0_SEL_IN_MASK,
+ MT8186_DPI0_FROM_RDMA1),
};
#endif /* __SOC_MEDIATEK_MT8186_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8188-mmsys.h b/drivers/soc/mediatek/mt8188-mmsys.h
index 6bebf1a69fc0..99080afead7e 100644
--- a/drivers/soc/mediatek/mt8188-mmsys.h
+++ b/drivers/soc/mediatek/mt8188-mmsys.h
@@ -202,158 +202,126 @@ static const u8 mmsys_mt8188_vdo1_rst_tb[] = {
};
static const struct mtk_mmsys_routes mmsys_mt8188_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8188_VDO0_OVL_MOUT_EN, MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0,
- MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_WDMA0,
- MT8188_VDO0_OVL_MOUT_EN, MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0,
- MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8188_VDO0_DISP_RDMA_SEL, MT8188_SEL_IN_DISP_RDMA0_FROM_MASK,
- MT8188_SEL_IN_DISP_RDMA0_FROM_DISP_OVL0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8188_VDO0_DSI0_SEL_IN, MT8188_SEL_IN_DSI0_FROM_MASK,
- MT8188_SEL_IN_DSI0_FROM_DISP_DITHER0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_MERGE0,
- MT8188_VDO0_VPP_MERGE_SEL, MT8188_SEL_IN_VPP_MERGE_FROM_MASK,
- MT8188_SEL_IN_VPP_MERGE_FROM_DITHER0_OUT
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSC0,
- MT8188_VDO0_DSC_WARP_SEL,
- MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_MASK,
- MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_DISP_DITHER0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DP_INTF0,
- MT8188_VDO0_DP_INTF0_SEL_IN, MT8188_SEL_IN_DP_INTF0_FROM_MASK,
- MT8188_SEL_IN_DP_INTF0_FROM_DISP_DITHER0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0,
- MT8188_VDO0_VPP_MERGE_SEL, MT8188_SEL_IN_VPP_MERGE_FROM_MASK,
- MT8188_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0,
- MT8188_VDO0_DSI0_SEL_IN, MT8188_SEL_IN_DSI0_FROM_MASK,
- MT8188_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8188_VDO0_DISP_RDMA_SEL, MT8188_SOUT_DISP_RDMA0_TO_MASK,
- MT8188_SOUT_DISP_RDMA0_TO_DISP_COLOR0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8188_VDO0_DISP_DITHER0_SEL_OUT,
- MT8188_SOUT_DISP_DITHER0_TO_MASK,
- MT8188_SOUT_DISP_DITHER0_TO_DSI0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DP_INTF0,
- MT8188_VDO0_DISP_DITHER0_SEL_OUT,
- MT8188_SOUT_DISP_DITHER0_TO_MASK,
- MT8188_SOUT_DISP_DITHER0_TO_DP_INTF0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DP_INTF0,
- MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
- MT8188_SOUT_VPP_MERGE_TO_DP_INTF0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DPI0,
- MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
- MT8188_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_WDMA0,
- MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
- MT8188_SOUT_VPP_MERGE_TO_DISP_WDMA0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSC0,
- MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
- MT8188_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0,
- MT8188_VDO0_DSC_WARP_SEL, MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8188_SOUT_DSC_WRAP0_OUT_TO_DSI0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0,
- MT8188_VDO0_DSC_WARP_SEL, MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8188_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE
- },
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8188_VDO0_OVL_MOUT_EN, MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0,
+ MT8188_MOUT_DISP_OVL0_TO_DISP_RDMA0),
+ MMSYS_ROUTE(OVL0, WDMA0,
+ MT8188_VDO0_OVL_MOUT_EN, MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0,
+ MT8188_MOUT_DISP_OVL0_TO_DISP_WDMA0),
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8188_VDO0_DISP_RDMA_SEL, MT8188_SEL_IN_DISP_RDMA0_FROM_MASK,
+ MT8188_SEL_IN_DISP_RDMA0_FROM_DISP_OVL0),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8188_VDO0_DSI0_SEL_IN, MT8188_SEL_IN_DSI0_FROM_MASK,
+ MT8188_SEL_IN_DSI0_FROM_DISP_DITHER0),
+ MMSYS_ROUTE(DITHER0, MERGE0,
+ MT8188_VDO0_VPP_MERGE_SEL, MT8188_SEL_IN_VPP_MERGE_FROM_MASK,
+ MT8188_SEL_IN_DP_INTF0_FROM_DISP_DITHER0),
+ MMSYS_ROUTE(DITHER0, DSC0,
+ MT8188_VDO0_DSC_WARP_SEL, MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_MASK,
+ MT8188_SEL_IN_DSC_WRAP0C0_IN_FROM_DISP_DITHER0),
+ MMSYS_ROUTE(DITHER0, DP_INTF0,
+ MT8188_VDO0_DP_INTF0_SEL_IN, MT8188_SEL_IN_DP_INTF0_FROM_MASK,
+ MT8188_SEL_IN_DP_INTF0_FROM_DISP_DITHER0),
+ MMSYS_ROUTE(DSC0, MERGE0,
+ MT8188_VDO0_VPP_MERGE_SEL, MT8188_SEL_IN_VPP_MERGE_FROM_MASK,
+ MT8188_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(MERGE0, DP_INTF0,
+ MT8188_VDO0_DP_INTF0_SEL_IN, MT8188_SEL_IN_DP_INTF0_FROM_MASK,
+ MT8188_SEL_IN_DP_INTF0_FROM_VPP_MERGE),
+ MMSYS_ROUTE(DSC0, DSI0,
+ MT8188_VDO0_DSI0_SEL_IN, MT8188_SEL_IN_DSI0_FROM_MASK,
+ MT8188_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(RDMA0, COLOR0,
+ MT8188_VDO0_DISP_RDMA_SEL, GENMASK(1, 0),
+ MT8188_SOUT_DISP_RDMA0_TO_DISP_COLOR0),
+ MMSYS_ROUTE(DITHER0, DSC0,
+ MT8188_VDO0_DISP_DITHER0_SEL_OUT, MT8188_SOUT_DISP_DITHER0_TO_MASK,
+ MT8188_SOUT_DISP_DITHER0_TO_DSC_WRAP0_IN),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8188_VDO0_DISP_DITHER0_SEL_OUT, MT8188_SOUT_DISP_DITHER0_TO_MASK,
+ MT8188_SOUT_DISP_DITHER0_TO_DSI0),
+ MMSYS_ROUTE(DITHER0, MERGE0,
+ MT8188_VDO0_DISP_DITHER0_SEL_OUT, MT8188_SOUT_DISP_DITHER0_TO_MASK,
+ MT8188_SOUT_DISP_DITHER0_TO_VPP_MERGE0),
+ MMSYS_ROUTE(DITHER0, DP_INTF0,
+ MT8188_VDO0_DISP_DITHER0_SEL_OUT, MT8188_SOUT_DISP_DITHER0_TO_MASK,
+ MT8188_SOUT_DISP_DITHER0_TO_DP_INTF0),
+ MMSYS_ROUTE(MERGE0, DP_INTF0,
+ MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
+ MT8188_SOUT_VPP_MERGE_TO_DP_INTF0),
+ MMSYS_ROUTE(MERGE0, DPI0,
+ MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
+ MT8188_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(MERGE0, WDMA0,
+ MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
+ MT8188_SOUT_VPP_MERGE_TO_DISP_WDMA0),
+ MMSYS_ROUTE(MERGE0, DSC0,
+ MT8188_VDO0_VPP_MERGE_SEL, MT8188_SOUT_VPP_MERGE_TO_MASK,
+ MT8188_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN),
+ MMSYS_ROUTE(DSC0, DSI0,
+ MT8188_VDO0_DSC_WARP_SEL, MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8188_SOUT_DSC_WRAP0_OUT_TO_DSI0),
+ MMSYS_ROUTE(DSC0, MERGE0,
+ MT8188_VDO0_DSC_WARP_SEL, MT8188_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8188_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE),
};
static const struct mtk_mmsys_routes mmsys_mt8188_vdo1_routing_table[] = {
- {
- DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1,
- MT8188_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0),
- MT8188_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0
- }, {
- DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1,
- MT8188_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0),
- MT8188_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1
- }, {
- DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2,
- MT8188_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0),
- MT8188_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2
- }, {
- DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8188_SOUT_TO_MIXER_IN1_SEL
- }, {
- DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MERGE1_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8188_SOUT_TO_MIXER_IN2_SEL
- }, {
- DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MERGE2_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8188_SOUT_TO_MIXER_IN3_SEL
- }, {
- DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MERGE3_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8188_SOUT_TO_MIXER_IN4_SEL
- }, {
- DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5,
- MT8188_VDO1_MIXER_OUT_SOUT_SEL, GENMASK(0, 0),
- MT8188_MIXER_SOUT_TO_MERGE4_ASYNC_SEL
- }, {
- DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MIXER_IN1_SEL_IN, GENMASK(0, 0),
- MT8188_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT
- }, {
- DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MIXER_IN2_SEL_IN, GENMASK(0, 0),
- MT8188_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT
- }, {
- DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MIXER_IN3_SEL_IN, GENMASK(0, 0),
- MT8188_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT
- }, {
- DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER,
- MT8188_VDO1_MIXER_IN4_SEL_IN, GENMASK(0, 0),
- MT8188_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT
- }, {
- DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5,
- MT8188_VDO1_MIXER_SOUT_SEL_IN, GENMASK(2, 0),
- MT8188_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER
- }, {
- DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5,
- MT8188_VDO1_MERGE4_ASYNC_SEL_IN, GENMASK(2, 0),
- MT8188_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1,
- MT8188_VDO1_DISP_DPI1_SEL_IN, GENMASK(1, 0),
- MT8188_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1,
- MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0),
- MT8188_MERGE4_SOUT_TO_DPI1_SEL
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1,
- MT8188_VDO1_DISP_DP_INTF0_SEL_IN, GENMASK(1, 0),
- MT8188_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1,
- MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(3, 0),
- MT8188_MERGE4_SOUT_TO_DP_INTF0_SEL
- }
+ MMSYS_ROUTE(MDP_RDMA0, MERGE1,
+ MT8188_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0),
+ MT8188_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0),
+ MMSYS_ROUTE(MDP_RDMA1, MERGE1,
+ MT8188_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0),
+ MT8188_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1),
+ MMSYS_ROUTE(MDP_RDMA2, MERGE2,
+ MT8188_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0),
+ MT8188_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2),
+ MMSYS_ROUTE(MERGE1, ETHDR_MIXER,
+ MT8188_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8188_SOUT_TO_MIXER_IN1_SEL),
+ MMSYS_ROUTE(MERGE2, ETHDR_MIXER,
+ MT8188_VDO1_MERGE1_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8188_SOUT_TO_MIXER_IN2_SEL),
+ MMSYS_ROUTE(MERGE3, ETHDR_MIXER,
+ MT8188_VDO1_MERGE2_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8188_SOUT_TO_MIXER_IN3_SEL),
+ MMSYS_ROUTE(MERGE4, ETHDR_MIXER,
+ MT8188_VDO1_MERGE3_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8188_SOUT_TO_MIXER_IN4_SEL),
+ MMSYS_ROUTE(ETHDR_MIXER, MERGE5,
+ MT8188_VDO1_MIXER_OUT_SOUT_SEL, GENMASK(0, 0),
+ MT8188_MIXER_SOUT_TO_MERGE4_ASYNC_SEL),
+ MMSYS_ROUTE(MERGE1, ETHDR_MIXER,
+ MT8188_VDO1_MIXER_IN1_SEL_IN, GENMASK(0, 0),
+ MT8188_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT),
+ MMSYS_ROUTE(MERGE2, ETHDR_MIXER,
+ MT8188_VDO1_MIXER_IN2_SEL_IN, GENMASK(0, 0),
+ MT8188_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT),
+ MMSYS_ROUTE(MERGE3, ETHDR_MIXER,
+ MT8188_VDO1_MIXER_IN3_SEL_IN, GENMASK(0, 0),
+ MT8188_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT),
+ MMSYS_ROUTE(MERGE4, ETHDR_MIXER,
+ MT8188_VDO1_MIXER_IN4_SEL_IN, GENMASK(0, 0),
+ MT8188_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT),
+ MMSYS_ROUTE(ETHDR_MIXER, MERGE5,
+ MT8188_VDO1_MIXER_SOUT_SEL_IN, GENMASK(2, 0),
+ MT8188_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER),
+ MMSYS_ROUTE(ETHDR_MIXER, MERGE5,
+ MT8188_VDO1_MERGE4_ASYNC_SEL_IN, GENMASK(2, 0),
+ MT8188_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT),
+ MMSYS_ROUTE(MERGE5, DPI1,
+ MT8188_VDO1_DISP_DPI1_SEL_IN, GENMASK(1, 0),
+ MT8188_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT),
+ MMSYS_ROUTE(MERGE5, DPI1,
+ MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(3, 0),
+ MT8188_MERGE4_SOUT_TO_DPI1_SEL),
+ MMSYS_ROUTE(MERGE5, DP_INTF1,
+ MT8188_VDO1_DISP_DP_INTF0_SEL_IN, GENMASK(1, 0),
+ MT8188_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT),
+ MMSYS_ROUTE(MERGE5, DP_INTF1,
+ MT8188_VDO1_MERGE4_SOUT_SEL, GENMASK(3, 0),
+ MT8188_MERGE4_SOUT_TO_DP_INTF0_SEL),
};
#endif /* __SOC_MEDIATEK_MT8188_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8192-mmsys.h b/drivers/soc/mediatek/mt8192-mmsys.h
index a016d80b4bc1..7cafa2455fd0 100644
--- a/drivers/soc/mediatek/mt8192-mmsys.h
+++ b/drivers/soc/mediatek/mt8192-mmsys.h
@@ -31,47 +31,36 @@
#define MT8192_DSI0_SEL_IN_DITHER0 0x1
static const struct mtk_mmsys_routes mmsys_mt8192_routing_table[] = {
- {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8192_DISP_OVL0_2L_MOUT_EN, MT8192_OVL0_MOUT_EN_DISP_RDMA0,
- MT8192_OVL0_MOUT_EN_DISP_RDMA0
- }, {
- DDP_COMPONENT_OVL_2L2, DDP_COMPONENT_RDMA4,
- MT8192_DISP_OVL2_2L_MOUT_EN, MT8192_OVL2_2L_MOUT_EN_RDMA4,
- MT8192_OVL2_2L_MOUT_EN_RDMA4
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8192_DISP_DITHER0_MOUT_EN, MT8192_DITHER0_MOUT_IN_DSI0,
- MT8192_DITHER0_MOUT_IN_DSI0
- }, {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8192_DISP_RDMA0_SEL_IN, MT8192_RDMA0_SEL_IN_OVL0_2L,
- MT8192_RDMA0_SEL_IN_OVL0_2L
- }, {
- DDP_COMPONENT_CCORR, DDP_COMPONENT_AAL0,
- MT8192_DISP_AAL0_SEL_IN, MT8192_AAL0_SEL_IN_CCORR0,
- MT8192_AAL0_SEL_IN_CCORR0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8192_DISP_DSI0_SEL_IN, MT8192_DSI0_SEL_IN_DITHER0,
- MT8192_DSI0_SEL_IN_DITHER0
- }, {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8192_DISP_RDMA0_SOUT_SEL, MT8192_RDMA0_SOUT_COLOR0,
- MT8192_RDMA0_SOUT_COLOR0
- }, {
- DDP_COMPONENT_CCORR, DDP_COMPONENT_AAL0,
- MT8192_DISP_CCORR0_SOUT_SEL, MT8192_CCORR0_SOUT_AAL0,
- MT8192_CCORR0_SOUT_AAL0
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0,
- MT8192_MMSYS_OVL_MOUT_EN, MT8192_DISP_OVL0_GO_BG,
- MT8192_DISP_OVL0_GO_BG
- }, {
- DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0,
- MT8192_MMSYS_OVL_MOUT_EN, MT8192_DISP_OVL0_2L_GO_BLEND,
- MT8192_DISP_OVL0_2L_GO_BLEND
- }
+ MMSYS_ROUTE(OVL_2L0, RDMA0,
+ MT8192_DISP_OVL0_2L_MOUT_EN, MT8192_OVL0_MOUT_EN_DISP_RDMA0,
+ MT8192_OVL0_MOUT_EN_DISP_RDMA0),
+ MMSYS_ROUTE(OVL_2L2, RDMA4,
+ MT8192_DISP_OVL2_2L_MOUT_EN, MT8192_OVL2_2L_MOUT_EN_RDMA4,
+ MT8192_OVL2_2L_MOUT_EN_RDMA4),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8192_DISP_DITHER0_MOUT_EN, MT8192_DITHER0_MOUT_IN_DSI0,
+ MT8192_DITHER0_MOUT_IN_DSI0),
+ MMSYS_ROUTE(OVL_2L0, RDMA0,
+ MT8192_DISP_RDMA0_SEL_IN, MT8192_RDMA0_SEL_IN_OVL0_2L,
+ MT8192_RDMA0_SEL_IN_OVL0_2L),
+ MMSYS_ROUTE(CCORR, AAL0,
+ MT8192_DISP_AAL0_SEL_IN, MT8192_AAL0_SEL_IN_CCORR0,
+ MT8192_AAL0_SEL_IN_CCORR0),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8192_DISP_DSI0_SEL_IN, MT8192_DSI0_SEL_IN_DITHER0,
+ MT8192_DSI0_SEL_IN_DITHER0),
+ MMSYS_ROUTE(RDMA0, COLOR0,
+ MT8192_DISP_RDMA0_SOUT_SEL, MT8192_RDMA0_SOUT_COLOR0,
+ MT8192_RDMA0_SOUT_COLOR0),
+ MMSYS_ROUTE(CCORR, AAL0,
+ MT8192_DISP_CCORR0_SOUT_SEL, MT8192_CCORR0_SOUT_AAL0,
+ MT8192_CCORR0_SOUT_AAL0),
+ MMSYS_ROUTE(OVL0, OVL_2L0,
+ MT8192_MMSYS_OVL_MOUT_EN, MT8192_DISP_OVL0_GO_BG,
+ MT8192_DISP_OVL0_GO_BG),
+ MMSYS_ROUTE(OVL_2L0, RDMA0,
+ MT8192_MMSYS_OVL_MOUT_EN, MT8192_DISP_OVL0_2L_GO_BLEND,
+ MT8192_DISP_OVL0_2L_GO_BLEND),
};
#endif /* __SOC_MEDIATEK_MT8192_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8195-mmsys.h b/drivers/soc/mediatek/mt8195-mmsys.h
index 9be2df2832a4..f69929a2a4d4 100644
--- a/drivers/soc/mediatek/mt8195-mmsys.h
+++ b/drivers/soc/mediatek/mt8195-mmsys.h
@@ -160,370 +160,278 @@
#define MT8195_SVPP3_MDP_RSZ BIT(5)
static const struct mtk_mmsys_routes mmsys_mt8195_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL0_TO_DISP_RDMA0,
- MT8195_MOUT_DISP_OVL0_TO_DISP_RDMA0
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_WDMA0,
- MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL0_TO_DISP_WDMA0,
- MT8195_MOUT_DISP_OVL0_TO_DISP_WDMA0
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL1,
- MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL0_TO_DISP_OVL1,
- MT8195_MOUT_DISP_OVL0_TO_DISP_OVL1
- }, {
- DDP_COMPONENT_OVL1, DDP_COMPONENT_RDMA1,
- MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL1_TO_DISP_RDMA1,
- MT8195_MOUT_DISP_OVL1_TO_DISP_RDMA1
- }, {
- DDP_COMPONENT_OVL1, DDP_COMPONENT_WDMA1,
- MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL1_TO_DISP_WDMA1,
- MT8195_MOUT_DISP_OVL1_TO_DISP_WDMA1
- }, {
- DDP_COMPONENT_OVL1, DDP_COMPONENT_OVL0,
- MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL1_TO_DISP_OVL0,
- MT8195_MOUT_DISP_OVL1_TO_DISP_OVL0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_VPP_MERGE_FROM_MASK,
- MT8195_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_VPP_MERGE_FROM_MASK,
- MT8195_SEL_IN_VPP_MERGE_FROM_DISP_DITHER1
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_VPP_MERGE_FROM_MASK,
- MT8195_SEL_IN_VPP_MERGE_FROM_VDO1_VIRTUAL0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSC0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP0_IN_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP0_IN_FROM_DISP_DITHER0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSC0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP0_IN_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP0_IN_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DSC1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_IN_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_IN_FROM_DISP_DITHER1
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSC1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_IN_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_IN_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINB_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINB_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINB_VIRTUAL0_FROM_MASK,
- MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DP_INTF0_FROM_MASK,
- MT8195_SEL_IN_DP_INTF0_FROM_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DP_INTF0_FROM_MASK,
- MT8195_SEL_IN_DP_INTF0_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DP_INTF0_FROM_MASK,
- MT8195_SEL_IN_DP_INTF0_FROM_VDO1_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI0_FROM_MASK,
- MT8195_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI0_FROM_MASK,
- MT8195_SEL_IN_DSI0_FROM_DISP_DITHER0
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI1_FROM_MASK,
- MT8195_SEL_IN_DSI1_FROM_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI1_FROM_MASK,
- MT8195_SEL_IN_DSI1_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_OVL1, DDP_COMPONENT_WDMA1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DISP_WDMA1_FROM_MASK,
- MT8195_SEL_IN_DISP_WDMA1_FROM_DISP_OVL1
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_WDMA1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DISP_WDMA1_FROM_MASK,
- MT8195_SEL_IN_DISP_WDMA1_FROM_VPP_MERGE
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
- MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1
- }, {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_WDMA0,
- MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DISP_WDMA0_FROM_MASK,
- MT8195_SEL_IN_DISP_WDMA0_FROM_DISP_OVL0
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSC0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER0_TO_MASK,
- MT8195_SOUT_DISP_DITHER0_TO_DSC_WRAP0_IN
- }, {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER0_TO_MASK,
- MT8195_SOUT_DISP_DITHER0_TO_DSI0
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DSC1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_VPP_MERGE
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_DITHER1, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
- MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VDO1_VIRTUAL0_TO_MASK,
- MT8195_SOUT_VDO1_VIRTUAL0_TO_VPP_MERGE
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VDO1_VIRTUAL0_TO_MASK,
- MT8195_SOUT_VDO1_VIRTUAL0_TO_DP_INTF0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_DSI1
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_DP_INTF0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_WDMA1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_DISP_WDMA1
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSC0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
- MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN
- }, {
- DDP_COMPONENT_MERGE0, DDP_COMPONENT_DSC1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN_MASK,
- MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DSI0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP0_OUT_TO_DSI0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC0, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DSI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP1_OUT_TO_DSI1
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DP_INTF0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP1_OUT_TO_DP_INTF0
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DPI0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_DPI1,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0
- }, {
- DDP_COMPONENT_DSC1, DDP_COMPONENT_MERGE0,
- MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
- MT8195_SOUT_DSC_WRAP1_OUT_TO_VPP_MERGE
- }
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL0_TO_DISP_RDMA0,
+ MT8195_MOUT_DISP_OVL0_TO_DISP_RDMA0),
+ MMSYS_ROUTE(OVL0, WDMA0,
+ MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL0_TO_DISP_WDMA0,
+ MT8195_MOUT_DISP_OVL0_TO_DISP_WDMA0),
+ MMSYS_ROUTE(OVL0, OVL1,
+ MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL0_TO_DISP_OVL1,
+ MT8195_MOUT_DISP_OVL0_TO_DISP_OVL1),
+ MMSYS_ROUTE(OVL1, RDMA1,
+ MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL1_TO_DISP_RDMA1,
+ MT8195_MOUT_DISP_OVL1_TO_DISP_RDMA1),
+ MMSYS_ROUTE(OVL1, WDMA1,
+ MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL1_TO_DISP_WDMA1,
+ MT8195_MOUT_DISP_OVL1_TO_DISP_WDMA1),
+ MMSYS_ROUTE(OVL1, OVL0,
+ MT8195_VDO0_OVL_MOUT_EN, MT8195_MOUT_DISP_OVL1_TO_DISP_OVL0,
+ MT8195_MOUT_DISP_OVL1_TO_DISP_OVL0),
+ MMSYS_ROUTE(DSC0, MERGE0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_VPP_MERGE_FROM_MASK,
+ MT8195_SEL_IN_VPP_MERGE_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(DITHER1, MERGE0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_VPP_MERGE_FROM_MASK,
+ MT8195_SEL_IN_VPP_MERGE_FROM_DISP_DITHER1),
+ MMSYS_ROUTE(MERGE5, MERGE0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_VPP_MERGE_FROM_MASK,
+ MT8195_SEL_IN_VPP_MERGE_FROM_VDO1_VIRTUAL0),
+ MMSYS_ROUTE(DITHER0, DSC0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP0_IN_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP0_IN_FROM_DISP_DITHER0),
+ MMSYS_ROUTE(MERGE0, DSC0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP0_IN_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP0_IN_FROM_VPP_MERGE),
+ MMSYS_ROUTE(DITHER1, DSC1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_IN_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_IN_FROM_DISP_DITHER1),
+ MMSYS_ROUTE(MERGE0, DSC1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_IN_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_IN_FROM_VPP_MERGE),
+ MMSYS_ROUTE(MERGE0, DP_INTF1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE),
+ MMSYS_ROUTE(MERGE0, DPI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE),
+ MMSYS_ROUTE(MERGE0, DPI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINA_VIRTUAL0_FROM_VPP_MERGE),
+ MMSYS_ROUTE(DSC1, DP_INTF1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DSC1, DPI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DSC1, DPI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINA_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINA_VIRTUAL0_FROM_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DSC0, DP_INTF1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINB_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(DSC0, DPI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINB_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(DSC0, DPI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_SINB_VIRTUAL0_FROM_MASK,
+ MT8195_SEL_IN_SINB_VIRTUAL0_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(DSC1, DP_INTF0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DP_INTF0_FROM_MASK,
+ MT8195_SEL_IN_DP_INTF0_FROM_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(MERGE0, DP_INTF0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DP_INTF0_FROM_MASK,
+ MT8195_SEL_IN_DP_INTF0_FROM_VPP_MERGE),
+ MMSYS_ROUTE(MERGE5, DP_INTF0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DP_INTF0_FROM_MASK,
+ MT8195_SEL_IN_DP_INTF0_FROM_VDO1_VIRTUAL0),
+ MMSYS_ROUTE(DSC0, DSI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI0_FROM_MASK,
+ MT8195_SEL_IN_DSI0_FROM_DSC_WRAP0_OUT),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI0_FROM_MASK,
+ MT8195_SEL_IN_DSI0_FROM_DISP_DITHER0),
+ MMSYS_ROUTE(DSC1, DSI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI1_FROM_MASK,
+ MT8195_SEL_IN_DSI1_FROM_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(MERGE0, DSI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSI1_FROM_MASK,
+ MT8195_SEL_IN_DSI1_FROM_VPP_MERGE),
+ MMSYS_ROUTE(OVL1, WDMA1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DISP_WDMA1_FROM_MASK,
+ MT8195_SEL_IN_DISP_WDMA1_FROM_DISP_OVL1),
+ MMSYS_ROUTE(MERGE0, WDMA1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DISP_WDMA1_FROM_MASK,
+ MT8195_SEL_IN_DISP_WDMA1_FROM_VPP_MERGE),
+ MMSYS_ROUTE(DSC1, DSI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DSC1, DP_INTF0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DSC1, DP_INTF1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DSC1, DPI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DSC1, DPI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DSC1, MERGE0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DITHER1, DSI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1),
+ MMSYS_ROUTE(DITHER1, DP_INTF0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1),
+ MMSYS_ROUTE(DITHER1, DPI0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1),
+ MMSYS_ROUTE(DITHER1, DPI1,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DSC_WRAP1_FROM_MASK,
+ MT8195_SEL_IN_DSC_WRAP1_OUT_FROM_DISP_DITHER1),
+ MMSYS_ROUTE(OVL0, WDMA0,
+ MT8195_VDO0_SEL_IN, MT8195_SEL_IN_DISP_WDMA0_FROM_MASK,
+ MT8195_SEL_IN_DISP_WDMA0_FROM_DISP_OVL0),
+ MMSYS_ROUTE(DITHER0, DSC0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER0_TO_MASK,
+ MT8195_SOUT_DISP_DITHER0_TO_DSC_WRAP0_IN),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER0_TO_MASK,
+ MT8195_SOUT_DISP_DITHER0_TO_DSI0),
+ MMSYS_ROUTE(DITHER1, DSC1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DITHER1, MERGE0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_VPP_MERGE),
+ MMSYS_ROUTE(DITHER1, DSI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DITHER1, DP_INTF0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DITHER1, DP_INTF1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DITHER1, DPI0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(DITHER1, DPI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DISP_DITHER1_TO_MASK,
+ MT8195_SOUT_DISP_DITHER1_TO_DSC_WRAP1_OUT),
+ MMSYS_ROUTE(MERGE5, MERGE0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VDO1_VIRTUAL0_TO_MASK,
+ MT8195_SOUT_VDO1_VIRTUAL0_TO_VPP_MERGE),
+ MMSYS_ROUTE(MERGE5, DP_INTF0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VDO1_VIRTUAL0_TO_MASK,
+ MT8195_SOUT_VDO1_VIRTUAL0_TO_DP_INTF0),
+ MMSYS_ROUTE(MERGE0, DSI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_DSI1),
+ MMSYS_ROUTE(MERGE0, DP_INTF0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_DP_INTF0),
+ MMSYS_ROUTE(MERGE0, DP_INTF1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(MERGE0, DPI0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(MERGE0, DPI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(MERGE0, WDMA1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_DISP_WDMA1),
+ MMSYS_ROUTE(MERGE0, DSC0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP0_IN),
+ MMSYS_ROUTE(MERGE0, DSC1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN_MASK,
+ MT8195_SOUT_VPP_MERGE_TO_DSC_WRAP1_IN),
+ MMSYS_ROUTE(DSC0, DSI0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP0_OUT_TO_DSI0),
+ MMSYS_ROUTE(DSC0, DP_INTF1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0),
+ MMSYS_ROUTE(DSC0, DPI0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0),
+ MMSYS_ROUTE(DSC0, DPI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP0_OUT_TO_SINB_VIRTUAL0),
+ MMSYS_ROUTE(DSC0, MERGE0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP0_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP0_OUT_TO_VPP_MERGE),
+ MMSYS_ROUTE(DSC1, DSI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP1_OUT_TO_DSI1),
+ MMSYS_ROUTE(DSC1, DP_INTF0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP1_OUT_TO_DP_INTF0),
+ MMSYS_ROUTE(DSC1, DP_INTF1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(DSC1, DPI0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(DSC1, DPI1,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP1_OUT_TO_SINA_VIRTUAL0),
+ MMSYS_ROUTE(DSC1, MERGE0,
+ MT8195_VDO0_SEL_OUT, MT8195_SOUT_DSC_WRAP1_OUT_TO_MASK,
+ MT8195_SOUT_DSC_WRAP1_OUT_TO_VPP_MERGE),
};
static const struct mtk_mmsys_routes mmsys_mt8195_vdo1_routing_table[] = {
- {
- DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1,
- MT8195_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0),
- MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0
- }, {
- DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1,
- MT8195_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0),
- MT8195_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1
- }, {
- DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2,
- MT8195_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0),
- MT8195_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2
- }, {
- DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8195_SOUT_TO_MIXER_IN1_SEL
- }, {
- DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MERGE1_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8195_SOUT_TO_MIXER_IN2_SEL
- }, {
- DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MERGE2_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8195_SOUT_TO_MIXER_IN3_SEL
- }, {
- DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MERGE3_ASYNC_SOUT_SEL, GENMASK(1, 0),
- MT8195_SOUT_TO_MIXER_IN4_SEL
- }, {
- DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5,
- MT8195_VDO1_MIXER_OUT_SOUT_SEL, GENMASK(0, 0),
- MT8195_MIXER_SOUT_TO_MERGE4_ASYNC_SEL
- }, {
- DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MIXER_IN1_SEL_IN, GENMASK(0, 0),
- MT8195_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT
- }, {
- DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MIXER_IN2_SEL_IN, GENMASK(0, 0),
- MT8195_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT
- }, {
- DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MIXER_IN3_SEL_IN, GENMASK(0, 0),
- MT8195_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT
- }, {
- DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER,
- MT8195_VDO1_MIXER_IN4_SEL_IN, GENMASK(0, 0),
- MT8195_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT
- }, {
- DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5,
- MT8195_VDO1_MIXER_SOUT_SEL_IN, GENMASK(2, 0),
- MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER
- }, {
- DDP_COMPONENT_ETHDR_MIXER, DDP_COMPONENT_MERGE5,
- MT8195_VDO1_MERGE4_ASYNC_SEL_IN, GENMASK(2, 0),
- MT8195_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1,
- MT8195_VDO1_DISP_DPI1_SEL_IN, GENMASK(1, 0),
- MT8195_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DPI1,
- MT8195_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0),
- MT8195_MERGE4_SOUT_TO_DPI1_SEL
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO1_DISP_DP_INTF0_SEL_IN, GENMASK(1, 0),
- MT8195_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT
- }, {
- DDP_COMPONENT_MERGE5, DDP_COMPONENT_DP_INTF1,
- MT8195_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0),
- MT8195_MERGE4_SOUT_TO_DP_INTF0_SEL
- }
+ MMSYS_ROUTE(MDP_RDMA0, MERGE1,
+ MT8195_VDO1_VPP_MERGE0_P0_SEL_IN, GENMASK(0, 0),
+ MT8195_VPP_MERGE0_P0_SEL_IN_FROM_MDP_RDMA0),
+ MMSYS_ROUTE(MDP_RDMA1, MERGE1,
+ MT8195_VDO1_VPP_MERGE0_P1_SEL_IN, GENMASK(0, 0),
+ MT8195_VPP_MERGE0_P1_SEL_IN_FROM_MDP_RDMA1),
+ MMSYS_ROUTE(MDP_RDMA2, MERGE2,
+ MT8195_VDO1_VPP_MERGE1_P0_SEL_IN, GENMASK(0, 0),
+ MT8195_VPP_MERGE1_P0_SEL_IN_FROM_MDP_RDMA2),
+ MMSYS_ROUTE(MERGE1, ETHDR_MIXER,
+ MT8195_VDO1_MERGE0_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8195_SOUT_TO_MIXER_IN1_SEL),
+ MMSYS_ROUTE(MERGE2, ETHDR_MIXER,
+ MT8195_VDO1_MERGE1_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8195_SOUT_TO_MIXER_IN2_SEL),
+ MMSYS_ROUTE(MERGE3, ETHDR_MIXER,
+ MT8195_VDO1_MERGE2_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8195_SOUT_TO_MIXER_IN3_SEL),
+ MMSYS_ROUTE(MERGE4, ETHDR_MIXER,
+ MT8195_VDO1_MERGE3_ASYNC_SOUT_SEL, GENMASK(1, 0),
+ MT8195_SOUT_TO_MIXER_IN4_SEL),
+ MMSYS_ROUTE(ETHDR_MIXER, MERGE5,
+ MT8195_VDO1_MIXER_OUT_SOUT_SEL, GENMASK(0, 0),
+ MT8195_MIXER_SOUT_TO_MERGE4_ASYNC_SEL),
+ MMSYS_ROUTE(MERGE1, ETHDR_MIXER,
+ MT8195_VDO1_MIXER_IN1_SEL_IN, GENMASK(0, 0),
+ MT8195_MIXER_IN1_SEL_IN_FROM_MERGE0_ASYNC_SOUT),
+ MMSYS_ROUTE(MERGE2, ETHDR_MIXER,
+ MT8195_VDO1_MIXER_IN2_SEL_IN, GENMASK(0, 0),
+ MT8195_MIXER_IN2_SEL_IN_FROM_MERGE1_ASYNC_SOUT),
+ MMSYS_ROUTE(MERGE3, ETHDR_MIXER,
+ MT8195_VDO1_MIXER_IN3_SEL_IN, GENMASK(0, 0),
+ MT8195_MIXER_IN3_SEL_IN_FROM_MERGE2_ASYNC_SOUT),
+ MMSYS_ROUTE(MERGE4, ETHDR_MIXER,
+ MT8195_VDO1_MIXER_IN4_SEL_IN, GENMASK(0, 0),
+ MT8195_MIXER_IN4_SEL_IN_FROM_MERGE3_ASYNC_SOUT),
+ MMSYS_ROUTE(ETHDR_MIXER, MERGE5,
+ MT8195_VDO1_MIXER_SOUT_SEL_IN, GENMASK(2, 0),
+ MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER),
+ MMSYS_ROUTE(ETHDR_MIXER, MERGE5,
+ MT8195_VDO1_MERGE4_ASYNC_SEL_IN, GENMASK(2, 0),
+ MT8195_MERGE4_ASYNC_SEL_IN_FROM_MIXER_OUT_SOUT),
+ MMSYS_ROUTE(MERGE5, DPI1,
+ MT8195_VDO1_DISP_DPI1_SEL_IN, GENMASK(1, 0),
+ MT8195_DISP_DPI1_SEL_IN_FROM_VPP_MERGE4_MOUT),
+ MMSYS_ROUTE(MERGE5, DPI1,
+ MT8195_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0),
+ MT8195_MERGE4_SOUT_TO_DPI1_SEL),
+ MMSYS_ROUTE(MERGE5, DP_INTF1,
+ MT8195_VDO1_DISP_DP_INTF0_SEL_IN, GENMASK(1, 0),
+ MT8195_DISP_DP_INTF0_SEL_IN_FROM_VPP_MERGE4_MOUT),
+ MMSYS_ROUTE(MERGE5, DP_INTF1,
+ MT8195_VDO1_MERGE4_SOUT_SEL, GENMASK(1, 0),
+ MT8195_MERGE4_SOUT_TO_DP_INTF0_SEL),
};
#endif /* __SOC_MEDIATEK_MT8195_MMSYS_H */
diff --git a/drivers/soc/mediatek/mt8365-mmsys.h b/drivers/soc/mediatek/mt8365-mmsys.h
index 7abaf048d91e..533a3fd0923b 100644
--- a/drivers/soc/mediatek/mt8365-mmsys.h
+++ b/drivers/soc/mediatek/mt8365-mmsys.h
@@ -14,8 +14,9 @@
#define MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN 0xfd8
#define MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00 0xfdc
+#define MT8365_DISP_MS_IN_OUT_MASK GENMASK(3, 0)
#define MT8365_RDMA0_SOUT_COLOR0 0x1
-#define MT8365_DITHER_MOUT_EN_DSI0 0x1
+#define MT8365_DITHER_MOUT_EN_DSI0 BIT(0)
#define MT8365_DSI0_SEL_IN_DITHER 0x1
#define MT8365_RDMA0_SEL_IN_OVL0 0x0
#define MT8365_RDMA0_RSZ0_SEL_IN_RDMA0 0x0
@@ -27,56 +28,37 @@
#define MT8365_DPI0_SEL_IN_RDMA1 0x0
static const struct mtk_mmsys_routes mt8365_mmsys_routing_table[] = {
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN,
- MT8365_OVL0_MOUT_PATH0_SEL, MT8365_OVL0_MOUT_PATH0_SEL
- },
- {
- DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
- MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN,
- MT8365_RDMA0_SEL_IN_OVL0, MT8365_RDMA0_SEL_IN_OVL0
- },
- {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL,
- MT8365_RDMA0_SOUT_COLOR0, MT8365_RDMA0_SOUT_COLOR0
- },
- {
- DDP_COMPONENT_COLOR0, DDP_COMPONENT_CCORR,
- MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN,
- MT8365_DISP_COLOR_SEL_IN_COLOR0,MT8365_DISP_COLOR_SEL_IN_COLOR0
- },
- {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN,
- MT8365_DITHER_MOUT_EN_DSI0, MT8365_DITHER_MOUT_EN_DSI0
- },
- {
- DDP_COMPONENT_DITHER0, DDP_COMPONENT_DSI0,
- MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN,
- MT8365_DSI0_SEL_IN_DITHER, MT8365_DSI0_SEL_IN_DITHER
- },
- {
- DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0,
- MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN,
- MT8365_RDMA0_RSZ0_SEL_IN_RDMA0, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0
- },
- {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00,
- MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK, MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK
- },
- {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN,
- MT8365_DPI0_SEL_IN_RDMA1, MT8365_DPI0_SEL_IN_RDMA1
- },
- {
- DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
- MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL,
- MT8365_RDMA1_SOUT_DPI0, MT8365_RDMA1_SOUT_DPI0
- },
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8365_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_OVL0_MOUT_PATH0_SEL),
+ MMSYS_ROUTE(OVL0, RDMA0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA0_SEL_IN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA0_SEL_IN_OVL0),
+ MMSYS_ROUTE(RDMA0, COLOR0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA0_SOUT_COLOR0),
+ MMSYS_ROUTE(COLOR0, CCORR,
+ MT8365_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DISP_COLOR_SEL_IN_COLOR0),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8365_DISP_REG_CONFIG_DISP_DITHER0_MOUT_EN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DITHER_MOUT_EN_DSI0),
+ MMSYS_ROUTE(DITHER0, DSI0,
+ MT8365_DISP_REG_CONFIG_DISP_DSI0_SEL_IN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DSI0_SEL_IN_DITHER),
+ MMSYS_ROUTE(RDMA0, COLOR0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA0_RSZ0_SEL_IN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA0_RSZ0_SEL_IN_RDMA0),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8365_DISP_REG_CONFIG_DISP_LVDS_SYS_CFG_00,
+ MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK,
+ MT8365_LVDS_SYS_CFG_00_SEL_LVDS_PXL_CLK),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8365_DISP_REG_CONFIG_DISP_DPI0_SEL_IN,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_DPI0_SEL_IN_RDMA1),
+ MMSYS_ROUTE(RDMA1, DPI0,
+ MT8365_DISP_REG_CONFIG_DISP_RDMA1_SOUT_SEL,
+ MT8365_DISP_MS_IN_OUT_MASK, MT8365_RDMA1_SOUT_DPI0),
};
#endif /* __SOC_MEDIATEK_MT8365_MMSYS_H */
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
index b0cd071c4719..455221e8de24 100644
--- a/drivers/soc/mediatek/mtk-cmdq-helper.c
+++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
@@ -12,9 +12,13 @@
#define CMDQ_WRITE_ENABLE_MASK BIT(0)
#define CMDQ_POLL_ENABLE_MASK BIT(0)
+/* dedicate the last GPR_R15 to assign the register address to be poll */
+#define CMDQ_POLL_ADDR_GPR (15)
#define CMDQ_EOC_IRQ_EN BIT(0)
+#define CMDQ_IMMEDIATE_VALUE 0
#define CMDQ_REG_TYPE 1
-#define CMDQ_JUMP_RELATIVE 1
+#define CMDQ_JUMP_RELATIVE 0
+#define CMDQ_JUMP_ABSOLUTE 1
struct cmdq_instruction {
union {
@@ -42,6 +46,16 @@ struct cmdq_instruction {
u8 op;
};
+static inline u8 cmdq_operand_get_type(struct cmdq_operand *op)
+{
+ return op->reg ? CMDQ_REG_TYPE : CMDQ_IMMEDIATE_VALUE;
+}
+
+static inline u16 cmdq_operand_get_idx_value(struct cmdq_operand *op)
+{
+ return op->reg ? op->idx : op->value;
+}
+
int cmdq_dev_get_client_reg(struct device *dev,
struct cmdq_client_reg *client_reg, int idx)
{
@@ -55,7 +69,7 @@ int cmdq_dev_get_client_reg(struct device *dev,
"mediatek,gce-client-reg",
3, idx, &spec);
if (err < 0) {
- dev_err(dev,
+ dev_warn(dev,
"error %d can't parse gce-client-reg property (%d)",
err, idx);
@@ -105,22 +119,16 @@ void cmdq_mbox_destroy(struct cmdq_client *client)
}
EXPORT_SYMBOL(cmdq_mbox_destroy);
-struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)
+int cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt, size_t size)
{
- struct cmdq_pkt *pkt;
struct device *dev;
dma_addr_t dma_addr;
- pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
- if (!pkt)
- return ERR_PTR(-ENOMEM);
pkt->va_base = kzalloc(size, GFP_KERNEL);
- if (!pkt->va_base) {
- kfree(pkt);
- return ERR_PTR(-ENOMEM);
- }
+ if (!pkt->va_base)
+ return -ENOMEM;
+
pkt->buf_size = size;
- pkt->cl = (void *)client;
dev = client->chan->mbox->dev;
dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
@@ -128,24 +136,20 @@ struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
kfree(pkt->va_base);
- kfree(pkt);
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
pkt->pa_base = dma_addr;
- return pkt;
+ return 0;
}
EXPORT_SYMBOL(cmdq_pkt_create);
-void cmdq_pkt_destroy(struct cmdq_pkt *pkt)
+void cmdq_pkt_destroy(struct cmdq_client *client, struct cmdq_pkt *pkt)
{
- struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
-
dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
DMA_TO_DEVICE);
kfree(pkt->va_base);
- kfree(pkt);
}
EXPORT_SYMBOL(cmdq_pkt_destroy);
@@ -176,15 +180,23 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt,
return 0;
}
-int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
+static int cmdq_pkt_mask(struct cmdq_pkt *pkt, u32 mask)
{
- struct cmdq_instruction inst;
-
- inst.op = CMDQ_CODE_WRITE;
- inst.value = value;
- inst.offset = offset;
- inst.subsys = subsys;
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_MASK,
+ .mask = ~mask
+ };
+ return cmdq_pkt_append_command(pkt, inst);
+}
+int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
+{
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WRITE,
+ .value = value,
+ .offset = offset,
+ .subsys = subsys
+ };
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write);
@@ -192,36 +204,30 @@ EXPORT_SYMBOL(cmdq_pkt_write);
int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
u16 offset, u32 value, u32 mask)
{
- struct cmdq_instruction inst = { {0} };
u16 offset_mask = offset;
int err;
- if (mask != 0xffffffff) {
- inst.op = CMDQ_CODE_MASK;
- inst.mask = ~mask;
- err = cmdq_pkt_append_command(pkt, inst);
+ if (mask != GENMASK(31, 0)) {
+ err = cmdq_pkt_mask(pkt, mask);
if (err < 0)
return err;
offset_mask |= CMDQ_WRITE_ENABLE_MASK;
}
- err = cmdq_pkt_write(pkt, subsys, offset_mask, value);
-
- return err;
+ return cmdq_pkt_write(pkt, subsys, offset_mask, value);
}
EXPORT_SYMBOL(cmdq_pkt_write_mask);
int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx, u16 addr_low,
u16 reg_idx)
{
- struct cmdq_instruction inst = {};
-
- inst.op = CMDQ_CODE_READ_S;
- inst.dst_t = CMDQ_REG_TYPE;
- inst.sop = high_addr_reg_idx;
- inst.reg_dst = reg_idx;
- inst.src_reg = addr_low;
-
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_READ_S,
+ .dst_t = CMDQ_REG_TYPE,
+ .sop = high_addr_reg_idx,
+ .reg_dst = reg_idx,
+ .src_reg = addr_low
+ };
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_read_s);
@@ -229,14 +235,13 @@ EXPORT_SYMBOL(cmdq_pkt_read_s);
int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
u16 addr_low, u16 src_reg_idx)
{
- struct cmdq_instruction inst = {};
-
- inst.op = CMDQ_CODE_WRITE_S;
- inst.src_t = CMDQ_REG_TYPE;
- inst.sop = high_addr_reg_idx;
- inst.offset = addr_low;
- inst.src_reg = src_reg_idx;
-
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WRITE_S,
+ .src_t = CMDQ_REG_TYPE,
+ .sop = high_addr_reg_idx,
+ .offset = addr_low,
+ .src_reg = src_reg_idx
+ };
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s);
@@ -244,22 +249,19 @@ EXPORT_SYMBOL(cmdq_pkt_write_s);
int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
u16 addr_low, u16 src_reg_idx, u32 mask)
{
- struct cmdq_instruction inst = {};
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WRITE_S_MASK,
+ .src_t = CMDQ_REG_TYPE,
+ .sop = high_addr_reg_idx,
+ .offset = addr_low,
+ .src_reg = src_reg_idx,
+ };
int err;
- inst.op = CMDQ_CODE_MASK;
- inst.mask = ~mask;
- err = cmdq_pkt_append_command(pkt, inst);
+ err = cmdq_pkt_mask(pkt, mask);
if (err < 0)
return err;
- inst.mask = 0;
- inst.op = CMDQ_CODE_WRITE_S_MASK;
- inst.src_t = CMDQ_REG_TYPE;
- inst.sop = high_addr_reg_idx;
- inst.offset = addr_low;
- inst.src_reg = src_reg_idx;
-
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s_mask);
@@ -267,13 +269,12 @@ EXPORT_SYMBOL(cmdq_pkt_write_s_mask);
int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
u16 addr_low, u32 value)
{
- struct cmdq_instruction inst = {};
-
- inst.op = CMDQ_CODE_WRITE_S;
- inst.sop = high_addr_reg_idx;
- inst.offset = addr_low;
- inst.value = value;
-
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WRITE_S,
+ .sop = high_addr_reg_idx,
+ .offset = addr_low,
+ .value = value
+ };
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s_value);
@@ -281,50 +282,89 @@ EXPORT_SYMBOL(cmdq_pkt_write_s_value);
int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
u16 addr_low, u32 value, u32 mask)
{
- struct cmdq_instruction inst = {};
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WRITE_S_MASK,
+ .sop = high_addr_reg_idx,
+ .offset = addr_low,
+ .value = value
+ };
int err;
- inst.op = CMDQ_CODE_MASK;
- inst.mask = ~mask;
- err = cmdq_pkt_append_command(pkt, inst);
+ err = cmdq_pkt_mask(pkt, mask);
if (err < 0)
return err;
- inst.op = CMDQ_CODE_WRITE_S_MASK;
- inst.sop = high_addr_reg_idx;
- inst.offset = addr_low;
- inst.value = value;
-
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_write_s_mask_value);
+int cmdq_pkt_mem_move(struct cmdq_pkt *pkt, dma_addr_t src_addr, dma_addr_t dst_addr)
+{
+ const u16 high_addr_reg_idx = CMDQ_THR_SPR_IDX0;
+ const u16 value_reg_idx = CMDQ_THR_SPR_IDX1;
+ int ret;
+
+ /* read the value of src_addr into high_addr_reg_idx */
+ ret = cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(src_addr));
+ if (ret < 0)
+ return ret;
+ ret = cmdq_pkt_read_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(src_addr), value_reg_idx);
+ if (ret < 0)
+ return ret;
+
+ /* write the value of value_reg_idx into dst_addr */
+ ret = cmdq_pkt_assign(pkt, high_addr_reg_idx, CMDQ_ADDR_HIGH(dst_addr));
+ if (ret < 0)
+ return ret;
+ ret = cmdq_pkt_write_s(pkt, high_addr_reg_idx, CMDQ_ADDR_LOW(dst_addr), value_reg_idx);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(cmdq_pkt_mem_move);
+
int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear)
{
- struct cmdq_instruction inst = { {0} };
u32 clear_option = clear ? CMDQ_WFE_UPDATE : 0;
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WFE,
+ .value = CMDQ_WFE_OPTION | clear_option,
+ .event = event
+ };
if (event >= CMDQ_MAX_EVENT)
return -EINVAL;
- inst.op = CMDQ_CODE_WFE;
- inst.value = CMDQ_WFE_OPTION | clear_option;
- inst.event = event;
-
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_wfe);
-int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
+int cmdq_pkt_acquire_event(struct cmdq_pkt *pkt, u16 event)
{
- struct cmdq_instruction inst = { {0} };
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WFE,
+ .value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE | CMDQ_WFE_WAIT,
+ .event = event
+ };
if (event >= CMDQ_MAX_EVENT)
return -EINVAL;
- inst.op = CMDQ_CODE_WFE;
- inst.value = CMDQ_WFE_UPDATE;
- inst.event = event;
+ return cmdq_pkt_append_command(pkt, inst);
+}
+EXPORT_SYMBOL(cmdq_pkt_acquire_event);
+
+int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
+{
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WFE,
+ .value = CMDQ_WFE_UPDATE,
+ .event = event
+ };
+
+ if (event >= CMDQ_MAX_EVENT)
+ return -EINVAL;
return cmdq_pkt_append_command(pkt, inst);
}
@@ -332,15 +372,15 @@ EXPORT_SYMBOL(cmdq_pkt_clear_event);
int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event)
{
- struct cmdq_instruction inst = {};
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_WFE,
+ .value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE,
+ .event = event
+ };
if (event >= CMDQ_MAX_EVENT)
return -EINVAL;
- inst.op = CMDQ_CODE_WFE;
- inst.value = CMDQ_WFE_UPDATE | CMDQ_WFE_UPDATE_VALUE;
- inst.event = event;
-
return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_set_event);
@@ -348,97 +388,141 @@ EXPORT_SYMBOL(cmdq_pkt_set_event);
int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
u16 offset, u32 value)
{
- struct cmdq_instruction inst = { {0} };
- int err;
-
- inst.op = CMDQ_CODE_POLL;
- inst.value = value;
- inst.offset = offset;
- inst.subsys = subsys;
- err = cmdq_pkt_append_command(pkt, inst);
-
- return err;
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_POLL,
+ .value = value,
+ .offset = offset,
+ .subsys = subsys
+ };
+ return cmdq_pkt_append_command(pkt, inst);
}
EXPORT_SYMBOL(cmdq_pkt_poll);
int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
u16 offset, u32 value, u32 mask)
{
- struct cmdq_instruction inst = { {0} };
int err;
- inst.op = CMDQ_CODE_MASK;
- inst.mask = ~mask;
- err = cmdq_pkt_append_command(pkt, inst);
+ err = cmdq_pkt_mask(pkt, mask);
if (err < 0)
return err;
offset = offset | CMDQ_POLL_ENABLE_MASK;
- err = cmdq_pkt_poll(pkt, subsys, offset, value);
-
- return err;
+ return cmdq_pkt_poll(pkt, subsys, offset, value);
}
EXPORT_SYMBOL(cmdq_pkt_poll_mask);
-int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
+int cmdq_pkt_poll_addr(struct cmdq_pkt *pkt, dma_addr_t addr, u32 value, u32 mask)
{
- struct cmdq_instruction inst = {};
+ struct cmdq_instruction inst = { {0} };
+ u8 use_mask = 0;
+ int ret;
+
+ /*
+ * Append an MASK instruction to set the mask for following POLL instruction
+ * which enables use_mask bit.
+ */
+ if (mask != GENMASK(31, 0)) {
+ ret = cmdq_pkt_mask(pkt, mask);
+ if (ret < 0)
+ return ret;
+ use_mask = CMDQ_POLL_ENABLE_MASK;
+ }
- inst.op = CMDQ_CODE_LOGIC;
+ /*
+ * POLL is an legacy operation in GCE and it does not support SPR and CMDQ_CODE_LOGIC,
+ * so it can not use cmdq_pkt_assign to keep polling register address to SPR.
+ * If user wants to poll a register address which doesn't have a subsys id,
+ * user needs to use GPR and CMDQ_CODE_MASK to move polling register address to GPR.
+ */
+ inst.op = CMDQ_CODE_MASK;
inst.dst_t = CMDQ_REG_TYPE;
- inst.reg_dst = reg_idx;
+ inst.sop = CMDQ_POLL_ADDR_GPR;
+ inst.value = addr;
+ ret = cmdq_pkt_append_command(pkt, inst);
+ if (ret < 0)
+ return ret;
+
+ /* Append POLL instruction to poll the register address assign to GPR previously. */
+ inst.op = CMDQ_CODE_POLL;
+ inst.dst_t = CMDQ_REG_TYPE;
+ inst.sop = CMDQ_POLL_ADDR_GPR;
+ inst.offset = use_mask;
inst.value = value;
- return cmdq_pkt_append_command(pkt, inst);
+ ret = cmdq_pkt_append_command(pkt, inst);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
-EXPORT_SYMBOL(cmdq_pkt_assign);
+EXPORT_SYMBOL(cmdq_pkt_poll_addr);
-int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr)
+int cmdq_pkt_logic_command(struct cmdq_pkt *pkt, u16 result_reg_idx,
+ struct cmdq_operand *left_operand,
+ enum cmdq_logic_op s_op,
+ struct cmdq_operand *right_operand)
{
- struct cmdq_instruction inst = {};
+ struct cmdq_instruction inst;
+
+ if (!left_operand || !right_operand || s_op >= CMDQ_LOGIC_MAX)
+ return -EINVAL;
+
+ inst.value = 0;
+ inst.op = CMDQ_CODE_LOGIC;
+ inst.dst_t = CMDQ_REG_TYPE;
+ inst.src_t = cmdq_operand_get_type(left_operand);
+ inst.arg_c_t = cmdq_operand_get_type(right_operand);
+ inst.sop = s_op;
+ inst.reg_dst = result_reg_idx;
+ inst.src_reg = cmdq_operand_get_idx_value(left_operand);
+ inst.arg_c = cmdq_operand_get_idx_value(right_operand);
- inst.op = CMDQ_CODE_JUMP;
- inst.offset = CMDQ_JUMP_RELATIVE;
- inst.value = addr >>
- cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan);
return cmdq_pkt_append_command(pkt, inst);
}
-EXPORT_SYMBOL(cmdq_pkt_jump);
+EXPORT_SYMBOL(cmdq_pkt_logic_command);
-int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
+int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
{
- struct cmdq_instruction inst = { {0} };
- int err;
-
- /* insert EOC and generate IRQ for each command iteration */
- inst.op = CMDQ_CODE_EOC;
- inst.value = CMDQ_EOC_IRQ_EN;
- err = cmdq_pkt_append_command(pkt, inst);
- if (err < 0)
- return err;
-
- /* JUMP to end */
- inst.op = CMDQ_CODE_JUMP;
- inst.value = CMDQ_JUMP_PASS >>
- cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan);
- err = cmdq_pkt_append_command(pkt, inst);
-
- return err;
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_LOGIC,
+ .dst_t = CMDQ_REG_TYPE,
+ .reg_dst = reg_idx,
+ .value = value
+ };
+ return cmdq_pkt_append_command(pkt, inst);
}
-EXPORT_SYMBOL(cmdq_pkt_finalize);
+EXPORT_SYMBOL(cmdq_pkt_assign);
-int cmdq_pkt_flush_async(struct cmdq_pkt *pkt)
+int cmdq_pkt_jump_abs(struct cmdq_pkt *pkt, dma_addr_t addr, u8 shift_pa)
{
- int err;
- struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_JUMP,
+ .offset = CMDQ_JUMP_ABSOLUTE,
+ .value = addr >> shift_pa
+ };
+ return cmdq_pkt_append_command(pkt, inst);
+}
+EXPORT_SYMBOL(cmdq_pkt_jump_abs);
- err = mbox_send_message(client->chan, pkt);
- if (err < 0)
- return err;
- /* We can send next packet immediately, so just call txdone. */
- mbox_client_txdone(client->chan, 0);
+int cmdq_pkt_jump_rel(struct cmdq_pkt *pkt, s32 offset, u8 shift_pa)
+{
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_JUMP,
+ .value = (u32)offset >> shift_pa
+ };
+ return cmdq_pkt_append_command(pkt, inst);
+}
+EXPORT_SYMBOL(cmdq_pkt_jump_rel);
- return 0;
+int cmdq_pkt_eoc(struct cmdq_pkt *pkt)
+{
+ struct cmdq_instruction inst = {
+ .op = CMDQ_CODE_EOC,
+ .value = CMDQ_EOC_IRQ_EN
+ };
+ return cmdq_pkt_append_command(pkt, inst);
}
-EXPORT_SYMBOL(cmdq_pkt_flush_async);
+EXPORT_SYMBOL(cmdq_pkt_eoc);
+MODULE_DESCRIPTION("MediaTek Command Queue (CMDQ) driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/mediatek/mtk-devapc.c b/drivers/soc/mediatek/mtk-devapc.c
index 56cc345552a4..f54c966138b5 100644
--- a/drivers/soc/mediatek/mtk-devapc.c
+++ b/drivers/soc/mediatek/mtk-devapc.c
@@ -273,23 +273,31 @@ static int mtk_devapc_probe(struct platform_device *pdev)
return -EINVAL;
devapc_irq = irq_of_parse_and_map(node, 0);
- if (!devapc_irq)
- return -EINVAL;
+ if (!devapc_irq) {
+ ret = -EINVAL;
+ goto err;
+ }
ctx->infra_clk = devm_clk_get_enabled(&pdev->dev, "devapc-infra-clock");
- if (IS_ERR(ctx->infra_clk))
- return -EINVAL;
+ if (IS_ERR(ctx->infra_clk)) {
+ ret = -EINVAL;
+ goto err;
+ }
ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq,
IRQF_TRIGGER_NONE, "devapc", ctx);
if (ret)
- return ret;
+ goto err;
platform_set_drvdata(pdev, ctx);
start_devapc(ctx);
return 0;
+
+err:
+ iounmap(ctx->infra_base);
+ return ret;
}
static void mtk_devapc_remove(struct platform_device *pdev)
@@ -297,11 +305,12 @@ static void mtk_devapc_remove(struct platform_device *pdev)
struct mtk_devapc_context *ctx = platform_get_drvdata(pdev);
stop_devapc(ctx);
+ iounmap(ctx->infra_base);
}
static struct platform_driver mtk_devapc_driver = {
.probe = mtk_devapc_probe,
- .remove_new = mtk_devapc_remove,
+ .remove = mtk_devapc_remove,
.driver = {
.name = "mtk-devapc",
.of_match_table = mtk_devapc_dt_match,
diff --git a/drivers/soc/mediatek/mtk-dvfsrc.c b/drivers/soc/mediatek/mtk-dvfsrc.c
new file mode 100644
index 000000000000..41add5636b03
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-dvfsrc.c
@@ -0,0 +1,578 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 MediaTek Inc.
+ * Copyright (c) 2024 Collabora Ltd.
+ * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+#include <linux/arm-smccc.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/soc/mediatek/dvfsrc.h>
+#include <linux/soc/mediatek/mtk_sip_svc.h>
+
+/* DVFSRC_LEVEL */
+#define DVFSRC_V1_LEVEL_TARGET_LEVEL GENMASK(15, 0)
+#define DVFSRC_TGT_LEVEL_IDLE 0x00
+#define DVFSRC_V1_LEVEL_CURRENT_LEVEL GENMASK(31, 16)
+
+/* DVFSRC_SW_REQ, DVFSRC_SW_REQ2 */
+#define DVFSRC_V1_SW_REQ2_DRAM_LEVEL GENMASK(1, 0)
+#define DVFSRC_V1_SW_REQ2_VCORE_LEVEL GENMASK(3, 2)
+
+#define DVFSRC_V2_SW_REQ_DRAM_LEVEL GENMASK(3, 0)
+#define DVFSRC_V2_SW_REQ_VCORE_LEVEL GENMASK(6, 4)
+
+/* DVFSRC_VCORE */
+#define DVFSRC_V2_VCORE_REQ_VSCP_LEVEL GENMASK(14, 12)
+
+#define DVFSRC_POLL_TIMEOUT_US 1000
+#define STARTUP_TIME_US 1
+
+#define MTK_SIP_DVFSRC_INIT 0x0
+#define MTK_SIP_DVFSRC_START 0x1
+
+struct dvfsrc_bw_constraints {
+ u16 max_dram_nom_bw;
+ u16 max_dram_peak_bw;
+ u16 max_dram_hrt_bw;
+};
+
+struct dvfsrc_opp {
+ u32 vcore_opp;
+ u32 dram_opp;
+};
+
+struct dvfsrc_opp_desc {
+ const struct dvfsrc_opp *opps;
+ u32 num_opp;
+};
+
+struct dvfsrc_soc_data;
+struct mtk_dvfsrc {
+ struct device *dev;
+ struct platform_device *icc;
+ struct platform_device *regulator;
+ const struct dvfsrc_soc_data *dvd;
+ const struct dvfsrc_opp_desc *curr_opps;
+ void __iomem *regs;
+ int dram_type;
+};
+
+struct dvfsrc_soc_data {
+ const int *regs;
+ const struct dvfsrc_opp_desc *opps_desc;
+ u32 (*get_target_level)(struct mtk_dvfsrc *dvfsrc);
+ u32 (*get_current_level)(struct mtk_dvfsrc *dvfsrc);
+ u32 (*get_vcore_level)(struct mtk_dvfsrc *dvfsrc);
+ u32 (*get_vscp_level)(struct mtk_dvfsrc *dvfsrc);
+ void (*set_dram_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw);
+ void (*set_dram_peak_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw);
+ void (*set_dram_hrt_bw)(struct mtk_dvfsrc *dvfsrc, u64 bw);
+ void (*set_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
+ void (*set_vcore_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
+ void (*set_vscp_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
+ int (*wait_for_opp_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
+ int (*wait_for_vcore_level)(struct mtk_dvfsrc *dvfsrc, u32 level);
+ const struct dvfsrc_bw_constraints *bw_constraints;
+};
+
+static u32 dvfsrc_readl(struct mtk_dvfsrc *dvfs, u32 offset)
+{
+ return readl(dvfs->regs + dvfs->dvd->regs[offset]);
+}
+
+static void dvfsrc_writel(struct mtk_dvfsrc *dvfs, u32 offset, u32 val)
+{
+ writel(val, dvfs->regs + dvfs->dvd->regs[offset]);
+}
+
+enum dvfsrc_regs {
+ DVFSRC_SW_REQ,
+ DVFSRC_SW_REQ2,
+ DVFSRC_LEVEL,
+ DVFSRC_TARGET_LEVEL,
+ DVFSRC_SW_BW,
+ DVFSRC_SW_PEAK_BW,
+ DVFSRC_SW_HRT_BW,
+ DVFSRC_VCORE,
+ DVFSRC_REGS_MAX,
+};
+
+static const int dvfsrc_mt8183_regs[] = {
+ [DVFSRC_SW_REQ] = 0x4,
+ [DVFSRC_SW_REQ2] = 0x8,
+ [DVFSRC_LEVEL] = 0xDC,
+ [DVFSRC_SW_BW] = 0x160,
+};
+
+static const int dvfsrc_mt8195_regs[] = {
+ [DVFSRC_SW_REQ] = 0xc,
+ [DVFSRC_VCORE] = 0x6c,
+ [DVFSRC_SW_PEAK_BW] = 0x278,
+ [DVFSRC_SW_BW] = 0x26c,
+ [DVFSRC_SW_HRT_BW] = 0x290,
+ [DVFSRC_LEVEL] = 0xd44,
+ [DVFSRC_TARGET_LEVEL] = 0xd48,
+};
+
+static const struct dvfsrc_opp *dvfsrc_get_current_opp(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 level = dvfsrc->dvd->get_current_level(dvfsrc);
+
+ return &dvfsrc->curr_opps->opps[level];
+}
+
+static bool dvfsrc_is_idle(struct mtk_dvfsrc *dvfsrc)
+{
+ if (!dvfsrc->dvd->get_target_level)
+ return true;
+
+ return dvfsrc->dvd->get_target_level(dvfsrc) == DVFSRC_TGT_LEVEL_IDLE;
+}
+
+static int dvfsrc_wait_for_vcore_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ const struct dvfsrc_opp *curr;
+
+ return readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr,
+ curr->vcore_opp >= level, STARTUP_TIME_US,
+ DVFSRC_POLL_TIMEOUT_US);
+}
+
+static int dvfsrc_wait_for_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ const struct dvfsrc_opp *target, *curr;
+ int ret;
+
+ target = &dvfsrc->curr_opps->opps[level];
+ ret = readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr,
+ curr->dram_opp >= target->dram_opp &&
+ curr->vcore_opp >= target->vcore_opp,
+ STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US);
+ if (ret < 0) {
+ dev_warn(dvfsrc->dev,
+ "timeout! target OPP: %u, dram: %d, vcore: %d\n", level,
+ curr->dram_opp, curr->vcore_opp);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int dvfsrc_wait_for_opp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ const struct dvfsrc_opp *target, *curr;
+ int ret;
+
+ target = &dvfsrc->curr_opps->opps[level];
+ ret = readx_poll_timeout_atomic(dvfsrc_get_current_opp, dvfsrc, curr,
+ curr->dram_opp >= target->dram_opp &&
+ curr->vcore_opp >= target->vcore_opp,
+ STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US);
+ if (ret < 0) {
+ dev_warn(dvfsrc->dev,
+ "timeout! target OPP: %u, dram: %d\n", level, curr->dram_opp);
+ return ret;
+ }
+
+ return 0;
+}
+
+static u32 dvfsrc_get_target_level_v1(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL);
+
+ return FIELD_GET(DVFSRC_V1_LEVEL_TARGET_LEVEL, val);
+}
+
+static u32 dvfsrc_get_current_level_v1(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL);
+ u32 current_level = FIELD_GET(DVFSRC_V1_LEVEL_CURRENT_LEVEL, val);
+
+ return ffs(current_level) - 1;
+}
+
+static u32 dvfsrc_get_target_level_v2(struct mtk_dvfsrc *dvfsrc)
+{
+ return dvfsrc_readl(dvfsrc, DVFSRC_TARGET_LEVEL);
+}
+
+static u32 dvfsrc_get_current_level_v2(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_LEVEL);
+ u32 level = ffs(val);
+
+ /* Valid levels */
+ if (level < dvfsrc->curr_opps->num_opp)
+ return dvfsrc->curr_opps->num_opp - level;
+
+ /* Zero for level 0 or invalid level */
+ return 0;
+}
+
+static u32 dvfsrc_get_vcore_level_v1(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ2);
+
+ return FIELD_GET(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, val);
+}
+
+static void dvfsrc_set_vcore_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ2);
+
+ val &= ~DVFSRC_V1_SW_REQ2_VCORE_LEVEL;
+ val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, level);
+
+ dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ2, val);
+}
+
+static u32 dvfsrc_get_vcore_level_v2(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ);
+
+ return FIELD_GET(DVFSRC_V2_SW_REQ_VCORE_LEVEL, val);
+}
+
+static void dvfsrc_set_vcore_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_SW_REQ);
+
+ val &= ~DVFSRC_V2_SW_REQ_VCORE_LEVEL;
+ val |= FIELD_PREP(DVFSRC_V2_SW_REQ_VCORE_LEVEL, level);
+
+ dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val);
+}
+
+static u32 dvfsrc_get_vscp_level_v2(struct mtk_dvfsrc *dvfsrc)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_VCORE);
+
+ return FIELD_GET(DVFSRC_V2_VCORE_REQ_VSCP_LEVEL, val);
+}
+
+static void dvfsrc_set_vscp_level_v2(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ u32 val = dvfsrc_readl(dvfsrc, DVFSRC_VCORE);
+
+ val &= ~DVFSRC_V2_VCORE_REQ_VSCP_LEVEL;
+ val |= FIELD_PREP(DVFSRC_V2_VCORE_REQ_VSCP_LEVEL, level);
+
+ dvfsrc_writel(dvfsrc, DVFSRC_VCORE, val);
+}
+
+static void __dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u32 reg,
+ u16 max_bw, u16 min_bw, u64 bw)
+{
+ u32 new_bw = (u32)div_u64(bw, 100 * 1000);
+
+ /* If bw constraints (in mbps) are defined make sure to respect them */
+ if (max_bw)
+ new_bw = min(new_bw, max_bw);
+ if (min_bw && new_bw > 0)
+ new_bw = max(new_bw, min_bw);
+
+ dvfsrc_writel(dvfsrc, reg, new_bw);
+}
+
+static void dvfsrc_set_dram_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw)
+{
+ u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_nom_bw;
+
+ __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_BW, max_bw, 0, bw);
+};
+
+static void dvfsrc_set_dram_peak_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw)
+{
+ u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_peak_bw;
+
+ __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_PEAK_BW, max_bw, 0, bw);
+}
+
+static void dvfsrc_set_dram_hrt_bw_v1(struct mtk_dvfsrc *dvfsrc, u64 bw)
+{
+ u64 max_bw = dvfsrc->dvd->bw_constraints->max_dram_hrt_bw;
+
+ __dvfsrc_set_dram_bw_v1(dvfsrc, DVFSRC_SW_HRT_BW, max_bw, 0, bw);
+}
+
+static void dvfsrc_set_opp_level_v1(struct mtk_dvfsrc *dvfsrc, u32 level)
+{
+ const struct dvfsrc_opp *opp = &dvfsrc->curr_opps->opps[level];
+ u32 val;
+
+ /* Translate Pstate to DVFSRC level and set it to DVFSRC HW */
+ val = FIELD_PREP(DVFSRC_V1_SW_REQ2_DRAM_LEVEL, opp->dram_opp);
+ val |= FIELD_PREP(DVFSRC_V1_SW_REQ2_VCORE_LEVEL, opp->vcore_opp);
+
+ dev_dbg(dvfsrc->dev, "vcore_opp: %d, dram_opp: %d\n", opp->vcore_opp, opp->dram_opp);
+ dvfsrc_writel(dvfsrc, DVFSRC_SW_REQ, val);
+}
+
+int mtk_dvfsrc_send_request(const struct device *dev, u32 cmd, u64 data)
+{
+ struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev);
+ bool state;
+ int ret;
+
+ dev_dbg(dvfsrc->dev, "cmd: %d, data: %llu\n", cmd, data);
+
+ switch (cmd) {
+ case MTK_DVFSRC_CMD_BW:
+ dvfsrc->dvd->set_dram_bw(dvfsrc, data);
+ return 0;
+ case MTK_DVFSRC_CMD_HRT_BW:
+ if (dvfsrc->dvd->set_dram_hrt_bw)
+ dvfsrc->dvd->set_dram_hrt_bw(dvfsrc, data);
+ return 0;
+ case MTK_DVFSRC_CMD_PEAK_BW:
+ if (dvfsrc->dvd->set_dram_peak_bw)
+ dvfsrc->dvd->set_dram_peak_bw(dvfsrc, data);
+ return 0;
+ case MTK_DVFSRC_CMD_OPP:
+ if (!dvfsrc->dvd->set_opp_level)
+ return 0;
+
+ dvfsrc->dvd->set_opp_level(dvfsrc, data);
+ break;
+ case MTK_DVFSRC_CMD_VCORE_LEVEL:
+ dvfsrc->dvd->set_vcore_level(dvfsrc, data);
+ break;
+ case MTK_DVFSRC_CMD_VSCP_LEVEL:
+ if (!dvfsrc->dvd->set_vscp_level)
+ return 0;
+
+ dvfsrc->dvd->set_vscp_level(dvfsrc, data);
+ break;
+ default:
+ dev_err(dvfsrc->dev, "unknown command: %d\n", cmd);
+ return -EOPNOTSUPP;
+ }
+
+ /* DVFSRC needs at least 2T(~196ns) to handle a request */
+ udelay(STARTUP_TIME_US);
+
+ ret = readx_poll_timeout_atomic(dvfsrc_is_idle, dvfsrc, state, state,
+ STARTUP_TIME_US, DVFSRC_POLL_TIMEOUT_US);
+ if (ret < 0) {
+ dev_warn(dvfsrc->dev,
+ "%d: idle timeout, data: %llu, last: %d -> %d\n", cmd, data,
+ dvfsrc->dvd->get_current_level(dvfsrc),
+ dvfsrc->dvd->get_target_level(dvfsrc));
+ return ret;
+ }
+
+ if (cmd == MTK_DVFSRC_CMD_OPP)
+ ret = dvfsrc->dvd->wait_for_opp_level(dvfsrc, data);
+ else
+ ret = dvfsrc->dvd->wait_for_vcore_level(dvfsrc, data);
+
+ if (ret < 0) {
+ dev_warn(dvfsrc->dev,
+ "%d: wait timeout, data: %llu, last: %d -> %d\n",
+ cmd, data,
+ dvfsrc->dvd->get_current_level(dvfsrc),
+ dvfsrc->dvd->get_target_level(dvfsrc));
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mtk_dvfsrc_send_request);
+
+int mtk_dvfsrc_query_info(const struct device *dev, u32 cmd, int *data)
+{
+ struct mtk_dvfsrc *dvfsrc = dev_get_drvdata(dev);
+
+ switch (cmd) {
+ case MTK_DVFSRC_CMD_VCORE_LEVEL:
+ *data = dvfsrc->dvd->get_vcore_level(dvfsrc);
+ break;
+ case MTK_DVFSRC_CMD_VSCP_LEVEL:
+ *data = dvfsrc->dvd->get_vscp_level(dvfsrc);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mtk_dvfsrc_query_info);
+
+static int mtk_dvfsrc_probe(struct platform_device *pdev)
+{
+ struct arm_smccc_res ares;
+ struct mtk_dvfsrc *dvfsrc;
+ int ret;
+
+ dvfsrc = devm_kzalloc(&pdev->dev, sizeof(*dvfsrc), GFP_KERNEL);
+ if (!dvfsrc)
+ return -ENOMEM;
+
+ dvfsrc->dvd = of_device_get_match_data(&pdev->dev);
+ dvfsrc->dev = &pdev->dev;
+
+ dvfsrc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+ if (IS_ERR(dvfsrc->regs))
+ return PTR_ERR(dvfsrc->regs);
+
+ arm_smccc_smc(MTK_SIP_DVFSRC_VCOREFS_CONTROL, MTK_SIP_DVFSRC_INIT,
+ 0, 0, 0, 0, 0, 0, &ares);
+ if (ares.a0)
+ return dev_err_probe(&pdev->dev, -EINVAL, "DVFSRC init failed: %lu\n", ares.a0);
+
+ dvfsrc->dram_type = ares.a1;
+ dev_dbg(&pdev->dev, "DRAM Type: %d\n", dvfsrc->dram_type);
+
+ dvfsrc->curr_opps = &dvfsrc->dvd->opps_desc[dvfsrc->dram_type];
+ platform_set_drvdata(pdev, dvfsrc);
+
+ ret = devm_of_platform_populate(&pdev->dev);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Failed to populate child devices\n");
+
+ /* Everything is set up - make it run! */
+ arm_smccc_smc(MTK_SIP_DVFSRC_VCOREFS_CONTROL, MTK_SIP_DVFSRC_START,
+ 0, 0, 0, 0, 0, 0, &ares);
+ if (ares.a0)
+ return dev_err_probe(&pdev->dev, -EINVAL, "Cannot start DVFSRC: %lu\n", ares.a0);
+
+ return 0;
+}
+
+static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_v1 = { 0, 0, 0 };
+static const struct dvfsrc_bw_constraints dvfsrc_bw_constr_v2 = {
+ .max_dram_nom_bw = 255,
+ .max_dram_peak_bw = 255,
+ .max_dram_hrt_bw = 1023,
+};
+
+static const struct dvfsrc_opp dvfsrc_opp_mt6893_lp4[] = {
+ { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },
+ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 },
+ { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 },
+ { 1, 4 }, { 2, 4 }, { 3, 4 }, { 2, 5 },
+ { 3, 5 }, { 3, 6 }, { 4, 6 }, { 4, 7 },
+};
+
+static const struct dvfsrc_opp_desc dvfsrc_opp_mt6893_desc[] = {
+ [0] = {
+ .opps = dvfsrc_opp_mt6893_lp4,
+ .num_opp = ARRAY_SIZE(dvfsrc_opp_mt6893_lp4),
+ }
+};
+
+static const struct dvfsrc_soc_data mt6893_data = {
+ .opps_desc = dvfsrc_opp_mt6893_desc,
+ .regs = dvfsrc_mt8195_regs,
+ .get_target_level = dvfsrc_get_target_level_v2,
+ .get_current_level = dvfsrc_get_current_level_v2,
+ .get_vcore_level = dvfsrc_get_vcore_level_v2,
+ .get_vscp_level = dvfsrc_get_vscp_level_v2,
+ .set_dram_bw = dvfsrc_set_dram_bw_v1,
+ .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1,
+ .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1,
+ .set_vcore_level = dvfsrc_set_vcore_level_v2,
+ .set_vscp_level = dvfsrc_set_vscp_level_v2,
+ .wait_for_opp_level = dvfsrc_wait_for_opp_level_v2,
+ .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1,
+ .bw_constraints = &dvfsrc_bw_constr_v2,
+};
+
+static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp4[] = {
+ { 0, 0 }, { 0, 1 }, { 0, 2 }, { 1, 2 },
+};
+
+static const struct dvfsrc_opp dvfsrc_opp_mt8183_lp3[] = {
+ { 0, 0 }, { 0, 1 }, { 1, 1 }, { 1, 2 },
+};
+
+static const struct dvfsrc_opp_desc dvfsrc_opp_mt8183_desc[] = {
+ [0] = {
+ .opps = dvfsrc_opp_mt8183_lp4,
+ .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp4),
+ },
+ [1] = {
+ .opps = dvfsrc_opp_mt8183_lp3,
+ .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp3),
+ },
+ [2] = {
+ .opps = dvfsrc_opp_mt8183_lp3,
+ .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8183_lp3),
+ }
+};
+
+static const struct dvfsrc_soc_data mt8183_data = {
+ .opps_desc = dvfsrc_opp_mt8183_desc,
+ .regs = dvfsrc_mt8183_regs,
+ .get_target_level = dvfsrc_get_target_level_v1,
+ .get_current_level = dvfsrc_get_current_level_v1,
+ .get_vcore_level = dvfsrc_get_vcore_level_v1,
+ .set_dram_bw = dvfsrc_set_dram_bw_v1,
+ .set_opp_level = dvfsrc_set_opp_level_v1,
+ .set_vcore_level = dvfsrc_set_vcore_level_v1,
+ .wait_for_opp_level = dvfsrc_wait_for_opp_level_v1,
+ .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1,
+ .bw_constraints = &dvfsrc_bw_constr_v1,
+};
+
+static const struct dvfsrc_opp dvfsrc_opp_mt8195_lp4[] = {
+ { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 },
+ { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 },
+ { 1, 3 }, { 2, 3 }, { 3, 3 }, { 1, 4 },
+ { 2, 4 }, { 3, 4 }, { 2, 5 }, { 3, 5 },
+ { 3, 6 },
+};
+
+static const struct dvfsrc_opp_desc dvfsrc_opp_mt8195_desc[] = {
+ [0] = {
+ .opps = dvfsrc_opp_mt8195_lp4,
+ .num_opp = ARRAY_SIZE(dvfsrc_opp_mt8195_lp4),
+ }
+};
+
+static const struct dvfsrc_soc_data mt8195_data = {
+ .opps_desc = dvfsrc_opp_mt8195_desc,
+ .regs = dvfsrc_mt8195_regs,
+ .get_target_level = dvfsrc_get_target_level_v2,
+ .get_current_level = dvfsrc_get_current_level_v2,
+ .get_vcore_level = dvfsrc_get_vcore_level_v2,
+ .get_vscp_level = dvfsrc_get_vscp_level_v2,
+ .set_dram_bw = dvfsrc_set_dram_bw_v1,
+ .set_dram_peak_bw = dvfsrc_set_dram_peak_bw_v1,
+ .set_dram_hrt_bw = dvfsrc_set_dram_hrt_bw_v1,
+ .set_vcore_level = dvfsrc_set_vcore_level_v2,
+ .set_vscp_level = dvfsrc_set_vscp_level_v2,
+ .wait_for_opp_level = dvfsrc_wait_for_opp_level_v2,
+ .wait_for_vcore_level = dvfsrc_wait_for_vcore_level_v1,
+ .bw_constraints = &dvfsrc_bw_constr_v2,
+};
+
+static const struct of_device_id mtk_dvfsrc_of_match[] = {
+ { .compatible = "mediatek,mt6893-dvfsrc", .data = &mt6893_data },
+ { .compatible = "mediatek,mt8183-dvfsrc", .data = &mt8183_data },
+ { .compatible = "mediatek,mt8195-dvfsrc", .data = &mt8195_data },
+ { /* sentinel */ }
+};
+
+static struct platform_driver mtk_dvfsrc_driver = {
+ .probe = mtk_dvfsrc_probe,
+ .driver = {
+ .name = "mtk-dvfsrc",
+ .of_match_table = mtk_dvfsrc_of_match,
+ },
+};
+module_platform_driver(mtk_dvfsrc_driver);
+
+MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
+MODULE_AUTHOR("Dawei Chien <dawei.chien@mediatek.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek DVFSRC driver");
diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
index f370f4ec4b88..bb4639ca0b8c 100644
--- a/drivers/soc/mediatek/mtk-mmsys.c
+++ b/drivers/soc/mediatek/mtk-mmsys.c
@@ -236,6 +236,7 @@ void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_ALPHA + (idx - 1) * 4, ~0,
alpha << 16 | alpha, cmdq_pkt);
+ mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(15 + idx), 0, cmdq_pkt);
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_HDR_TOP_CFG, BIT(19 + idx),
alpha_sel << (19 + idx), cmdq_pkt);
mtk_mmsys_update_bits(mmsys, MT8195_VDO1_MIXER_IN1_PAD + (idx - 1) * 4,
@@ -486,7 +487,7 @@ static struct platform_driver mtk_mmsys_drv = {
.of_match_table = of_match_mtk_mmsys,
},
.probe = mtk_mmsys_probe,
- .remove_new = mtk_mmsys_remove,
+ .remove = mtk_mmsys_remove,
};
module_platform_driver(mtk_mmsys_drv);
diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h
index d370192737ca..fe628d5f5198 100644
--- a/drivers/soc/mediatek/mtk-mmsys.h
+++ b/drivers/soc/mediatek/mtk-mmsys.h
@@ -80,6 +80,20 @@
#define MMSYS_RST_NR(bank, bit) (((bank) * 32) + (bit))
+/*
+ * This macro adds a compile time check to make sure that the in/out
+ * selection bit(s) fit in the register mask, similar to bitfield
+ * macros, but this does not transform the value.
+ */
+#define MMSYS_ROUTE(from, to, reg_addr, reg_mask, selection) \
+ { DDP_COMPONENT_##from, DDP_COMPONENT_##to, reg_addr, reg_mask, \
+ (__BUILD_BUG_ON_ZERO_MSG((reg_mask) == 0, "Invalid mask") + \
+ __BUILD_BUG_ON_ZERO_MSG(~(reg_mask) & (selection), \
+ #selection " does not fit in " \
+ #reg_mask) + \
+ (selection)) \
+ }
+
struct mtk_mmsys_routes {
u32 from_comp;
u32 to_comp;
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 73c256d3950b..aaa965d4b050 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -155,6 +155,7 @@
#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE3 23
#define MT8188_MUTEX_MOD_DISP1_VPP_MERGE4 24
#define MT8188_MUTEX_MOD_DISP1_DISP_MIXER 30
+#define MT8188_MUTEX_MOD_DISP1_DPI1 38
#define MT8188_MUTEX_MOD_DISP1_DP_INTF1 39
#define MT8195_MUTEX_MOD_DISP_OVL0 0
@@ -289,6 +290,7 @@
#define MT8188_MUTEX_SOF_DSI0 1
#define MT8188_MUTEX_SOF_DP_INTF0 3
#define MT8188_MUTEX_SOF_DP_INTF1 4
+#define MT8188_MUTEX_SOF_DPI1 5
#define MT8195_MUTEX_SOF_DSI0 1
#define MT8195_MUTEX_SOF_DSI1 2
#define MT8195_MUTEX_SOF_DP_INTF0 3
@@ -301,6 +303,7 @@
#define MT8188_MUTEX_EOF_DSI0 (MT8188_MUTEX_SOF_DSI0 << 7)
#define MT8188_MUTEX_EOF_DP_INTF0 (MT8188_MUTEX_SOF_DP_INTF0 << 7)
#define MT8188_MUTEX_EOF_DP_INTF1 (MT8188_MUTEX_SOF_DP_INTF1 << 7)
+#define MT8188_MUTEX_EOF_DPI1 (MT8188_MUTEX_SOF_DPI1 << 7)
#define MT8195_MUTEX_EOF_DSI0 (MT8195_MUTEX_SOF_DSI0 << 7)
#define MT8195_MUTEX_EOF_DSI1 (MT8195_MUTEX_SOF_DSI1 << 7)
#define MT8195_MUTEX_EOF_DP_INTF0 (MT8195_MUTEX_SOF_DP_INTF0 << 7)
@@ -327,11 +330,11 @@ enum mtk_mutex_sof_id {
};
struct mtk_mutex_data {
- const unsigned int *mutex_mod;
- const unsigned int *mutex_sof;
- const unsigned int mutex_mod_reg;
- const unsigned int mutex_sof_reg;
- const unsigned int *mutex_table_mod;
+ const u8 *mutex_mod;
+ const u8 *mutex_table_mod;
+ const u16 *mutex_sof;
+ const u16 mutex_mod_reg;
+ const u16 mutex_sof_reg;
const bool no_clk;
};
@@ -345,7 +348,7 @@ struct mtk_mutex_ctx {
struct cmdq_client_reg cmdq_reg;
};
-static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
[DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
[DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
@@ -354,7 +357,7 @@ static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
};
-static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
[DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
@@ -374,7 +377,7 @@ static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
};
-static const unsigned int mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8167_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_CCORR] = MT8167_MUTEX_MOD_DISP_CCORR,
[DDP_COMPONENT_COLOR0] = MT8167_MUTEX_MOD_DISP_COLOR,
@@ -389,7 +392,7 @@ static const unsigned int mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8167_MUTEX_MOD_DISP_WDMA0,
};
-static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
[DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
@@ -407,7 +410,7 @@ static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
};
-static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8183_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8183_MUTEX_MOD_DISP_CCORR0,
[DDP_COMPONENT_COLOR0] = MT8183_MUTEX_MOD_DISP_COLOR0,
@@ -421,7 +424,7 @@ static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0,
};
-static const unsigned int mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8183_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RSZ0] = MT8183_MUTEX_MOD_MDP_RSZ0,
[MUTEX_MOD_IDX_MDP_RSZ1] = MT8183_MUTEX_MOD_MDP_RSZ1,
@@ -432,7 +435,7 @@ static const unsigned int mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_CCORR0] = MT8183_MUTEX_MOD_MDP_CCORR0,
};
-static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8186_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8186_MUTEX_MOD_DISP_CCORR0,
[DDP_COMPONENT_COLOR0] = MT8186_MUTEX_MOD_DISP_COLOR0,
@@ -445,7 +448,7 @@ static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1,
};
-static const unsigned int mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8186_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RSZ0] = MT8186_MUTEX_MOD_MDP_RSZ0,
[MUTEX_MOD_IDX_MDP_RSZ1] = MT8186_MUTEX_MOD_MDP_RSZ1,
@@ -456,7 +459,7 @@ static const unsigned int mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_COLOR0] = MT8186_MUTEX_MOD_MDP_COLOR0,
};
-static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_OVL0] = MT8188_MUTEX_MOD_DISP_OVL0,
[DDP_COMPONENT_WDMA0] = MT8188_MUTEX_MOD_DISP_WDMA0,
[DDP_COMPONENT_RDMA0] = MT8188_MUTEX_MOD_DISP_RDMA0,
@@ -472,6 +475,7 @@ static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_PWM0] = MT8188_MUTEX_MOD2_DISP_PWM0,
[DDP_COMPONENT_DP_INTF0] = MT8188_MUTEX_MOD_DISP_DP_INTF0,
[DDP_COMPONENT_DP_INTF1] = MT8188_MUTEX_MOD_DISP1_DP_INTF1,
+ [DDP_COMPONENT_DPI1] = MT8188_MUTEX_MOD_DISP1_DPI1,
[DDP_COMPONENT_ETHDR_MIXER] = MT8188_MUTEX_MOD_DISP1_DISP_MIXER,
[DDP_COMPONENT_MDP_RDMA0] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA0,
[DDP_COMPONENT_MDP_RDMA1] = MT8188_MUTEX_MOD_DISP1_MDP_RDMA1,
@@ -496,7 +500,41 @@ static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_MERGE5] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE4,
};
-static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+ [MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0,
+ [MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2,
+ [MUTEX_MOD_IDX_MDP_RDMA3] = MT8195_MUTEX_MOD_MDP_RDMA3,
+ [MUTEX_MOD_IDX_MDP_FG0] = MT8195_MUTEX_MOD_MDP_FG0,
+ [MUTEX_MOD_IDX_MDP_FG2] = MT8195_MUTEX_MOD_MDP_FG2,
+ [MUTEX_MOD_IDX_MDP_FG3] = MT8195_MUTEX_MOD_MDP_FG3,
+ [MUTEX_MOD_IDX_MDP_HDR0] = MT8195_MUTEX_MOD_MDP_HDR0,
+ [MUTEX_MOD_IDX_MDP_HDR2] = MT8195_MUTEX_MOD_MDP_HDR2,
+ [MUTEX_MOD_IDX_MDP_HDR3] = MT8195_MUTEX_MOD_MDP_HDR3,
+ [MUTEX_MOD_IDX_MDP_AAL0] = MT8195_MUTEX_MOD_MDP_AAL0,
+ [MUTEX_MOD_IDX_MDP_AAL2] = MT8195_MUTEX_MOD_MDP_AAL2,
+ [MUTEX_MOD_IDX_MDP_AAL3] = MT8195_MUTEX_MOD_MDP_AAL3,
+ [MUTEX_MOD_IDX_MDP_RSZ0] = MT8195_MUTEX_MOD_MDP_RSZ0,
+ [MUTEX_MOD_IDX_MDP_RSZ2] = MT8195_MUTEX_MOD_MDP_RSZ2,
+ [MUTEX_MOD_IDX_MDP_RSZ3] = MT8195_MUTEX_MOD_MDP_RSZ3,
+ [MUTEX_MOD_IDX_MDP_MERGE2] = MT8195_MUTEX_MOD_MDP_MERGE2,
+ [MUTEX_MOD_IDX_MDP_MERGE3] = MT8195_MUTEX_MOD_MDP_MERGE3,
+ [MUTEX_MOD_IDX_MDP_TDSHP0] = MT8195_MUTEX_MOD_MDP_TDSHP0,
+ [MUTEX_MOD_IDX_MDP_TDSHP2] = MT8195_MUTEX_MOD_MDP_TDSHP2,
+ [MUTEX_MOD_IDX_MDP_TDSHP3] = MT8195_MUTEX_MOD_MDP_TDSHP3,
+ [MUTEX_MOD_IDX_MDP_COLOR0] = MT8195_MUTEX_MOD_MDP_COLOR0,
+ [MUTEX_MOD_IDX_MDP_COLOR2] = MT8195_MUTEX_MOD_MDP_COLOR2,
+ [MUTEX_MOD_IDX_MDP_COLOR3] = MT8195_MUTEX_MOD_MDP_COLOR3,
+ [MUTEX_MOD_IDX_MDP_OVL0] = MT8195_MUTEX_MOD_MDP_OVL0,
+ [MUTEX_MOD_IDX_MDP_PAD0] = MT8195_MUTEX_MOD_MDP_PAD0,
+ [MUTEX_MOD_IDX_MDP_PAD2] = MT8195_MUTEX_MOD_MDP_PAD2,
+ [MUTEX_MOD_IDX_MDP_PAD3] = MT8195_MUTEX_MOD_MDP_PAD3,
+ [MUTEX_MOD_IDX_MDP_TCC0] = MT8195_MUTEX_MOD_MDP_TCC0,
+ [MUTEX_MOD_IDX_MDP_WROT0] = MT8195_MUTEX_MOD_MDP_WROT0,
+ [MUTEX_MOD_IDX_MDP_WROT2] = MT8195_MUTEX_MOD_MDP_WROT2,
+ [MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
+};
+
+static const u8 mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0,
[DDP_COMPONENT_COLOR0] = MT8192_MUTEX_MOD_DISP_COLOR0,
@@ -510,7 +548,7 @@ static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_RDMA4] = MT8192_MUTEX_MOD_DISP_RDMA4,
};
-static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_OVL0] = MT8195_MUTEX_MOD_DISP_OVL0,
[DDP_COMPONENT_WDMA0] = MT8195_MUTEX_MOD_DISP_WDMA0,
[DDP_COMPONENT_RDMA0] = MT8195_MUTEX_MOD_DISP_RDMA0,
@@ -541,7 +579,7 @@ static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_DP_INTF1] = MT8195_MUTEX_MOD_DISP1_DP_INTF0,
};
-static const unsigned int mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RDMA1] = MT8195_MUTEX_MOD_MDP_RDMA1,
[MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2,
@@ -587,7 +625,7 @@ static const unsigned int mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
};
-static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
[DDP_COMPONENT_COLOR0] = MT8365_MUTEX_MOD_DISP_COLOR0,
@@ -603,7 +641,7 @@ static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8365_MUTEX_MOD_DISP_WDMA0,
};
-static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
[MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
@@ -613,14 +651,14 @@ static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
};
-static const unsigned int mt6795_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt6795_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
[MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
[MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
};
-static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
[MUTEX_SOF_DPI0] = MT8167_MUTEX_SOF_DPI0,
@@ -628,13 +666,13 @@ static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
};
/* Add EOF setting so overlay hardware can receive frame done irq */
-static const unsigned int mt8183_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8183_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0 | MT8183_MUTEX_EOF_DSI0,
[MUTEX_SOF_DPI0] = MT8183_MUTEX_SOF_DPI0 | MT8183_MUTEX_EOF_DPI0,
};
-static const unsigned int mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
+static const u16 mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MT8186_MUTEX_SOF_DSI0 | MT8186_MUTEX_EOF_DSI0,
[MUTEX_SOF_DPI0] = MT8186_MUTEX_SOF_DPI0 | MT8186_MUTEX_EOF_DPI0,
@@ -648,17 +686,19 @@ static const unsigned int mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
* but also detect the error at end of frame(EAEOF) when EOF signal
* arrives.
*/
-static const unsigned int mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] =
MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0,
+ [MUTEX_SOF_DPI1] =
+ MT8188_MUTEX_SOF_DPI1 | MT8188_MUTEX_EOF_DPI1,
[MUTEX_SOF_DP_INTF0] =
MT8188_MUTEX_SOF_DP_INTF0 | MT8188_MUTEX_EOF_DP_INTF0,
[MUTEX_SOF_DP_INTF1] =
MT8188_MUTEX_SOF_DP_INTF1 | MT8188_MUTEX_EOF_DP_INTF1,
};
-static const unsigned int mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MT8195_MUTEX_SOF_DSI0 | MT8195_MUTEX_EOF_DSI0,
[MUTEX_SOF_DSI1] = MT8195_MUTEX_SOF_DSI1 | MT8195_MUTEX_EOF_DSI1,
@@ -735,6 +775,13 @@ static const struct mtk_mutex_data mt8188_mutex_driver_data = {
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
};
+static const struct mtk_mutex_data mt8188_vpp_mutex_driver_data = {
+ .mutex_sof = mt8188_mutex_sof,
+ .mutex_mod_reg = MT8183_MUTEX0_MOD0,
+ .mutex_sof_reg = MT8183_MUTEX0_SOF0,
+ .mutex_table_mod = mt8188_mdp_mutex_table_mod,
+};
+
static const struct mtk_mutex_data mt8192_mutex_driver_data = {
.mutex_mod = mt8192_mutex_mod,
.mutex_sof = mt8183_mutex_sof,
@@ -1089,6 +1136,7 @@ static const struct of_device_id mutex_driver_dt_match[] = {
{ .compatible = "mediatek,mt8186-disp-mutex", .data = &mt8186_mutex_driver_data },
{ .compatible = "mediatek,mt8186-mdp3-mutex", .data = &mt8186_mdp_mutex_driver_data },
{ .compatible = "mediatek,mt8188-disp-mutex", .data = &mt8188_mutex_driver_data },
+ { .compatible = "mediatek,mt8188-vpp-mutex", .data = &mt8188_vpp_mutex_driver_data },
{ .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data },
{ .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data },
{ .compatible = "mediatek,mt8195-vpp-mutex", .data = &mt8195_vpp_mutex_driver_data },
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index efd9cae212dc..0bcd85826375 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -483,7 +483,7 @@ enum pwrap_regs {
PWRAP_MSB_FIRST,
};
-static int mt2701_regs[] = {
+static const int mt2701_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -569,7 +569,7 @@ static int mt2701_regs[] = {
[PWRAP_ADC_RDATA_ADDR2] = 0x154,
};
-static int mt6765_regs[] = {
+static const int mt6765_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -601,7 +601,7 @@ static int mt6765_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x1E0,
};
-static int mt6779_regs[] = {
+static const int mt6779_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -640,7 +640,7 @@ static int mt6779_regs[] = {
[PWRAP_WACS2_VLDCLR] = 0xC28,
};
-static int mt6795_regs[] = {
+static const int mt6795_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -725,7 +725,7 @@ static int mt6795_regs[] = {
[PWRAP_EXT_CK] = 0x14c,
};
-static int mt6797_regs[] = {
+static const int mt6797_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -758,7 +758,7 @@ static int mt6797_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x1D4,
};
-static int mt6873_regs[] = {
+static const int mt6873_regs[] = {
[PWRAP_INIT_DONE2] = 0x0,
[PWRAP_TIMER_EN] = 0x3E0,
[PWRAP_INT_EN] = 0x448,
@@ -769,7 +769,7 @@ static int mt6873_regs[] = {
[PWRAP_WACS2_RDATA] = 0xCA8,
};
-static int mt7622_regs[] = {
+static const int mt7622_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -881,7 +881,7 @@ static int mt7622_regs[] = {
[PWRAP_SPI2_CTRL] = 0x244,
};
-static int mt8135_regs[] = {
+static const int mt8135_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -954,7 +954,7 @@ static int mt8135_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x160,
};
-static int mt8173_regs[] = {
+static const int mt8173_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1036,7 +1036,7 @@ static int mt8173_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x148,
};
-static int mt8183_regs[] = {
+static const int mt8183_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1087,7 +1087,7 @@ static int mt8183_regs[] = {
[PWRAP_WACS2_VLDCLR] = 0xC28,
};
-static int mt8195_regs[] = {
+static const int mt8195_regs[] = {
[PWRAP_INIT_DONE2] = 0x0,
[PWRAP_STAUPD_CTRL] = 0x4C,
[PWRAP_TIMER_EN] = 0x3E4,
@@ -1104,7 +1104,7 @@ static int mt8195_regs[] = {
[PWRAP_WACS2_RDATA] = 0x8A8,
};
-static int mt8365_regs[] = {
+static const int mt8365_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1166,7 +1166,7 @@ static int mt8365_regs[] = {
[PWRAP_WDT_SRC_EN_1] = 0xf8,
};
-static int mt8516_regs[] = {
+static const int mt8516_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1251,7 +1251,7 @@ static int mt8516_regs[] = {
[PWRAP_MSB_FIRST] = 0x170,
};
-static int mt8186_regs[] = {
+static const int mt8186_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1366,10 +1366,6 @@ struct pmic_wrapper {
struct regmap *regmap;
const struct pmic_wrapper_type *master;
const struct pwrap_slv_type *slave;
- struct clk *clk_spi;
- struct clk *clk_wrap;
- struct clk *clk_sys;
- struct clk *clk_tmr;
struct reset_control *rstc;
struct reset_control *rstc_bridge;
@@ -1377,7 +1373,7 @@ struct pmic_wrapper {
};
struct pmic_wrapper_type {
- int *regs;
+ const int *regs;
enum pwrap_type type;
u32 arb_en_all;
u32 int_en_all;
@@ -2397,7 +2393,7 @@ static const struct pmic_wrapper_type pwrap_mt8183 = {
.init_soc_specific = pwrap_mt8183_init_soc_specific,
};
-static struct pmic_wrapper_type pwrap_mt8195 = {
+static const struct pmic_wrapper_type pwrap_mt8195 = {
.regs = mt8195_regs,
.type = PWRAP_MT8195,
.arb_en_all = 0x777f, /* NEED CONFIRM */
@@ -2423,7 +2419,7 @@ static const struct pmic_wrapper_type pwrap_mt8365 = {
.init_soc_specific = NULL,
};
-static struct pmic_wrapper_type pwrap_mt8516 = {
+static const struct pmic_wrapper_type pwrap_mt8516 = {
.regs = mt8516_regs,
.type = PWRAP_MT8516,
.arb_en_all = 0xff,
@@ -2435,7 +2431,7 @@ static struct pmic_wrapper_type pwrap_mt8516 = {
.init_soc_specific = NULL,
};
-static struct pmic_wrapper_type pwrap_mt8186 = {
+static const struct pmic_wrapper_type pwrap_mt8186 = {
.regs = mt8186_regs,
.type = PWRAP_MT8186,
.arb_en_all = 0xfb27f,
@@ -2472,6 +2468,7 @@ static int pwrap_probe(struct platform_device *pdev)
int ret, irq;
u32 mask_done;
struct pmic_wrapper *wrp;
+ struct clk_bulk_data *clk;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_slave_id = NULL;
@@ -2521,49 +2518,10 @@ static int pwrap_probe(struct platform_device *pdev)
}
}
- wrp->clk_spi = devm_clk_get(wrp->dev, "spi");
- if (IS_ERR(wrp->clk_spi)) {
- dev_dbg(wrp->dev, "failed to get clock: %ld\n",
- PTR_ERR(wrp->clk_spi));
- return PTR_ERR(wrp->clk_spi);
- }
-
- wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap");
- if (IS_ERR(wrp->clk_wrap)) {
- dev_dbg(wrp->dev, "failed to get clock: %ld\n",
- PTR_ERR(wrp->clk_wrap));
- return PTR_ERR(wrp->clk_wrap);
- }
-
- wrp->clk_sys = devm_clk_get_optional(wrp->dev, "sys");
- if (IS_ERR(wrp->clk_sys)) {
- return dev_err_probe(wrp->dev, PTR_ERR(wrp->clk_sys),
- "failed to get clock: %pe\n",
- wrp->clk_sys);
- }
-
- wrp->clk_tmr = devm_clk_get_optional(wrp->dev, "tmr");
- if (IS_ERR(wrp->clk_tmr)) {
- return dev_err_probe(wrp->dev, PTR_ERR(wrp->clk_tmr),
- "failed to get clock: %pe\n",
- wrp->clk_tmr);
- }
-
- ret = clk_prepare_enable(wrp->clk_spi);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(wrp->clk_wrap);
- if (ret)
- goto err_out1;
-
- ret = clk_prepare_enable(wrp->clk_sys);
- if (ret)
- goto err_out2;
-
- ret = clk_prepare_enable(wrp->clk_tmr);
- if (ret)
- goto err_out3;
+ ret = devm_clk_bulk_get_all_enabled(wrp->dev, &clk);
+ if (ret < 0)
+ return dev_err_probe(wrp->dev, ret,
+ "failed to get clocks\n");
/* Enable internal dynamic clock */
if (HAS_CAP(wrp->master->caps, PWRAP_CAP_DCM)) {
@@ -2579,7 +2537,7 @@ static int pwrap_probe(struct platform_device *pdev)
ret = pwrap_init(wrp);
if (ret) {
dev_dbg(wrp->dev, "init failed with %d\n", ret);
- goto err_out4;
+ return ret;
}
}
@@ -2592,8 +2550,7 @@ static int pwrap_probe(struct platform_device *pdev)
if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & mask_done)) {
dev_dbg(wrp->dev, "initialization isn't finished\n");
- ret = -ENODEV;
- goto err_out4;
+ return -ENODEV;
}
/* Initialize watchdog, may not be done by the bootloader */
@@ -2622,42 +2579,27 @@ static int pwrap_probe(struct platform_device *pdev)
pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- ret = irq;
- goto err_out2;
- }
+ if (irq < 0)
+ return irq;
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt,
IRQF_TRIGGER_HIGH,
"mt-pmic-pwrap", wrp);
if (ret)
- goto err_out4;
+ return ret;
wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regops->regmap);
- if (IS_ERR(wrp->regmap)) {
- ret = PTR_ERR(wrp->regmap);
- goto err_out2;
- }
+ if (IS_ERR(wrp->regmap))
+ return PTR_ERR(wrp->regmap);
ret = of_platform_populate(np, NULL, NULL, wrp->dev);
if (ret) {
dev_dbg(wrp->dev, "failed to create child devices at %pOF\n",
np);
- goto err_out4;
+ return ret;
}
return 0;
-
-err_out4:
- clk_disable_unprepare(wrp->clk_tmr);
-err_out3:
- clk_disable_unprepare(wrp->clk_sys);
-err_out2:
- clk_disable_unprepare(wrp->clk_wrap);
-err_out1:
- clk_disable_unprepare(wrp->clk_spi);
-
- return ret;
}
static struct platform_driver pwrap_drv = {
diff --git a/drivers/soc/mediatek/mtk-regulator-coupler.c b/drivers/soc/mediatek/mtk-regulator-coupler.c
index ad2ed42aa697..0b6a2884145e 100644
--- a/drivers/soc/mediatek/mtk-regulator-coupler.c
+++ b/drivers/soc/mediatek/mtk-regulator-coupler.c
@@ -147,6 +147,7 @@ static int mediatek_regulator_coupler_init(void)
{
if (!of_machine_is_compatible("mediatek,mt8183") &&
!of_machine_is_compatible("mediatek,mt8186") &&
+ !of_machine_is_compatible("mediatek,mt8188") &&
!of_machine_is_compatible("mediatek,mt8192"))
return 0;
diff --git a/drivers/soc/mediatek/mtk-socinfo.c b/drivers/soc/mediatek/mtk-socinfo.c
index 42572e8c1520..c697a0398d91 100644
--- a/drivers/soc/mediatek/mtk-socinfo.c
+++ b/drivers/soc/mediatek/mtk-socinfo.c
@@ -48,36 +48,47 @@ static struct socinfo_data socinfo_data_table[] = {
MTK_SOCINFO_ENTRY("MT8183", "MT8183V/AZA", "Kompanio 500", 0x00010043, 0x00000940),
MTK_SOCINFO_ENTRY("MT8186", "MT8186GV/AZA", "Kompanio 520", 0x81861001, CELL_NOT_USED),
MTK_SOCINFO_ENTRY("MT8186T", "MT8186TV/AZA", "Kompanio 528", 0x81862001, CELL_NOT_USED),
- MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/AZA", "Kompanio 830", 0x81880000, 0x00000010),
- MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/HZA", "Kompanio 830", 0x81880000, 0x00000011),
+ MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/AZA", "Kompanio 838", 0x81880000, 0x00000010),
+ MTK_SOCINFO_ENTRY("MT8188", "MT8188GV/HZA", "Kompanio 838", 0x81880000, 0x00000011),
MTK_SOCINFO_ENTRY("MT8192", "MT8192V/AZA", "Kompanio 820", 0x00001100, 0x00040080),
MTK_SOCINFO_ENTRY("MT8192T", "MT8192V/ATZA", "Kompanio 828", 0x00000100, 0x000400C0),
MTK_SOCINFO_ENTRY("MT8195", "MT8195GV/EZA", "Kompanio 1200", 0x81950300, CELL_NOT_USED),
MTK_SOCINFO_ENTRY("MT8195", "MT8195GV/EHZA", "Kompanio 1200", 0x81950304, CELL_NOT_USED),
MTK_SOCINFO_ENTRY("MT8195", "MT8195TV/EZA", "Kompanio 1380", 0x81950400, CELL_NOT_USED),
MTK_SOCINFO_ENTRY("MT8195", "MT8195TV/EHZA", "Kompanio 1380", 0x81950404, CELL_NOT_USED),
+ MTK_SOCINFO_ENTRY("MT8370", "MT8370AV/AZA", "Genio 510", 0x83700000, 0x00000081),
+ MTK_SOCINFO_ENTRY("MT8390", "MT8390AV/AZA", "Genio 700", 0x83900000, 0x00000080),
+ MTK_SOCINFO_ENTRY("MT8395", "MT8395AV/ZA", "Genio 1200", 0x83950100, CELL_NOT_USED),
+ MTK_SOCINFO_ENTRY("MT8395", "MT8395AV/ZA", "Genio 1200", 0x83950800, CELL_NOT_USED),
};
static int mtk_socinfo_create_socinfo_node(struct mtk_socinfo *mtk_socinfop)
{
struct soc_device_attribute *attrs;
- static char machine[30] = {0};
+ struct socinfo_data *data = mtk_socinfop->socinfo_data;
static const char *soc_manufacturer = "MediaTek";
attrs = devm_kzalloc(mtk_socinfop->dev, sizeof(*attrs), GFP_KERNEL);
if (!attrs)
return -ENOMEM;
- snprintf(machine, sizeof(machine), "%s (%s)", mtk_socinfop->socinfo_data->marketing_name,
- mtk_socinfop->socinfo_data->soc_name);
- attrs->family = soc_manufacturer;
- attrs->machine = machine;
+ if (data->marketing_name != NULL && data->marketing_name[0] != '\0')
+ attrs->family = devm_kasprintf(mtk_socinfop->dev, GFP_KERNEL, "MediaTek %s",
+ data->marketing_name);
+ else
+ attrs->family = soc_manufacturer;
+
+ attrs->soc_id = data->soc_name;
+ /*
+ * The "machine" field will be populated automatically with the model
+ * name from board DTS (if available).
+ **/
mtk_socinfop->soc_dev = soc_device_register(attrs);
if (IS_ERR(mtk_socinfop->soc_dev))
return PTR_ERR(mtk_socinfop->soc_dev);
- dev_info(mtk_socinfop->dev, "%s %s SoC detected.\n", soc_manufacturer, attrs->machine);
+ dev_info(mtk_socinfop->dev, "%s (%s) SoC detected.\n", attrs->family, attrs->soc_id);
return 0;
}
@@ -144,7 +155,14 @@ static int mtk_socinfo_get_socinfo_data(struct mtk_socinfo *mtk_socinfop)
}
}
- return match_socinfo_index >= 0 ? match_socinfo_index : -ENOENT;
+ if (match_socinfo_index < 0) {
+ dev_warn(mtk_socinfop->dev,
+ "Unknown MediaTek SoC with ID 0x%08x 0x%08x\n",
+ cell_data[0], cell_data[1]);
+ return -ENOENT;
+ }
+
+ return match_socinfo_index;
}
static int mtk_socinfo_probe(struct platform_device *pdev)
@@ -179,7 +197,7 @@ static void mtk_socinfo_remove(struct platform_device *pdev)
static struct platform_driver mtk_socinfo = {
.probe = mtk_socinfo_probe,
- .remove_new = mtk_socinfo_remove,
+ .remove = mtk_socinfo_remove,
.driver = {
.name = "mtk-socinfo",
},
diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c
index 9a91298c1253..7c349a94b45c 100644
--- a/drivers/soc/mediatek/mtk-svs.c
+++ b/drivers/soc/mediatek/mtk-svs.c
@@ -2133,14 +2133,12 @@ static struct device *svs_get_subsys_device(struct svs_platform *svsp,
}
pdev = of_find_device_by_node(np);
+ of_node_put(np);
if (!pdev) {
- of_node_put(np);
dev_err(svsp->dev, "cannot find pdev by %s\n", node_name);
return ERR_PTR(-ENXIO);
}
- of_node_put(np);
-
return &pdev->dev;
}
diff --git a/drivers/soc/microchip/mpfs-sys-controller.c b/drivers/soc/microchip/mpfs-sys-controller.c
index 7a4936019329..30bc45d17d34 100644
--- a/drivers/soc/microchip/mpfs-sys-controller.c
+++ b/drivers/soc/microchip/mpfs-sys-controller.c
@@ -232,7 +232,7 @@ static struct platform_driver mpfs_sys_controller_driver = {
.of_match_table = mpfs_sys_controller_of_match,
},
.probe = mpfs_sys_controller_probe,
- .remove_new = mpfs_sys_controller_remove,
+ .remove = mpfs_sys_controller_remove,
};
module_platform_driver(mpfs_sys_controller_driver);
diff --git a/drivers/soc/pxa/ssp.c b/drivers/soc/pxa/ssp.c
index 7af04e8b8163..bb0062c165fe 100644
--- a/drivers/soc/pxa/ssp.c
+++ b/drivers/soc/pxa/ssp.c
@@ -25,7 +25,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/spi/pxa2xx_spi.h>
+#include <linux/pxa2xx_ssp.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -197,7 +197,7 @@ static const struct platform_device_id ssp_id_table[] = {
static struct platform_driver pxa_ssp_driver = {
.probe = pxa_ssp_probe,
- .remove_new = pxa_ssp_remove,
+ .remove = pxa_ssp_remove,
.driver = {
.name = "pxa2xx-ssp",
.of_match_table = of_match_ptr(pxa_ssp_of_ids),
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 5af33b0e3470..58e63cf0036b 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -72,11 +72,28 @@ config QCOM_OCMEM
requirements. This is typically used by the GPU, camera/video, and
audio components on some Snapdragon SoCs.
+config QCOM_PD_MAPPER
+ tristate "Qualcomm Protection Domain Mapper"
+ select QCOM_QMI_HELPERS
+ select QCOM_PDR_MSG
+ select AUXILIARY_BUS
+ depends on NET && QRTR && (ARCH_QCOM || COMPILE_TEST)
+ default QCOM_RPROC_COMMON
+ help
+ The Protection Domain Mapper maps registered services to the domains
+ and instances handled by the remote DSPs. This is a kernel-space
+ implementation of the service. It is a simpler alternative to the
+ userspace daemon.
+
config QCOM_PDR_HELPERS
tristate
select QCOM_QMI_HELPERS
+ select QCOM_PDR_MSG
depends on NET
+config QCOM_PDR_MSG
+ tristate
+
config QCOM_PMIC_PDCHARGER_ULOG
tristate "Qualcomm PMIC PDCharger ULOG driver"
depends on RPMSG
@@ -122,7 +139,7 @@ config QCOM_RAMP_CTRL
config QCOM_RMTFS_MEM
tristate "Qualcomm Remote Filesystem memory driver"
- depends on ARCH_QCOM
+ depends on ARCH_QCOM || COMPILE_TEST
select QCOM_SCM
help
The Qualcomm remote filesystem memory driver is used for allocating
@@ -194,6 +211,7 @@ config QCOM_SMP2P
config QCOM_SMSM
tristate "Qualcomm Shared Memory State Machine"
+ depends on MAILBOX
depends on QCOM_SMEM
select QCOM_SMEM_STATE
select IRQ_DOMAIN
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index ca0bece0dfff..acbca2ab5cc2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -7,7 +7,9 @@ obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
+obj-$(CONFIG_QCOM_PD_MAPPER) += qcom_pd_mapper.o
obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
+obj-$(CONFIG_QCOM_PDR_MSG) += qcom_pdr_msg.o
obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
@@ -23,6 +25,7 @@ qcom_rpmh-y += rpmh.o
obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o
obj-$(CONFIG_QCOM_SMEM) += smem.o
obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
+CFLAGS_smp2p.o := -I$(src)
obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o
diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
index 50749e870efa..a956c407ce03 100644
--- a/drivers/soc/qcom/apr.c
+++ b/drivers/soc/qcom/apr.c
@@ -338,10 +338,10 @@ static void apr_rxwq(struct work_struct *work)
}
}
-static int apr_device_match(struct device *dev, struct device_driver *drv)
+static int apr_device_match(struct device *dev, const struct device_driver *drv)
{
struct apr_device *adev = to_apr_device(dev);
- struct apr_driver *adrv = to_apr_driver(drv);
+ const struct apr_driver *adrv = to_apr_driver(drv);
const struct apr_device_id *id = adrv->id_table;
/* Attempt an OF style match first */
@@ -485,11 +485,10 @@ static int of_apr_add_pd_lookups(struct device *dev)
{
const char *service_name, *service_path;
struct packet_router *apr = dev_get_drvdata(dev);
- struct device_node *node;
struct pdr_service *pds;
int ret;
- for_each_child_of_node(dev->of_node, node) {
+ for_each_child_of_node_scoped(dev->of_node, node) {
ret = of_property_read_string_index(node, "qcom,protection-domain",
0, &service_name);
if (ret < 0)
@@ -499,14 +498,12 @@ static int of_apr_add_pd_lookups(struct device *dev)
1, &service_path);
if (ret < 0) {
dev_err(dev, "pdr service path missing: %d\n", ret);
- of_node_put(node);
return ret;
}
pds = pdr_add_lookup(apr->pdr, service_name, service_path);
if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds));
- of_node_put(node);
return PTR_ERR(pds);
}
}
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index a5fd68411bed..ae66c2623d25 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -1,6 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved. */
+/*
+ * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -17,6 +21,8 @@
#define MAX_SLV_ID 8
#define SLAVE_ID_MASK 0x7
#define SLAVE_ID_SHIFT 16
+#define SLAVE_ID(addr) FIELD_GET(GENMASK(19, 16), addr)
+#define VRM_ADDR(addr) FIELD_GET(GENMASK(19, 4), addr)
/**
* struct entry_header: header for each entry in cmddb
@@ -147,12 +153,7 @@ static int cmd_db_get_header(const char *id, const struct entry_header **eh,
if (ret)
return ret;
- /*
- * Pad out query string to same length as in DB. NOTE: the output
- * query string is not necessarily '\0' terminated if it bumps up
- * against the max size. That's OK and expected.
- */
- strncpy(query, id, sizeof(query));
+ strtomem_pad(query, id, 0);
for (i = 0; i < MAX_SLV_ID; i++) {
rsc_hdr = &cmd_db_header->header[i];
@@ -221,6 +222,30 @@ const void *cmd_db_read_aux_data(const char *id, size_t *len)
EXPORT_SYMBOL_GPL(cmd_db_read_aux_data);
/**
+ * cmd_db_match_resource_addr() - Compare if both Resource addresses are same
+ *
+ * @addr1: Resource address to compare
+ * @addr2: Resource address to compare
+ *
+ * Return: true if two addresses refer to the same resource, false otherwise
+ */
+bool cmd_db_match_resource_addr(u32 addr1, u32 addr2)
+{
+ /*
+ * Each RPMh VRM accelerator resource has 3 or 4 contiguous 4-byte
+ * aligned addresses associated with it. Ignore the offset to check
+ * for VRM requests.
+ */
+ if (addr1 == addr2)
+ return true;
+ else if (SLAVE_ID(addr1) == CMD_DB_HW_VRM && VRM_ADDR(addr1) == VRM_ADDR(addr2))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(cmd_db_match_resource_addr);
+
+/**
* cmd_db_read_slave_id - Get the slave ID for a given resource address
*
* @id: Resource id to query the DB for version
@@ -324,7 +349,7 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
return -EINVAL;
}
- cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
+ cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WC);
if (!cmd_db_header) {
ret = -ENOMEM;
cmd_db_header = NULL;
@@ -362,7 +387,7 @@ static int __init cmd_db_device_init(void)
{
return platform_driver_register(&cmd_db_dev_driver);
}
-arch_initcall(cmd_db_device_init);
+core_initcall(cmd_db_device_init);
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index 656706259353..3dfa448bf8cf 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -17,6 +17,8 @@
#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/sizes.h>
+#define CREATE_TRACE_POINTS
+#include "trace_icc-bwmon.h"
/*
* The BWMON samples data throughput within 'sample_ms' time. With three
@@ -282,7 +284,7 @@ static const struct regmap_config msm8998_bwmon_regmap_cfg = {
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const struct regmap_config msm8998_bwmon_global_regmap_cfg = {
@@ -301,7 +303,7 @@ static const struct regmap_config msm8998_bwmon_global_regmap_cfg = {
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static const struct reg_field sdm845_cpu_bwmon_reg_fields[] = {
@@ -369,7 +371,7 @@ static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg = {
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
/* BWMON v5 */
@@ -446,7 +448,7 @@ static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = {
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
- .cache_type = REGCACHE_RBTREE,
+ .cache_type = REGCACHE_MAPLE,
};
static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
@@ -565,7 +567,7 @@ static void bwmon_start(struct icc_bwmon *bwmon)
int window;
/* No need to check for errors, as this must have succeeded before. */
- dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0);
+ dev_pm_opp_put(dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0));
bwmon_clear_counters(bwmon, true);
@@ -645,9 +647,10 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
struct icc_bwmon *bwmon = dev_id;
unsigned int irq_enable = 0;
struct dev_pm_opp *opp, *target_opp;
- unsigned int bw_kbps, up_kbps, down_kbps;
+ unsigned int bw_kbps, up_kbps, down_kbps, meas_kbps;
bw_kbps = bwmon->target_kbps;
+ meas_kbps = bwmon->target_kbps;
target_opp = dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_kbps, 0);
if (IS_ERR(target_opp) && PTR_ERR(target_opp) == -ERANGE)
@@ -679,6 +682,7 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
bwmon_clear_irq(bwmon);
bwmon_enable(bwmon, irq_enable);
+ trace_qcom_bwmon_update(dev_name(bwmon->dev), meas_kbps, up_kbps, down_kbps);
if (bwmon->target_kbps == bwmon->current_kbps)
goto out;
@@ -772,18 +776,25 @@ static int bwmon_probe(struct platform_device *pdev)
opp = dev_pm_opp_find_bw_floor(dev, &bwmon->max_bw_kbps, 0);
if (IS_ERR(opp))
return dev_err_probe(dev, PTR_ERR(opp), "failed to find max peak bandwidth\n");
+ dev_pm_opp_put(opp);
bwmon->min_bw_kbps = 0;
opp = dev_pm_opp_find_bw_ceil(dev, &bwmon->min_bw_kbps, 0);
if (IS_ERR(opp))
return dev_err_probe(dev, PTR_ERR(opp), "failed to find min peak bandwidth\n");
+ dev_pm_opp_put(opp);
bwmon->dev = dev;
bwmon_disable(bwmon);
- ret = devm_request_threaded_irq(dev, bwmon->irq, bwmon_intr,
- bwmon_intr_thread,
- IRQF_ONESHOT, dev_name(dev), bwmon);
+
+ /*
+ * SoCs with multiple cpu-bwmon instances can end up using a shared interrupt
+ * line. Using the devm_ variant might result in the IRQ handler being executed
+ * after bwmon_disable in bwmon_remove()
+ */
+ ret = request_threaded_irq(bwmon->irq, bwmon_intr, bwmon_intr_thread,
+ IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), bwmon);
if (ret)
return dev_err_probe(dev, ret, "failed to request IRQ\n");
@@ -798,6 +809,7 @@ static void bwmon_remove(struct platform_device *pdev)
struct icc_bwmon *bwmon = platform_get_drvdata(pdev);
bwmon_disable(bwmon);
+ free_irq(bwmon->irq, bwmon);
}
static const struct icc_bwmon_data msm8998_bwmon_data = {
@@ -860,7 +872,7 @@ MODULE_DEVICE_TABLE(of, bwmon_of_match);
static struct platform_driver bwmon_driver = {
.probe = bwmon_probe,
- .remove_new = bwmon_remove,
+ .remove = bwmon_remove,
.driver = {
.name = "qcom-bwmon",
.of_match_table = bwmon_of_match,
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index fbab7fe5c652..c467b55b4174 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -8,8 +8,10 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -19,20 +21,63 @@
#include <soc/qcom/ice.h>
-#define AES_256_XTS_KEY_SIZE 64
+#define AES_256_XTS_KEY_SIZE 64 /* for raw keys only */
+#define QCOM_ICE_HWKM_WRAPPED_KEY_SIZE 100 /* assuming HWKM v2 */
/* QCOM ICE registers */
+
+#define QCOM_ICE_REG_CONTROL 0x0000
+#define QCOM_ICE_LEGACY_MODE_ENABLED BIT(0)
+
#define QCOM_ICE_REG_VERSION 0x0008
+
#define QCOM_ICE_REG_FUSE_SETTING 0x0010
+#define QCOM_ICE_FUSE_SETTING_MASK BIT(0)
+#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK BIT(1)
+#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK BIT(2)
+
#define QCOM_ICE_REG_BIST_STATUS 0x0070
+#define QCOM_ICE_BIST_STATUS_MASK GENMASK(31, 28)
+
#define QCOM_ICE_REG_ADVANCED_CONTROL 0x1000
-/* BIST ("built-in self-test") status flags */
-#define QCOM_ICE_BIST_STATUS_MASK GENMASK(31, 28)
+#define QCOM_ICE_REG_CRYPTOCFG_BASE 0x4040
+#define QCOM_ICE_REG_CRYPTOCFG_SIZE 0x80
+#define QCOM_ICE_REG_CRYPTOCFG(slot) (QCOM_ICE_REG_CRYPTOCFG_BASE + \
+ QCOM_ICE_REG_CRYPTOCFG_SIZE * (slot))
+union crypto_cfg {
+ __le32 regval;
+ struct {
+ u8 dusize;
+ u8 capidx;
+ u8 reserved;
+#define QCOM_ICE_HWKM_CFG_ENABLE_VAL BIT(7)
+ u8 cfge;
+ };
+};
+
+/* QCOM ICE HWKM (Hardware Key Manager) registers */
+
+#define HWKM_OFFSET 0x8000
-#define QCOM_ICE_FUSE_SETTING_MASK 0x1
-#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK 0x2
-#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK 0x4
+#define QCOM_ICE_REG_HWKM_TZ_KM_CTL (HWKM_OFFSET + 0x1000)
+#define QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL (BIT(1) | BIT(2))
+
+#define QCOM_ICE_REG_HWKM_TZ_KM_STATUS (HWKM_OFFSET + 0x1004)
+#define QCOM_ICE_HWKM_KT_CLEAR_DONE BIT(0)
+#define QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE BIT(1)
+#define QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE BIT(2)
+#define QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 BIT(7)
+#define QCOM_ICE_HWKM_BIST_DONE_V2 BIT(9)
+
+#define QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS (HWKM_OFFSET + 0x2008)
+#define QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL BIT(3)
+
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_0 (HWKM_OFFSET + 0x5000)
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_1 (HWKM_OFFSET + 0x5004)
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_2 (HWKM_OFFSET + 0x5008)
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_3 (HWKM_OFFSET + 0x500C)
+#define QCOM_ICE_REG_HWKM_BANK0_BBAC_4 (HWKM_OFFSET + 0x5010)
#define qcom_ice_writel(engine, val, reg) \
writel((val), (engine)->base + (reg))
@@ -40,12 +85,18 @@
#define qcom_ice_readl(engine, reg) \
readl((engine)->base + (reg))
+static bool qcom_ice_use_wrapped_keys;
+module_param_named(use_wrapped_keys, qcom_ice_use_wrapped_keys, bool, 0660);
+MODULE_PARM_DESC(use_wrapped_keys,
+ "Support wrapped keys instead of raw keys, if available on the platform");
+
struct qcom_ice {
struct device *dev;
void __iomem *base;
- struct device_link *link;
struct clk *core_clk;
+ bool use_hwkm;
+ bool hwkm_init_complete;
};
static bool qcom_ice_check_supported(struct qcom_ice *ice)
@@ -75,6 +126,35 @@ static bool qcom_ice_check_supported(struct qcom_ice *ice)
return false;
}
+ /*
+ * Check for HWKM support and decide whether to use it or not. ICE
+ * v3.2.1 and later have HWKM v2. ICE v3.2.0 has HWKM v1. Earlier ICE
+ * versions don't have HWKM at all. However, for HWKM to be fully
+ * usable by Linux, the TrustZone software also needs to support certain
+ * SCM calls including the ones to generate and prepare keys. That
+ * effectively makes the earliest supported SoC be SM8650, which has
+ * HWKM v2. Therefore, this driver doesn't include support for HWKM v1,
+ * and it checks for the SCM call support before it decides to use HWKM.
+ *
+ * Also, since HWKM and legacy mode are mutually exclusive, and
+ * ICE-capable storage driver(s) need to know early on whether to
+ * advertise support for raw keys or wrapped keys, HWKM cannot be used
+ * unconditionally. A module parameter is used to opt into using it.
+ */
+ if ((major >= 4 ||
+ (major == 3 && (minor >= 3 || (minor == 2 && step >= 1)))) &&
+ qcom_scm_has_wrapped_key_support()) {
+ if (qcom_ice_use_wrapped_keys) {
+ dev_info(dev, "Using HWKM. Supporting wrapped keys only.\n");
+ ice->use_hwkm = true;
+ } else {
+ dev_info(dev, "Not using HWKM. Supporting raw keys only.\n");
+ }
+ } else if (qcom_ice_use_wrapped_keys) {
+ dev_warn(dev, "A supported HWKM is not present. Ignoring qcom_ice.use_wrapped_keys=1.\n");
+ } else {
+ dev_info(dev, "A supported HWKM is not present. Supporting raw keys only.\n");
+ }
return true;
}
@@ -122,17 +202,71 @@ static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
regval, !(regval & QCOM_ICE_BIST_STATUS_MASK),
50, 5000);
- if (err)
+ if (err) {
dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n");
+ return err;
+ }
- return err;
+ if (ice->use_hwkm &&
+ qcom_ice_readl(ice, QCOM_ICE_REG_HWKM_TZ_KM_STATUS) !=
+ (QCOM_ICE_HWKM_KT_CLEAR_DONE |
+ QCOM_ICE_HWKM_BOOT_CMD_LIST0_DONE |
+ QCOM_ICE_HWKM_BOOT_CMD_LIST1_DONE |
+ QCOM_ICE_HWKM_CRYPTO_BIST_DONE_V2 |
+ QCOM_ICE_HWKM_BIST_DONE_V2)) {
+ dev_err(ice->dev, "HWKM self-test error!\n");
+ /*
+ * Too late to revoke use_hwkm here, as it was already
+ * propagated up the stack into the crypto capabilities.
+ */
+ }
+ return 0;
+}
+
+static void qcom_ice_hwkm_init(struct qcom_ice *ice)
+{
+ u32 regval;
+
+ if (!ice->use_hwkm)
+ return;
+
+ BUILD_BUG_ON(QCOM_ICE_HWKM_WRAPPED_KEY_SIZE >
+ BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE);
+ /*
+ * When ICE is in HWKM mode, it only supports wrapped keys.
+ * When ICE is in legacy mode, it only supports raw keys.
+ *
+ * Put ICE in HWKM mode. ICE defaults to legacy mode.
+ */
+ regval = qcom_ice_readl(ice, QCOM_ICE_REG_CONTROL);
+ regval &= ~QCOM_ICE_LEGACY_MODE_ENABLED;
+ qcom_ice_writel(ice, regval, QCOM_ICE_REG_CONTROL);
+
+ /* Disable CRC checks. This HWKM feature is not used. */
+ qcom_ice_writel(ice, QCOM_ICE_HWKM_DISABLE_CRC_CHECKS_VAL,
+ QCOM_ICE_REG_HWKM_TZ_KM_CTL);
+
+ /*
+ * Allow the HWKM slave to read and write the keyslots in the ICE HWKM
+ * slave. Without this, TrustZone cannot program keys into ICE.
+ */
+ qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_0);
+ qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_1);
+ qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_2);
+ qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_3);
+ qcom_ice_writel(ice, GENMASK(31, 0), QCOM_ICE_REG_HWKM_BANK0_BBAC_4);
+
+ /* Clear the HWKM response FIFO. */
+ qcom_ice_writel(ice, QCOM_ICE_HWKM_RSP_FIFO_CLEAR_VAL,
+ QCOM_ICE_REG_HWKM_BANK0_BANKN_IRQ_STATUS);
+ ice->hwkm_init_complete = true;
}
int qcom_ice_enable(struct qcom_ice *ice)
{
qcom_ice_low_power_mode_enable(ice);
qcom_ice_optimization_enable(ice);
-
+ qcom_ice_hwkm_init(ice);
return qcom_ice_wait_bist_status(ice);
}
EXPORT_SYMBOL_GPL(qcom_ice_enable);
@@ -148,7 +282,7 @@ int qcom_ice_resume(struct qcom_ice *ice)
err);
return err;
}
-
+ qcom_ice_hwkm_init(ice);
return qcom_ice_wait_bist_status(ice);
}
EXPORT_SYMBOL_GPL(qcom_ice_resume);
@@ -156,15 +290,58 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
int qcom_ice_suspend(struct qcom_ice *ice)
{
clk_disable_unprepare(ice->core_clk);
+ ice->hwkm_init_complete = false;
return 0;
}
EXPORT_SYMBOL_GPL(qcom_ice_suspend);
-int qcom_ice_program_key(struct qcom_ice *ice,
- u8 algorithm_id, u8 key_size,
- const u8 crypto_key[], u8 data_unit_size,
- int slot)
+static unsigned int translate_hwkm_slot(struct qcom_ice *ice, unsigned int slot)
+{
+ return slot * 2;
+}
+
+static int qcom_ice_program_wrapped_key(struct qcom_ice *ice, unsigned int slot,
+ const struct blk_crypto_key *bkey)
+{
+ struct device *dev = ice->dev;
+ union crypto_cfg cfg = {
+ .dusize = bkey->crypto_cfg.data_unit_size / 512,
+ .capidx = QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+ .cfge = QCOM_ICE_HWKM_CFG_ENABLE_VAL,
+ };
+ int err;
+
+ if (!ice->use_hwkm) {
+ dev_err_ratelimited(dev, "Got wrapped key when not using HWKM\n");
+ return -EINVAL;
+ }
+ if (!ice->hwkm_init_complete) {
+ dev_err_ratelimited(dev, "HWKM not yet initialized\n");
+ return -EINVAL;
+ }
+
+ /* Clear CFGE before programming the key. */
+ qcom_ice_writel(ice, 0x0, QCOM_ICE_REG_CRYPTOCFG(slot));
+
+ /* Call into TrustZone to program the wrapped key using HWKM. */
+ err = qcom_scm_ice_set_key(translate_hwkm_slot(ice, slot), bkey->bytes,
+ bkey->size, cfg.capidx, cfg.dusize);
+ if (err) {
+ dev_err_ratelimited(dev,
+ "qcom_scm_ice_set_key failed; err=%d, slot=%u\n",
+ err, slot);
+ return err;
+ }
+
+ /* Set CFGE after programming the key. */
+ qcom_ice_writel(ice, le32_to_cpu(cfg.regval),
+ QCOM_ICE_REG_CRYPTOCFG(slot));
+ return 0;
+}
+
+int qcom_ice_program_key(struct qcom_ice *ice, unsigned int slot,
+ const struct blk_crypto_key *blk_key)
{
struct device *dev = ice->dev;
union {
@@ -175,15 +352,26 @@ int qcom_ice_program_key(struct qcom_ice *ice,
int err;
/* Only AES-256-XTS has been tested so far. */
- if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS ||
- key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256) {
- dev_err_ratelimited(dev,
- "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
- algorithm_id, key_size);
+ if (blk_key->crypto_cfg.crypto_mode !=
+ BLK_ENCRYPTION_MODE_AES_256_XTS) {
+ dev_err_ratelimited(dev, "Unsupported crypto mode: %d\n",
+ blk_key->crypto_cfg.crypto_mode);
+ return -EINVAL;
+ }
+
+ if (blk_key->crypto_cfg.key_type == BLK_CRYPTO_KEY_TYPE_HW_WRAPPED)
+ return qcom_ice_program_wrapped_key(ice, slot, blk_key);
+
+ if (ice->use_hwkm) {
+ dev_err_ratelimited(dev, "Got raw key when using HWKM\n");
return -EINVAL;
}
- memcpy(key.bytes, crypto_key, AES_256_XTS_KEY_SIZE);
+ if (blk_key->size != AES_256_XTS_KEY_SIZE) {
+ dev_err_ratelimited(dev, "Incorrect key size\n");
+ return -EINVAL;
+ }
+ memcpy(key.bytes, blk_key->bytes, AES_256_XTS_KEY_SIZE);
/* The SCM call requires that the key words are encoded in big endian */
for (i = 0; i < ARRAY_SIZE(key.words); i++)
@@ -191,7 +379,7 @@ int qcom_ice_program_key(struct qcom_ice *ice,
err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
QCOM_SCM_ICE_CIPHER_AES_256_XTS,
- data_unit_size);
+ blk_key->crypto_cfg.data_unit_size / 512);
memzero_explicit(&key, sizeof(key));
@@ -201,10 +389,131 @@ EXPORT_SYMBOL_GPL(qcom_ice_program_key);
int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
{
+ if (ice->hwkm_init_complete)
+ slot = translate_hwkm_slot(ice, slot);
return qcom_scm_ice_invalidate_key(slot);
}
EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
+/**
+ * qcom_ice_get_supported_key_type() - Get the supported key type
+ * @ice: ICE driver data
+ *
+ * Return: the blk-crypto key type that the ICE driver is configured to use.
+ * This is the key type that ICE-capable storage drivers should advertise as
+ * supported in the crypto capabilities of any disks they register.
+ */
+enum blk_crypto_key_type qcom_ice_get_supported_key_type(struct qcom_ice *ice)
+{
+ if (ice->use_hwkm)
+ return BLK_CRYPTO_KEY_TYPE_HW_WRAPPED;
+ return BLK_CRYPTO_KEY_TYPE_RAW;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_get_supported_key_type);
+
+/**
+ * qcom_ice_derive_sw_secret() - Derive software secret from wrapped key
+ * @ice: ICE driver data
+ * @eph_key: an ephemerally-wrapped key
+ * @eph_key_size: size of @eph_key in bytes
+ * @sw_secret: output buffer for the software secret
+ *
+ * Use HWKM to derive the "software secret" from a hardware-wrapped key that is
+ * given in ephemerally-wrapped form.
+ *
+ * Return: 0 on success; -EBADMSG if the given ephemerally-wrapped key is
+ * invalid; or another -errno value.
+ */
+int qcom_ice_derive_sw_secret(struct qcom_ice *ice,
+ const u8 *eph_key, size_t eph_key_size,
+ u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
+{
+ int err = qcom_scm_derive_sw_secret(eph_key, eph_key_size,
+ sw_secret,
+ BLK_CRYPTO_SW_SECRET_SIZE);
+ if (err == -EIO || err == -EINVAL)
+ err = -EBADMSG; /* probably invalid key */
+ return err;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_derive_sw_secret);
+
+/**
+ * qcom_ice_generate_key() - Generate a wrapped key for inline encryption
+ * @ice: ICE driver data
+ * @lt_key: output buffer for the long-term wrapped key
+ *
+ * Use HWKM to generate a new key and return it as a long-term wrapped key.
+ *
+ * Return: the size of the resulting wrapped key on success; -errno on failure.
+ */
+int qcom_ice_generate_key(struct qcom_ice *ice,
+ u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+ int err;
+
+ err = qcom_scm_generate_ice_key(lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE);
+ if (err)
+ return err;
+
+ return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_generate_key);
+
+/**
+ * qcom_ice_prepare_key() - Prepare a wrapped key for inline encryption
+ * @ice: ICE driver data
+ * @lt_key: a long-term wrapped key
+ * @lt_key_size: size of @lt_key in bytes
+ * @eph_key: output buffer for the ephemerally-wrapped key
+ *
+ * Use HWKM to re-wrap a long-term wrapped key with the per-boot ephemeral key.
+ *
+ * Return: the size of the resulting wrapped key on success; -EBADMSG if the
+ * given long-term wrapped key is invalid; or another -errno value.
+ */
+int qcom_ice_prepare_key(struct qcom_ice *ice,
+ const u8 *lt_key, size_t lt_key_size,
+ u8 eph_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+ int err;
+
+ err = qcom_scm_prepare_ice_key(lt_key, lt_key_size,
+ eph_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE);
+ if (err == -EIO || err == -EINVAL)
+ err = -EBADMSG; /* probably invalid key */
+ if (err)
+ return err;
+
+ return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_prepare_key);
+
+/**
+ * qcom_ice_import_key() - Import a raw key for inline encryption
+ * @ice: ICE driver data
+ * @raw_key: the raw key to import
+ * @raw_key_size: size of @raw_key in bytes
+ * @lt_key: output buffer for the long-term wrapped key
+ *
+ * Use HWKM to import a raw key and return it as a long-term wrapped key.
+ *
+ * Return: the size of the resulting wrapped key on success; -errno on failure.
+ */
+int qcom_ice_import_key(struct qcom_ice *ice,
+ const u8 *raw_key, size_t raw_key_size,
+ u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
+{
+ int err;
+
+ err = qcom_scm_import_ice_key(raw_key, raw_key_size,
+ lt_key, QCOM_ICE_HWKM_WRAPPED_KEY_SIZE);
+ if (err)
+ return err;
+
+ return QCOM_ICE_HWKM_WRAPPED_KEY_SIZE;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_import_key);
+
static struct qcom_ice *qcom_ice_create(struct device *dev,
void __iomem *base)
{
@@ -261,13 +570,13 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
* Return: ICE pointer on success, NULL if there is no ICE data provided by the
* consumer or ERR_PTR() on error.
*/
-struct qcom_ice *of_qcom_ice_get(struct device *dev)
+static struct qcom_ice *of_qcom_ice_get(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct qcom_ice *ice;
- struct device_node *node;
struct resource *res;
void __iomem *base;
+ struct device_link *link;
if (!dev || !dev->of_node)
return ERR_PTR(-ENODEV);
@@ -292,15 +601,15 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
* (legacy DT binding), then it must at least provide a phandle
* to the ICE devicetree node, otherwise ICE is not supported.
*/
- node = of_parse_phandle(dev->of_node, "qcom,ice", 0);
+ struct device_node *node __free(device_node) = of_parse_phandle(dev->of_node,
+ "qcom,ice", 0);
if (!node)
return NULL;
pdev = of_find_device_by_node(node);
if (!pdev) {
dev_err(dev, "Cannot find device node %s\n", node->name);
- ice = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
ice = platform_get_drvdata(pdev);
@@ -308,12 +617,11 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
dev_err(dev, "Cannot get ice instance from %s\n",
dev_name(&pdev->dev));
platform_device_put(pdev);
- ice = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
- ice->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
- if (!ice->link) {
+ link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
+ if (!link) {
dev_err(&pdev->dev,
"Failed to create device link to consumer %s\n",
dev_name(dev));
@@ -321,12 +629,55 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
ice = ERR_PTR(-EINVAL);
}
-out:
- of_node_put(node);
+ return ice;
+}
+
+static void qcom_ice_put(const struct qcom_ice *ice)
+{
+ struct platform_device *pdev = to_platform_device(ice->dev);
+
+ if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"))
+ platform_device_put(pdev);
+}
+
+static void devm_of_qcom_ice_put(struct device *dev, void *res)
+{
+ qcom_ice_put(*(struct qcom_ice **)res);
+}
+
+/**
+ * devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from
+ * a DT node.
+ * @dev: device pointer for the consumer device.
+ *
+ * This function will provide an ICE instance either by creating one for the
+ * consumer device if its DT node provides the 'ice' reg range and the 'ice'
+ * clock (for legacy DT style). On the other hand, if consumer provides a
+ * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
+ * be created and so this function will return that instead.
+ *
+ * Return: ICE pointer on success, NULL if there is no ICE data provided by the
+ * consumer or ERR_PTR() on error.
+ */
+struct qcom_ice *devm_of_qcom_ice_get(struct device *dev)
+{
+ struct qcom_ice *ice, **dr;
+
+ dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return ERR_PTR(-ENOMEM);
+
+ ice = of_qcom_ice_get(dev);
+ if (!IS_ERR_OR_NULL(ice)) {
+ *dr = ice;
+ devres_add(dev, dr);
+ } else {
+ devres_free(dr);
+ }
return ice;
}
-EXPORT_SYMBOL_GPL(of_qcom_ice_get);
+EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get);
static int qcom_ice_probe(struct platform_device *pdev)
{
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index cbef0dea1d5d..192edc3f64dc 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -7,6 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/bitops.h>
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -26,14 +27,19 @@
#define ACT_CTRL_OPCODE_ACTIVATE BIT(0)
#define ACT_CTRL_OPCODE_DEACTIVATE BIT(1)
#define ACT_CTRL_ACT_TRIG BIT(0)
-#define ACT_CTRL_OPCODE_SHIFT 0x01
-#define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x02
-#define ATTR1_FIXED_SIZE_SHIFT 0x03
-#define ATTR1_PRIORITY_SHIFT 0x04
-#define ATTR1_MAX_CAP_SHIFT 0x10
+#define ACT_CTRL_OPCODE_SHIFT 1
+#define ATTR1_PROBE_TARGET_WAYS_SHIFT 2
+#define ATTR1_FIXED_SIZE_SHIFT 3
+#define ATTR1_PRIORITY_SHIFT 4
+#define ATTR1_MAX_CAP_SHIFT 16
#define ATTR0_RES_WAYS_MASK GENMASK(15, 0)
#define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16)
-#define ATTR0_BONUS_WAYS_SHIFT 0x10
+#define ATTR0_BONUS_WAYS_SHIFT 16
+#define ATTR2_PROBE_TARGET_WAYS_MASK BIT(4)
+#define ATTR2_FIXED_SIZE_MASK BIT(8)
+#define ATTR2_PRIORITY_MASK GENMASK(14, 12)
+#define ATTR2_PARENT_SCID_MASK GENMASK(21, 16)
+#define ATTR2_IN_A_GROUP_MASK BIT(24)
#define LLCC_STATUS_READ_DELAY 100
#define CACHE_LINE_SIZE_SHIFT 6
@@ -48,6 +54,10 @@
#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n)
#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n)
#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_4 * n)
+#define LLCC_V6_TRP_ATTR0_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR0_CFG] + SZ_64 * (n))
+#define LLCC_V6_TRP_ATTR1_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR1_CFG] + SZ_64 * (n))
+#define LLCC_V6_TRP_ATTR2_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR2_CFG] + SZ_64 * (n))
+#define LLCC_V6_TRP_ATTR3_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR3_CFG] + SZ_64 * (n))
#define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00
#define LLCC_TRP_PCB_ACT 0x21f04
@@ -65,6 +75,7 @@
#define LLCC_VERSION_2_0_0_0 0x02000000
#define LLCC_VERSION_2_1_0_0 0x02010000
#define LLCC_VERSION_4_1_0_0 0x04010000
+#define LLCC_VERSION_6_0_0_0 0X06000000
/**
* struct llcc_slice_config - Data associated with the llcc slice
@@ -105,6 +116,7 @@
* ovcap_en.
* @vict_prio: When current scid is under-capacity, allocate over other
* lower-than victim priority-line threshold scid.
+ * @parent_slice_id: For grouped slices, specifies the slice id of the parent.
*/
struct llcc_slice_config {
u32 usecase_id;
@@ -129,15 +141,20 @@ struct llcc_slice_config {
bool ovcap_en;
bool ovcap_prio;
bool vict_prio;
+ u32 parent_slice_id;
};
struct qcom_llcc_config {
const struct llcc_slice_config *sct_data;
const u32 *reg_offset;
const struct llcc_edac_reg_offset *edac_reg_offset;
+ u32 max_cap_shift; /* instead of ATTR1_MAX_CAP_SHIFT */
+ u32 num_banks;
int size;
- bool need_llcc_cfg;
+ bool skip_llcc_cfg;
bool no_edac;
+ bool irq_configured;
+ bool no_broadcast_register;
};
struct qcom_sct_config {
@@ -148,311 +165,3230 @@ struct qcom_sct_config {
enum llcc_reg_offset {
LLCC_COMMON_HW_INFO,
LLCC_COMMON_STATUS0,
+ LLCC_TRP_ATTR0_CFG,
+ LLCC_TRP_ATTR1_CFG,
+ LLCC_TRP_ATTR2_CFG,
+ LLCC_TRP_ATTR3_CFG,
+ LLCC_TRP_SID_DIS_CAP_ALLOC,
+ LLCC_TRP_ALGO_STALE_EN,
+ LLCC_TRP_ALGO_STALE_CAP_EN,
+ LLCC_TRP_ALGO_MRU0,
+ LLCC_TRP_ALGO_MRU1,
+ LLCC_TRP_ALGO_ALLOC0,
+ LLCC_TRP_ALGO_ALLOC1,
+ LLCC_TRP_ALGO_ALLOC2,
+ LLCC_TRP_ALGO_ALLOC3,
+ LLCC_TRP_WRS_EN,
+ LLCC_TRP_WRS_CACHEABLE_EN,
+};
+
+static const struct llcc_slice_config ipq5424_data[] = {
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 768,
+ .priority = 1,
+ .bonus_ways = 0xFFFF,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ .write_scid_cacheable_en = true,
+ .stale_en = true,
+ .stale_cap_en = true,
+ .alloc_oneway_en = true,
+ .ovcap_en = true,
+ .ovcap_prio = true,
+ .vict_prio = true,
+ },
+ {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 256,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xF000,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ .write_scid_cacheable_en = true,
+ .stale_en = true,
+ .stale_cap_en = true,
+ },
+};
+
+static const struct llcc_slice_config sa8775p_data[] = {
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 2048,
+ .priority = 1,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CPUSS1,
+ .slice_id = 3,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CPUHWT,
+ .slice_id = 5,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 4096,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CMPTDMA,
+ .slice_id = 15,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 4096,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDFW,
+ .slice_id = 17,
+ .max_cap = 3072,
+ .priority = 1,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 28,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0xf0,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
+};
+
+static const struct llcc_slice_config sar1130p_data[] = {
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 4096,
+ .priority = 1,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 3072,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 12800,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 28,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 26,
+ .max_cap = 2048,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x3,
+ .cache_mode = true,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 30,
+ .max_cap = 3072,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x1fff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP_LEFT,
+ .slice_id = 17,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP_RIGHT,
+ .slice_id = 18,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVCS_LEFT,
+ .slice_id = 22,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVCS_RIGHT,
+ .slice_id = 23,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ },
+};
+
+static const struct llcc_slice_config sar2130p_data[] = {
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = 0,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 128,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 1536,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 26,
+ .max_cap = 2048,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x3,
+ .cache_mode = true,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIEYE,
+ .slice_id = 7,
+ .max_cap = 7168,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDPTH,
+ .slice_id = 8,
+ .max_cap = 7168,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUMV,
+ .slice_id = 9,
+ .max_cap = 2048,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVA_LEFT,
+ .slice_id = 20,
+ .max_cap = 7168,
+ .priority = 5,
+ .fixed_size = true,
+ .bonus_ways = 0x3ffffffc,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVA_RIGHT,
+ .slice_id = 21,
+ .max_cap = 7168,
+ .priority = 5,
+ .fixed_size = true,
+ .bonus_ways = 0x3ffffffc,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVAGAIN,
+ .slice_id = 25,
+ .max_cap = 1024,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 30,
+ .max_cap = 3072,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIPTH,
+ .slice_id = 29,
+ .max_cap = 1024,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0x3fffffff,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP_LEFT,
+ .slice_id = 17,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP_RIGHT,
+ .slice_id = 18,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVCS_LEFT,
+ .slice_id = 22,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_EVCS_RIGHT,
+ .slice_id = 23,
+ .max_cap = 0,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_SPAD,
+ .slice_id = 24,
+ .max_cap = 7168,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x0,
+ .res_ways = 0x0,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ },
};
static const struct llcc_slice_config sc7180_data[] = {
- { LLCC_CPUSS, 1, 256, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 1 },
- { LLCC_MDM, 8, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPUHTW, 11, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPU, 12, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 256,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 128,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 128,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 128,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ },
};
static const struct llcc_slice_config sc7280_data[] = {
- { LLCC_CPUSS, 1, 768, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 1, 0},
- { LLCC_MDMHPGRW, 7, 512, 2, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
- { LLCC_CMPT, 10, 768, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
- { LLCC_GPUHTW, 11, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
- { LLCC_GPU, 12, 512, 1, 0, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
- { LLCC_MMUHWT, 13, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 0, 1, 0},
- { LLCC_MDMPNG, 21, 768, 0, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
- { LLCC_WLHW, 24, 256, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
- { LLCC_MODPE, 29, 64, 1, 1, 0x3f, 0x0, 0, 0, 0, 1, 0, 0},
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 768,
+ .priority = 1,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 768,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 768,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WLHW,
+ .slice_id = 24,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 64,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3f,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ },
};
static const struct llcc_slice_config sc8180x_data[] = {
- { LLCC_CPUSS, 1, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1 },
- { LLCC_VIDSC0, 2, 512, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_VIDSC1, 3, 512, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MDMHPGRW, 7, 3072, 1, 1, 0x3ff, 0xc00, 0, 0, 0, 1, 0 },
- { LLCC_MDM, 8, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MODHW, 9, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_CMPT, 10, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPU, 12, 5120, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1 },
- { LLCC_CMPTDMA, 15, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_VIDFW, 17, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MDMHPFX, 20, 1024, 2, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MDMPNG, 21, 1024, 0, 1, 0xc, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_NPU, 23, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_WLHW, 24, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MODPE, 29, 512, 1, 1, 0xc, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_APTCM, 30, 512, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0 },
- { LLCC_WRCACHE, 31, 128, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDSC1,
+ .slice_id = 3,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3ff,
+ .res_ways = 0xc00,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 5120,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CMPTDMA,
+ .slice_id = 15,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDFW,
+ .slice_id = 17,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPFX,
+ .slice_id = 20,
+ .max_cap = 1024,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0xc,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_NPU,
+ .slice_id = 23,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WLHW,
+ .slice_id = 24,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xc,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0x1,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ },
};
static const struct llcc_slice_config sc8280xp_data[] = {
- { LLCC_CPUSS, 1, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 },
- { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
- { LLCC_CMPT, 10, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
- { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_GPU, 12, 4096, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 },
- { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_DISP, 16, 6144, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_AUDHW, 22, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_ECC, 26, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0, 0 },
- { LLCC_WRCACHE, 31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_CVPFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_CPUSS1, 3, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_CPUHWT, 5, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
-};
-
-static const struct llcc_slice_config sdm845_data[] = {
- { LLCC_CPUSS, 1, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 1 },
- { LLCC_VIDSC0, 2, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 },
- { LLCC_VIDSC1, 3, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 },
- { LLCC_ROTATOR, 4, 563, 2, 1, 0x0, 0x00e, 2, 0, 1, 1, 0 },
- { LLCC_VOICE, 5, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_AUDIO, 6, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_MDMHPGRW, 7, 1024, 2, 0, 0xfc, 0xf00, 0, 0, 1, 1, 0 },
- { LLCC_MDM, 8, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_CMPT, 10, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_GPUHTW, 11, 512, 1, 1, 0xc, 0x0, 0, 0, 1, 1, 0 },
- { LLCC_GPU, 12, 2304, 1, 0, 0xff0, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_MMUHWT, 13, 256, 2, 0, 0x0, 0x1, 0, 0, 1, 0, 1 },
- { LLCC_CMPTDMA, 15, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_DISP, 16, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_VIDFW, 17, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
- { LLCC_MDMHPFX, 20, 1024, 2, 1, 0x0, 0xf00, 0, 0, 1, 1, 0 },
- { LLCC_MDMPNG, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0 },
- { LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 4096,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 2048,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_ECC,
+ .slice_id = 26,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 28,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0x1,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CVPFW,
+ .slice_id = 17,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CPUSS1,
+ .slice_id = 3,
+ .max_cap = 2048,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CPUHWT,
+ .slice_id = 5,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
+};
+
+static const struct llcc_slice_config sdm845_data[] = {{
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .res_ways = 0xf0,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDSC1,
+ .slice_id = 3,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .res_ways = 0xf0,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_ROTATOR,
+ .slice_id = 4,
+ .max_cap = 563,
+ .priority = 2,
+ .fixed_size = true,
+ .res_ways = 0xe,
+ .cache_mode = 2,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VOICE,
+ .slice_id = 5,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 1024,
+ .priority = 2,
+ .bonus_ways = 0xfc,
+ .res_ways = 0xf00,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xc,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 2304,
+ .priority = 1,
+ .bonus_ways = 0xff0,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 256,
+ .priority = 2,
+ .res_ways = 0x1,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CMPTDMA,
+ .slice_id = 15,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDFW,
+ .slice_id = 17,
+ .max_cap = 2816,
+ .priority = 1,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPFX,
+ .slice_id = 20,
+ .max_cap = 1024,
+ .priority = 2,
+ .fixed_size = true,
+ .res_ways = 0xf00,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0x1e,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .res_ways = 0x2,
+ .cache_mode = 0,
+ .dis_cap_alloc = true,
+ .retain_on_pc = true,
+ },
};
static const struct llcc_slice_config sm6350_data[] = {
- { LLCC_CPUSS, 1, 768, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 1 },
- { LLCC_MDM, 8, 512, 2, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_GPUHTW, 11, 256, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_GPU, 12, 512, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_MDMPNG, 21, 768, 0, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_NPU, 23, 768, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_MODPE, 29, 64, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 768,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 512,
+ .priority = 2,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 256,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 768,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_NPU,
+ .slice_id = 23,
+ .max_cap = 768,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 64,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
};
static const struct llcc_slice_config sm7150_data[] = {
- { LLCC_CPUSS, 1, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1 },
- { LLCC_MDM, 8, 128, 2, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPUHTW, 11, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPU, 12, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_NPU, 23, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 128,
+ .priority = 2,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_NPU,
+ .slice_id = 23,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ },
};
static const struct llcc_slice_config sm8150_data[] = {
- { LLCC_CPUSS, 1, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 1 },
- { LLCC_VIDSC0, 2, 512, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_VIDSC1, 3, 512, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_AUDIO, 6, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MDMHPGRW, 7, 3072, 1, 0, 0xFF, 0xF00, 0, 0, 0, 1, 0 },
- { LLCC_MDM, 8, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MODHW, 9, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_CMPT, 10, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPUHTW , 11, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_GPU, 12, 2560, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MMUHWT, 13, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1 },
- { LLCC_CMPTDMA, 15, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_DISP, 16, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MDMHPFX, 20, 1024, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MDMHPFX, 21, 1024, 0, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_AUDHW, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_NPU, 23, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_WLHW, 24, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_MODPE, 29, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
- { LLCC_APTCM, 30, 256, 3, 1, 0x0, 0x1, 1, 0, 0, 1, 0 },
- { LLCC_WRCACHE, 31, 128, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDSC1,
+ .slice_id = 3,
+ .max_cap = 512,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 3072,
+ .priority = 1,
+ .bonus_ways = 0xff,
+ .res_ways = 0xf00,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 2560,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CMPTDMA,
+ .slice_id = 15,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPFX,
+ .slice_id = 20,
+ .max_cap = 1024,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMHPFX,
+ .slice_id = 21,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_NPU,
+ .slice_id = 23,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WLHW,
+ .slice_id = 24,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0x1,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ },
};
static const struct llcc_slice_config sm8250_data[] = {
- { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 },
- { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_AUDIO, 6, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
- { LLCC_CMPT, 10, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
- { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 1 },
- { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_CMPTDMA, 15, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_DISP, 16, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_VIDFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_NPU, 23, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_WLHW, 24, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_CVP, 28, 256, 3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
- { LLCC_APTCM, 30, 128, 3, 0, 0x0, 0x3, 1, 0, 0, 1, 0, 0 },
- { LLCC_WRCACHE, 31, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 1024,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 1024,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CMPTDMA,
+ .slice_id = 15,
+ .max_cap = 1024,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_VIDFW,
+ .slice_id = 17,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_NPU,
+ .slice_id = 23,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WLHW,
+ .slice_id = 24,
+ .max_cap = 1024,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 28,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 128,
+ .priority = 3,
+ .res_ways = 0x3,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
};
static const struct llcc_slice_config sm8350_data[] = {
- { LLCC_CPUSS, 1, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 1 },
- { LLCC_VIDSC0, 2, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_AUDIO, 6, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 0 },
- { LLCC_MDMHPGRW, 7, 1024, 3, 0, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_MODHW, 9, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_CMPT, 10, 3072, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_GPUHTW, 11, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_GPU, 12, 1024, 1, 0, 0xfff, 0x0, 0, 0, 0, 1, 1, 0 },
- { LLCC_MMUHWT, 13, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 },
- { LLCC_DISP, 16, 3072, 2, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_MDMPNG, 21, 1024, 0, 1, 0xf, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_AUDHW, 22, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_CVP, 28, 512, 3, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_MODPE, 29, 256, 1, 1, 0xf, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0x1, 1, 0, 0, 0, 1, 0 },
- { LLCC_WRCACHE, 31, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 },
- { LLCC_CVPFW, 17, 512, 1, 0, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_CPUSS1, 3, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
- { LLCC_CPUHWT, 5, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 0, 1 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 1024,
+ .priority = 3,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 1024,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 3072,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 28,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0x1,
+ .cache_mode = 1,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_CVPFW,
+ .slice_id = 17,
+ .max_cap = 512,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CPUSS1,
+ .slice_id = 3,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CPUHWT,
+ .slice_id = 5,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .write_scid_en = true,
+ },
};
static const struct llcc_slice_config sm8450_data[] = {
- {LLCC_CPUSS, 1, 3072, 1, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 },
- {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 },
- {LLCC_MDMHPGRW, 7, 1024, 3, 0, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_MODHW, 9, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_GPU, 12, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 1, 0 },
- {LLCC_MMUHWT, 13, 768, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 },
- {LLCC_DISP, 16, 4096, 2, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_MDMPNG, 21, 1024, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 },
- {LLCC_CVP, 28, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_MODPE, 29, 64, 1, 1, 0xF000, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xF0, 1, 0, 0, 1, 0, 0, 0 },
- {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0 },
- {LLCC_CVPFW, 17, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_CPUSS1, 3, 1024, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_CAMEXP0, 4, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_CPUMTE, 23, 256, 1, 1, 0x0FFF, 0x0, 0, 0, 0, 0, 1, 0, 0 },
- {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 1, 0, 0 },
- {LLCC_CAMEXP1, 27, 256, 3, 1, 0xFFFF, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 3072,
+ .priority = 1,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 1024,
+ .priority = 3,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 4096,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 2048,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 768,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 4096,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf000,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 28,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 64,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf000,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0xf0,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CVPFW,
+ .slice_id = 17,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CPUSS1,
+ .slice_id = 3,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CAMEXP0,
+ .slice_id = 4,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_CPUMTE,
+ .slice_id = 23,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CPUHWT,
+ .slice_id = 5,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CAMEXP1,
+ .slice_id = 27,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 8,
+ .max_cap = 2048,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffff,
+ .cache_mode = 0,
+ },
};
static const struct llcc_slice_config sm8550_data[] = {
- {LLCC_CPUSS, 1, 5120, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_VIDSC0, 2, 512, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_MDMHPGRW, 25, 1024, 4, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_MODHW, 26, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_GPU, 9, 3096, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_MMUHWT, 18, 768, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_DISP, 16, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_MDMPNG, 27, 1024, 0, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CVP, 8, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_MODPE, 29, 64, 1, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, },
- {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CAMEXP0, 4, 256, 4, 1, 0xF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CAMEXP1, 7, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CMPTHCP, 17, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_LCPDARE, 30, 128, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, },
- {LLCC_AENPU, 3, 3072, 1, 1, 0xFE01FF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_ISLAND1, 12, 1792, 7, 1, 0xFE00, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_ISLAND4, 15, 256, 7, 1, 0x10000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CAMEXP2, 19, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CAMEXP3, 20, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_CAMEXP4, 21, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_DISP_WB, 23, 1024, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_DISP_1, 24, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 5120,
+ .priority = 1,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 25,
+ .max_cap = 1024,
+ .priority = 4,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 26,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 4096,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 9,
+ .max_cap = 3096,
+ .priority = 1,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .write_scid_en = true,
+ .write_scid_cacheable_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 18,
+ .max_cap = 768,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 27,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0xf00000,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 8,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 64,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf00000,
+ .cache_mode = 0,
+ .alloc_oneway_en = true,
+ .vict_prio = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CAMEXP0,
+ .slice_id = 4,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CPUHWT,
+ .slice_id = 5,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CAMEXP1,
+ .slice_id = 7,
+ .max_cap = 3200,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfffff0,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_CMPTHCP,
+ .slice_id = 17,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_LCPDARE,
+ .slice_id = 30,
+ .max_cap = 128,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .alloc_oneway_en = true,
+ .vict_prio = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 3,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfe01ff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_ISLAND1,
+ .slice_id = 12,
+ .max_cap = 1792,
+ .priority = 7,
+ .fixed_size = true,
+ .bonus_ways = 0xfe00,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_ISLAND4,
+ .slice_id = 15,
+ .max_cap = 256,
+ .priority = 7,
+ .fixed_size = true,
+ .bonus_ways = 0x10000,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CAMEXP2,
+ .slice_id = 19,
+ .max_cap = 3200,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfffff0,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_CAMEXP3,
+ .slice_id = 20,
+ .max_cap = 3200,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfffff0,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_CAMEXP4,
+ .slice_id = 21,
+ .max_cap = 3200,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xfffff0,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_DISP_WB,
+ .slice_id = 23,
+ .max_cap = 1024,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_DISP_1,
+ .slice_id = 24,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_VIDVSP,
+ .slice_id = 28,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ },
};
static const struct llcc_slice_config sm8650_data[] = {
- {LLCC_CPUSS, 1, 5120, 1, 0, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_AUDIO, 6, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MDMHPGRW, 25, 1024, 3, 0, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MODHW, 26, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_GPU, 9, 3096, 1, 0, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MMUHWT, 18, 768, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_DISP, 16, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MDMHPFX, 24, 1024, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MDMPNG, 27, 1024, 0, 1, 0x000000, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CVP, 8, 256, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MODPE, 29, 128, 1, 1, 0xF00000, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
- {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP0, 4, 256, 3, 1, 0xF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP1, 7, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CMPTHCP, 17, 256, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_LCPDARE, 30, 128, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
- {LLCC_AENPU, 3, 3072, 1, 1, 0xFFFFFF, 0x0, 2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND1, 12, 5888, 7, 1, 0x0, 0x7FFFFF, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_DISP_WB, 23, 1024, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_VIDVSP, 28, 256, 3, 1, 0xFFFFFF, 0x0, 0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 5120,
+ .priority = 1,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .stale_en = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 25,
+ .max_cap = 1024,
+ .priority = 3,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 26,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 4096,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 9,
+ .max_cap = 3096,
+ .priority = 1,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .write_scid_en = true,
+ .write_scid_cacheable_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 18,
+ .max_cap = 768,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_MDMHPFX,
+ .slice_id = 24,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 27,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 8,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf00000,
+ .cache_mode = 0,
+ .alloc_oneway_en = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CAMEXP0,
+ .slice_id = 4,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CAMEXP1,
+ .slice_id = 7,
+ .max_cap = 3200,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfffff0,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_CMPTHCP,
+ .slice_id = 17,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_LCPDARE,
+ .slice_id = 30,
+ .max_cap = 128,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .alloc_oneway_en = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 3,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_ISLAND1,
+ .slice_id = 12,
+ .max_cap = 5888,
+ .priority = 7,
+ .fixed_size = true,
+ .res_ways = 0x7fffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_DISP_WB,
+ .slice_id = 23,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_VIDVSP,
+ .slice_id = 28,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffffff,
+ .cache_mode = 0,
+ },
+};
+
+static const struct llcc_slice_config sm8750_data[] = {
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 5120,
+ .priority = 1,
+ .bonus_ways = 0xffffffff,
+ .activate_on_init = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MDMHPFX,
+ .slice_id = 24,
+ .max_cap = 1024,
+ .priority = 5,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 35,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 25,
+ .max_cap = 1024,
+ .priority = 5,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 26,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 34,
+ .max_cap = 4096,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 9,
+ .max_cap = 5632,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .write_scid_en = true,
+ .write_scid_cacheable_en = true
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 18,
+ .max_cap = 768,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_DISP,
+ .slice_id = 16,
+ .max_cap = 7168,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .cache_mode = 2,
+ .stale_en = true,
+ }, {
+ .usecase_id = LLCC_VIDFW,
+ .slice_id = 17,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_CAMFW,
+ .slice_id = 20,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 27,
+ .max_cap = 256,
+ .priority = 5,
+ .fixed_size = true,
+ .bonus_ways = 0xf0000000,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 8,
+ .max_cap = 800,
+ .priority = 5,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .vict_prio = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf0000000,
+ .alloc_oneway_en = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CVPFW,
+ .slice_id = 19,
+ .max_cap = 64,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_CMPTHCP,
+ .slice_id = 15,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_LCPDARE,
+ .slice_id = 30,
+ .max_cap = 128,
+ .priority = 5,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .activate_on_init = true,
+ .alloc_oneway_en = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 3,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_ISLAND1,
+ .slice_id = 12,
+ .max_cap = 7936,
+ .priority = 7,
+ .fixed_size = true,
+ .bonus_ways = 0x7fffffff,
+ }, {
+ .usecase_id = LLCC_DISP_WB,
+ .slice_id = 23,
+ .max_cap = 512,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_VIDVSP,
+ .slice_id = 4,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ }, {
+ .usecase_id = LLCC_VIDDEC,
+ .slice_id = 5,
+ .max_cap = 6144,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .cache_mode = 2,
+ .ovcap_prio = true,
+ .parent_slice_id = 33,
+ }, {
+ .usecase_id = LLCC_CAMOFE,
+ .slice_id = 33,
+ .max_cap = 6144,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .stale_en = true,
+ .ovcap_prio = true,
+ .parent_slice_id = 33,
+ }, {
+ .usecase_id = LLCC_CAMRTIP,
+ .slice_id = 13,
+ .max_cap = 1024,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .stale_en = true,
+ .ovcap_prio = true,
+ .parent_slice_id = 33,
+ }, {
+ .usecase_id = LLCC_CAMSRTIP,
+ .slice_id = 14,
+ .max_cap = 6144,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .stale_en = true,
+ .ovcap_prio = true,
+ .parent_slice_id = 33,
+ }, {
+ .usecase_id = LLCC_CAMRTRF,
+ .slice_id = 7,
+ .max_cap = 3584,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .stale_en = true,
+ .ovcap_prio = true,
+ .parent_slice_id = 33,
+ }, {
+ .usecase_id = LLCC_CAMSRTRF,
+ .slice_id = 21,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .stale_en = true,
+ .ovcap_prio = true,
+ .parent_slice_id = 33,
+ }, {
+ .usecase_id = LLCC_CPUSSMPAM,
+ .slice_id = 6,
+ .max_cap = 2048,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xffffffff,
+ .activate_on_init = true,
+ .write_scid_en = true,
+ },
+};
+
+static const struct llcc_slice_config qcs615_data[] = {
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 128,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MDM,
+ .slice_id = 8,
+ .max_cap = 256,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 128,
+ .priority = 1,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
+};
+
+static const struct llcc_slice_config qcs8300_data[] = {
+ {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 12,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ .write_scid_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 13,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_ECC,
+ .slice_id = 26,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xf,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
};
static const struct llcc_slice_config qdu1000_data_2ch[] = {
- { LLCC_MDMHPGRW, 7, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_MODHW, 9, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_MDMPNG, 21, 256, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_ECC, 26, 512, 3, 1, 0xffc, 0x0, 0, 0, 0, 0, 1, 0, 0 },
- { LLCC_MODPE, 29, 256, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_APTCM, 30, 256, 3, 1, 0x0, 0xc, 1, 0, 0, 1, 0, 0, 0 },
- { LLCC_WRCACHE, 31, 128, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+ {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 256,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_ECC,
+ .slice_id = 26,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 256,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0xc,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 128,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
};
static const struct llcc_slice_config qdu1000_data_4ch[] = {
- { LLCC_MDMHPGRW, 7, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_MODHW, 9, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_MDMPNG, 21, 512, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_ECC, 26, 1024, 3, 1, 0xffc, 0x0, 0, 0, 0, 0, 1, 0, 0 },
- { LLCC_MODPE, 29, 512, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_APTCM, 30, 512, 3, 1, 0x0, 0xc, 1, 0, 0, 1, 0, 0, 0 },
- { LLCC_WRCACHE, 31, 256, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+ {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 512,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_ECC,
+ .slice_id = 26,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0xc,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 256,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
};
static const struct llcc_slice_config qdu1000_data_8ch[] = {
- { LLCC_MDMHPGRW, 7, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_MODHW, 9, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_MDMPNG, 21, 1024, 0, 1, 0x3, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_ECC, 26, 2048, 3, 1, 0xffc, 0x0, 0, 0, 0, 0, 1, 0, 0 },
- { LLCC_MODPE, 29, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0, 0 },
- { LLCC_APTCM, 30, 1024, 3, 1, 0x0, 0xc, 1, 0, 0, 1, 0, 0, 0 },
- { LLCC_WRCACHE, 31, 512, 1, 1, 0x3, 0x0, 0, 0, 0, 0, 1, 0, 0 },
+ {
+ .usecase_id = LLCC_MDMHPGRW,
+ .slice_id = 7,
+ .max_cap = 2048,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MODHW,
+ .slice_id = 9,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_MDMPNG,
+ .slice_id = 21,
+ .max_cap = 1024,
+ .priority = 0,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_ECC,
+ .slice_id = 26,
+ .max_cap = 2048,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_MODPE,
+ .slice_id = 29,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_APTCM,
+ .slice_id = 30,
+ .max_cap = 1024,
+ .priority = 3,
+ .fixed_size = true,
+ .res_ways = 0xc,
+ .cache_mode = 1,
+ .retain_on_pc = true,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ },
};
static const struct llcc_slice_config x1e80100_data[] = {
- {LLCC_CPUSS, 1, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_AUDIO, 6, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CMPT, 10, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_GPUHTW, 11, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_GPU, 9, 4096, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MMUHWT, 18, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CVP, 8, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP1, 7, 3072, 2, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_LCPDARE, 30, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_AENPU, 3, 3072, 1, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND1, 12, 512, 7, 1, 0x1, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND2, 13, 512, 7, 1, 0x2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND3, 14, 512, 7, 1, 0x3, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND4, 15, 512, 7, 1, 0x4, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP2, 19, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP3, 20, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP4, 21, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {
+ .usecase_id = LLCC_CPUSS,
+ .slice_id = 1,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_VIDSC0,
+ .slice_id = 2,
+ .max_cap = 512,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_AUDIO,
+ .slice_id = 6,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CMPT,
+ .slice_id = 10,
+ .max_cap = 6144,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPUHTW,
+ .slice_id = 11,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_GPU,
+ .slice_id = 9,
+ .max_cap = 4608,
+ .priority = 1,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .write_scid_en = true,
+ .write_scid_cacheable_en = true,
+ .stale_en = true,
+ }, {
+ .usecase_id = LLCC_MMUHWT,
+ .slice_id = 18,
+ .max_cap = 512,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_AUDHW,
+ .slice_id = 22,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CVP,
+ .slice_id = 8,
+ .max_cap = 512,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_WRCACHE,
+ .slice_id = 31,
+ .max_cap = 1024,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ }, {
+ .usecase_id = LLCC_CAMEXP0,
+ .slice_id = 4,
+ .max_cap = 256,
+ .priority = 4,
+ .fixed_size = true,
+ .bonus_ways = 0x3,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CAMEXP1,
+ .slice_id = 7,
+ .max_cap = 3072,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_LCPDARE,
+ .slice_id = 30,
+ .max_cap = 512,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 0,
+ .activate_on_init = true,
+ .alloc_oneway_en = true,
+ }, {
+ .usecase_id = LLCC_AENPU,
+ .slice_id = 3,
+ .max_cap = 3072,
+ .priority = 1,
+ .fixed_size = true,
+ .bonus_ways = 0xfff,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_ISLAND1,
+ .slice_id = 12,
+ .max_cap = 2048,
+ .priority = 7,
+ .fixed_size = true,
+ .res_ways = 0xf,
+ .cache_mode = 0,
+ }, {
+ .usecase_id = LLCC_CAMEXP2,
+ .slice_id = 19,
+ .max_cap = 3072,
+ .priority = 3,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_CAMEXP3,
+ .slice_id = 20,
+ .max_cap = 3072,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 2,
+ }, {
+ .usecase_id = LLCC_CAMEXP4,
+ .slice_id = 21,
+ .max_cap = 3072,
+ .priority = 2,
+ .fixed_size = true,
+ .bonus_ways = 0xffc,
+ .cache_mode = 2,
+ },
};
static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
@@ -509,6 +3445,33 @@ static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = {
.drp_ecc_db_err_syn0 = 0x52120,
};
+static const struct llcc_edac_reg_offset llcc_v6_edac_reg_offset = {
+ .trp_ecc_error_status0 = 0x47448,
+ .trp_ecc_error_status1 = 0x47450,
+ .trp_ecc_sb_err_syn0 = 0x47490,
+ .trp_ecc_db_err_syn0 = 0x474d0,
+ .trp_ecc_error_cntr_clear = 0x47444,
+ .trp_interrupt_0_status = 0x47600,
+ .trp_interrupt_0_clear = 0x47604,
+ .trp_interrupt_0_enable = 0x47608,
+
+ /* LLCC Common registers */
+ .cmn_status0 = 0x6400c,
+ .cmn_interrupt_0_enable = 0x6401c,
+ .cmn_interrupt_2_enable = 0x6403c,
+
+ /* LLCC DRP registers */
+ .drp_ecc_error_cfg = 0x80000,
+ .drp_ecc_error_cntr_clear = 0x80004,
+ .drp_interrupt_status = 0x80020,
+ .drp_interrupt_clear = 0x80028,
+ .drp_interrupt_enable = 0x8002c,
+ .drp_ecc_error_status0 = 0x820f4,
+ .drp_ecc_error_status1 = 0x820f8,
+ .drp_ecc_sb_err_syn0 = 0x820fc,
+ .drp_ecc_db_err_syn0 = 0x82120,
+};
+
/* LLCC register offset starting from v1.0.0 */
static const u32 llcc_v1_reg_offset[] = {
[LLCC_COMMON_HW_INFO] = 0x00030000,
@@ -521,42 +3484,118 @@ static const u32 llcc_v2_1_reg_offset[] = {
[LLCC_COMMON_STATUS0] = 0x0003400c,
};
+/* LLCC register offset starting from v6.0.0 */
+static const u32 llcc_v6_reg_offset[] = {
+ [LLCC_COMMON_HW_INFO] = 0x00064000,
+ [LLCC_COMMON_STATUS0] = 0x0006400c,
+ [LLCC_TRP_ATTR0_CFG] = 0x00041000,
+ [LLCC_TRP_ATTR1_CFG] = 0x00041008,
+ [LLCC_TRP_ATTR2_CFG] = 0x00041010,
+ [LLCC_TRP_ATTR3_CFG] = 0x00041014,
+ [LLCC_TRP_SID_DIS_CAP_ALLOC] = 0x00042000,
+ [LLCC_TRP_ALGO_STALE_EN] = 0x00042008,
+ [LLCC_TRP_ALGO_STALE_CAP_EN] = 0x00042010,
+ [LLCC_TRP_ALGO_MRU0] = 0x00042018,
+ [LLCC_TRP_ALGO_MRU1] = 0x00042020,
+ [LLCC_TRP_ALGO_ALLOC0] = 0x00042028,
+ [LLCC_TRP_ALGO_ALLOC1] = 0x00042030,
+ [LLCC_TRP_ALGO_ALLOC2] = 0x00042038,
+ [LLCC_TRP_ALGO_ALLOC3] = 0x00042040,
+ [LLCC_TRP_WRS_EN] = 0x00042080,
+ [LLCC_TRP_WRS_CACHEABLE_EN] = 0x00042088,
+};
+
+static const struct qcom_llcc_config qcs615_cfg[] = {
+ {
+ .sct_data = qcs615_data,
+ .size = ARRAY_SIZE(qcs615_data),
+ .reg_offset = llcc_v1_reg_offset,
+ .edac_reg_offset = &llcc_v1_edac_reg_offset,
+ },
+};
+
+static const struct qcom_llcc_config qcs8300_cfg[] = {
+ {
+ .sct_data = qcs8300_data,
+ .size = ARRAY_SIZE(qcs8300_data),
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ .num_banks = 4,
+ },
+};
+
static const struct qcom_llcc_config qdu1000_cfg[] = {
{
.sct_data = qdu1000_data_8ch,
.size = ARRAY_SIZE(qdu1000_data_8ch),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
{
.sct_data = qdu1000_data_4ch,
.size = ARRAY_SIZE(qdu1000_data_4ch),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
{
.sct_data = qdu1000_data_4ch,
.size = ARRAY_SIZE(qdu1000_data_4ch),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
{
.sct_data = qdu1000_data_2ch,
.size = ARRAY_SIZE(qdu1000_data_2ch),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
};
+static const struct qcom_llcc_config ipq5424_cfg[] = {
+ {
+ .sct_data = ipq5424_data,
+ .size = ARRAY_SIZE(ipq5424_data),
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ .no_broadcast_register = true,
+ },
+};
+
+static const struct qcom_llcc_config sa8775p_cfg[] = {
+ {
+ .sct_data = sa8775p_data,
+ .size = ARRAY_SIZE(sa8775p_data),
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ },
+};
+
+static const struct qcom_llcc_config sar1130p_cfg[] = {
+ {
+ .sct_data = sar1130p_data,
+ .size = ARRAY_SIZE(sar1130p_data),
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ .max_cap_shift = 14,
+ .num_banks = 2,
+ },
+};
+
+static const struct qcom_llcc_config sar2130p_cfg[] = {
+ {
+ .sct_data = sar2130p_data,
+ .size = ARRAY_SIZE(sar2130p_data),
+ .reg_offset = llcc_v2_1_reg_offset,
+ .edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ .max_cap_shift = 14,
+ .num_banks = 2,
+ },
+};
+
static const struct qcom_llcc_config sc7180_cfg[] = {
{
.sct_data = sc7180_data,
.size = ARRAY_SIZE(sc7180_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -566,7 +3605,6 @@ static const struct qcom_llcc_config sc7280_cfg[] = {
{
.sct_data = sc7280_data,
.size = ARRAY_SIZE(sc7280_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -576,7 +3614,6 @@ static const struct qcom_llcc_config sc8180x_cfg[] = {
{
.sct_data = sc8180x_data,
.size = ARRAY_SIZE(sc8180x_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -586,7 +3623,6 @@ static const struct qcom_llcc_config sc8280xp_cfg[] = {
{
.sct_data = sc8280xp_data,
.size = ARRAY_SIZE(sc8280xp_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -596,7 +3632,7 @@ static const struct qcom_llcc_config sdm845_cfg[] = {
{
.sct_data = sdm845_data,
.size = ARRAY_SIZE(sdm845_data),
- .need_llcc_cfg = false,
+ .skip_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
.no_edac = true,
@@ -607,7 +3643,6 @@ static const struct qcom_llcc_config sm6350_cfg[] = {
{
.sct_data = sm6350_data,
.size = ARRAY_SIZE(sm6350_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -617,7 +3652,6 @@ static const struct qcom_llcc_config sm7150_cfg[] = {
{
.sct_data = sm7150_data,
.size = ARRAY_SIZE(sm7150_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -627,7 +3661,6 @@ static const struct qcom_llcc_config sm8150_cfg[] = {
{
.sct_data = sm8150_data,
.size = ARRAY_SIZE(sm8150_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -637,7 +3670,6 @@ static const struct qcom_llcc_config sm8250_cfg[] = {
{
.sct_data = sm8250_data,
.size = ARRAY_SIZE(sm8250_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -647,7 +3679,6 @@ static const struct qcom_llcc_config sm8350_cfg[] = {
{
.sct_data = sm8350_data,
.size = ARRAY_SIZE(sm8350_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
},
@@ -657,7 +3688,6 @@ static const struct qcom_llcc_config sm8450_cfg[] = {
{
.sct_data = sm8450_data,
.size = ARRAY_SIZE(sm8450_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
@@ -667,7 +3697,6 @@ static const struct qcom_llcc_config sm8550_cfg[] = {
{
.sct_data = sm8550_data,
.size = ARRAY_SIZE(sm8550_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
@@ -677,27 +3706,66 @@ static const struct qcom_llcc_config sm8650_cfg[] = {
{
.sct_data = sm8650_data,
.size = ARRAY_SIZE(sm8650_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
},
};
+static const struct qcom_llcc_config sm8750_cfg[] = {
+ {
+ .sct_data = sm8750_data,
+ .size = ARRAY_SIZE(sm8750_data),
+ .skip_llcc_cfg = false,
+ .reg_offset = llcc_v6_reg_offset,
+ .edac_reg_offset = &llcc_v6_edac_reg_offset,
+ },
+};
+
static const struct qcom_llcc_config x1e80100_cfg[] = {
{
.sct_data = x1e80100_data,
.size = ARRAY_SIZE(x1e80100_data),
- .need_llcc_cfg = true,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
+ .irq_configured = true,
},
};
+static const struct qcom_sct_config qcs615_cfgs = {
+ .llcc_config = qcs615_cfg,
+ .num_config = ARRAY_SIZE(qcs615_cfg),
+};
+
+static const struct qcom_sct_config qcs8300_cfgs = {
+ .llcc_config = qcs8300_cfg,
+ .num_config = ARRAY_SIZE(qcs8300_cfg),
+};
+
static const struct qcom_sct_config qdu1000_cfgs = {
.llcc_config = qdu1000_cfg,
.num_config = ARRAY_SIZE(qdu1000_cfg),
};
+static const struct qcom_sct_config ipq5424_cfgs = {
+ .llcc_config = ipq5424_cfg,
+ .num_config = ARRAY_SIZE(ipq5424_cfg),
+};
+
+static const struct qcom_sct_config sa8775p_cfgs = {
+ .llcc_config = sa8775p_cfg,
+ .num_config = ARRAY_SIZE(sa8775p_cfg),
+};
+
+static const struct qcom_sct_config sar1130p_cfgs = {
+ .llcc_config = sar1130p_cfg,
+ .num_config = ARRAY_SIZE(sar1130p_cfg),
+};
+
+static const struct qcom_sct_config sar2130p_cfgs = {
+ .llcc_config = sar2130p_cfg,
+ .num_config = ARRAY_SIZE(sar2130p_cfg),
+};
+
static const struct qcom_sct_config sc7180_cfgs = {
.llcc_config = sc7180_cfg,
.num_config = ARRAY_SIZE(sc7180_cfg),
@@ -763,6 +3831,11 @@ static const struct qcom_sct_config sm8650_cfgs = {
.num_config = ARRAY_SIZE(sm8650_cfg),
};
+static const struct qcom_sct_config sm8750_cfgs = {
+ .llcc_config = sm8750_cfg,
+ .num_config = ARRAY_SIZE(sm8750_cfg),
+};
+
static const struct qcom_sct_config x1e80100_cfgs = {
.llcc_config = x1e80100_cfg,
.num_config = ARRAY_SIZE(x1e80100_cfg),
@@ -821,6 +3894,7 @@ EXPORT_SYMBOL_GPL(llcc_slice_putd);
static int llcc_update_act_ctrl(u32 sid,
u32 act_ctrl_reg_val, u32 status)
{
+ struct regmap *regmap;
u32 act_ctrl_reg;
u32 act_clear_reg;
u32 status_reg;
@@ -849,7 +3923,8 @@ static int llcc_update_act_ctrl(u32 sid,
return ret;
if (drv_data->version >= LLCC_VERSION_4_1_0_0) {
- ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
+ regmap = drv_data->bcast_and_regmap ?: drv_data->bcast_regmap;
+ ret = regmap_read_poll_timeout(regmap, status_reg,
slice_status, (slice_status & ACT_COMPLETE),
0, LLCC_STATUS_READ_DELAY);
if (ret)
@@ -1003,7 +4078,10 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
*/
max_cap_cacheline = max_cap_cacheline / drv_data->num_banks;
max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
- attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT;
+ if (cfg->max_cap_shift)
+ attr1_val |= max_cap_cacheline << cfg->max_cap_shift;
+ else
+ attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT;
attr1_cfg = LLCC_TRP_ATTR1_CFGn(config->slice_id);
@@ -1032,7 +4110,8 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
return ret;
}
- if (cfg->need_llcc_cfg) {
+ /* At least SDM845 disallows non-secure writes to these registers */
+ if (!cfg->skip_llcc_cfg) {
u32 disable_cap_alloc, retain_pc;
disable_cap_alloc = config->dis_cap_alloc << config->slice_id;
@@ -1137,6 +4216,139 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
return ret;
}
+static int _qcom_llcc_cfg_program_v6(const struct llcc_slice_config *config,
+ const struct qcom_llcc_config *cfg)
+{
+ u32 stale_en, stale_cap_en, mru_uncap_en, mru_rollover;
+ u32 alloc_oneway_en, ovcap_en, ovcap_prio, vict_prio;
+ u32 attr0_cfg, attr1_cfg, attr2_cfg, attr3_cfg;
+ u32 attr0_val, attr1_val, attr2_val, attr3_val;
+ u32 slice_offset, reg_offset;
+ struct llcc_slice_desc *desc;
+ u32 wren, wr_cache_en;
+ int ret;
+
+ attr0_cfg = LLCC_V6_TRP_ATTR0_CFGn(config->slice_id);
+ attr1_cfg = LLCC_V6_TRP_ATTR1_CFGn(config->slice_id);
+ attr2_cfg = LLCC_V6_TRP_ATTR2_CFGn(config->slice_id);
+ attr3_cfg = LLCC_V6_TRP_ATTR3_CFGn(config->slice_id);
+
+ attr0_val = config->res_ways;
+ attr1_val = config->bonus_ways;
+ attr2_val = config->cache_mode;
+ attr2_val |= FIELD_PREP(ATTR2_PROBE_TARGET_WAYS_MASK, config->probe_target_ways);
+ attr2_val |= FIELD_PREP(ATTR2_FIXED_SIZE_MASK, config->fixed_size);
+ attr2_val |= FIELD_PREP(ATTR2_PRIORITY_MASK, config->priority);
+
+ if (config->parent_slice_id && config->fixed_size) {
+ attr2_val |= FIELD_PREP(ATTR2_PARENT_SCID_MASK, config->parent_slice_id);
+ attr2_val |= ATTR2_IN_A_GROUP_MASK;
+ }
+
+ attr3_val = MAX_CAP_TO_BYTES(config->max_cap);
+ attr3_val /= drv_data->num_banks;
+ attr3_val >>= CACHE_LINE_SIZE_SHIFT;
+
+ ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, attr0_val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, attr1_val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(drv_data->bcast_regmap, attr2_cfg, attr2_val);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(drv_data->bcast_regmap, attr3_cfg, attr3_val);
+ if (ret)
+ return ret;
+
+ slice_offset = config->slice_id % 32;
+ reg_offset = (config->slice_id / 32) * 4;
+
+ wren = config->write_scid_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_WRS_EN] + reg_offset,
+ BIT(slice_offset), wren);
+ if (ret)
+ return ret;
+
+ wr_cache_en = config->write_scid_cacheable_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_WRS_CACHEABLE_EN] + reg_offset,
+ BIT(slice_offset), wr_cache_en);
+ if (ret)
+ return ret;
+
+ stale_en = config->stale_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_STALE_EN] + reg_offset,
+ BIT(slice_offset), stale_en);
+ if (ret)
+ return ret;
+
+ stale_cap_en = config->stale_cap_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_STALE_CAP_EN] + reg_offset,
+ BIT(slice_offset), stale_cap_en);
+ if (ret)
+ return ret;
+
+ mru_uncap_en = config->mru_uncap_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_MRU0] + reg_offset,
+ BIT(slice_offset), mru_uncap_en);
+ if (ret)
+ return ret;
+
+ mru_rollover = config->mru_rollover << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_MRU1] + reg_offset,
+ BIT(slice_offset), mru_rollover);
+ if (ret)
+ return ret;
+
+ alloc_oneway_en = config->alloc_oneway_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_ALLOC0] + reg_offset,
+ BIT(slice_offset), alloc_oneway_en);
+ if (ret)
+ return ret;
+
+ ovcap_en = config->ovcap_en << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_ALLOC1] + reg_offset,
+ BIT(slice_offset), ovcap_en);
+ if (ret)
+ return ret;
+
+ ovcap_prio = config->ovcap_prio << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_ALLOC2] + reg_offset,
+ BIT(slice_offset), ovcap_prio);
+ if (ret)
+ return ret;
+
+ vict_prio = config->vict_prio << slice_offset;
+ ret = regmap_update_bits(drv_data->bcast_regmap,
+ cfg->reg_offset[LLCC_TRP_ALGO_ALLOC3] + reg_offset,
+ BIT(slice_offset), vict_prio);
+ if (ret)
+ return ret;
+
+ if (config->activate_on_init) {
+ desc = llcc_slice_getd(config->usecase_id);
+ if (PTR_ERR_OR_ZERO(desc))
+ return -EINVAL;
+
+ ret = llcc_slice_activate(desc);
+ }
+
+ return ret;
+}
+
static int qcom_llcc_cfg_program(struct platform_device *pdev,
const struct qcom_llcc_config *cfg)
{
@@ -1148,10 +4360,18 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
sz = drv_data->cfg_size;
llcc_table = drv_data->cfg;
- for (i = 0; i < sz; i++) {
- ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg);
- if (ret)
- return ret;
+ if (drv_data->version >= LLCC_VERSION_6_0_0_0) {
+ for (i = 0; i < sz; i++) {
+ ret = _qcom_llcc_cfg_program_v6(&llcc_table[i], cfg);
+ if (ret)
+ return ret;
+ }
+ } else {
+ for (i = 0; i < sz; i++) {
+ ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg);
+ if (ret)
+ return ret;
+ }
}
return ret;
@@ -1240,12 +4460,17 @@ static int qcom_llcc_probe(struct platform_device *pdev)
goto err;
cfg = &cfgs->llcc_config[cfg_index];
- ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks);
- if (ret)
- goto err;
+ if (cfg->num_banks) {
+ num_banks = cfg->num_banks;
+ } else {
+ ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks);
+ if (ret)
+ goto err;
+
+ num_banks &= LLCC_LB_CNT_MASK;
+ num_banks >>= LLCC_LB_CNT_SHIFT;
+ }
- num_banks &= LLCC_LB_CNT_MASK;
- num_banks >>= LLCC_LB_CNT_SHIFT;
drv_data->num_banks = num_banks;
drv_data->regmaps = devm_kcalloc(dev, num_banks, sizeof(*drv_data->regmaps), GFP_KERNEL);
@@ -1258,22 +4483,23 @@ static int qcom_llcc_probe(struct platform_device *pdev)
/* Initialize rest of LLCC bank regmaps */
for (i = 1; i < num_banks; i++) {
- char *base = kasprintf(GFP_KERNEL, "llcc%d_base", i);
+ char *base __free(kfree) = kasprintf(GFP_KERNEL, "llcc%d_base", i);
drv_data->regmaps[i] = qcom_llcc_init_mmio(pdev, i, base);
if (IS_ERR(drv_data->regmaps[i])) {
ret = PTR_ERR(drv_data->regmaps[i]);
- kfree(base);
goto err;
}
-
- kfree(base);
}
drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base");
if (IS_ERR(drv_data->bcast_regmap)) {
- ret = PTR_ERR(drv_data->bcast_regmap);
- goto err;
+ if (cfg->no_broadcast_register) {
+ drv_data->bcast_regmap = regmap;
+ } else {
+ ret = PTR_ERR(drv_data->bcast_regmap);
+ goto err;
+ }
}
/* Extract version of the IP */
@@ -1284,6 +4510,18 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->version = version;
+ /* Applicable only when drv_data->version >= 4.1 */
+ if (drv_data->version >= LLCC_VERSION_4_1_0_0) {
+ drv_data->bcast_and_regmap = qcom_llcc_init_mmio(pdev, i + 1, "llcc_broadcast_and_base");
+ if (IS_ERR(drv_data->bcast_and_regmap)) {
+ ret = PTR_ERR(drv_data->bcast_and_regmap);
+ if (ret == -EINVAL)
+ drv_data->bcast_and_regmap = NULL;
+ else
+ goto err;
+ }
+ }
+
llcc_cfg = cfg->sct_data;
sz = cfg->size;
@@ -1301,6 +4539,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->cfg = llcc_cfg;
drv_data->cfg_size = sz;
drv_data->edac_reg_offset = cfg->edac_reg_offset;
+ drv_data->ecc_irq_configured = cfg->irq_configured;
mutex_init(&drv_data->lock);
platform_set_drvdata(pdev, drv_data);
@@ -1331,7 +4570,13 @@ err:
}
static const struct of_device_id qcom_llcc_of_match[] = {
+ { .compatible = "qcom,ipq5424-llcc", .data = &ipq5424_cfgs},
+ { .compatible = "qcom,qcs615-llcc", .data = &qcs615_cfgs},
+ { .compatible = "qcom,qcs8300-llcc", .data = &qcs8300_cfgs},
{ .compatible = "qcom,qdu1000-llcc", .data = &qdu1000_cfgs},
+ { .compatible = "qcom,sa8775p-llcc", .data = &sa8775p_cfgs },
+ { .compatible = "qcom,sar1130p-llcc", .data = &sar1130p_cfgs },
+ { .compatible = "qcom,sar2130p-llcc", .data = &sar2130p_cfgs },
{ .compatible = "qcom,sc7180-llcc", .data = &sc7180_cfgs },
{ .compatible = "qcom,sc7280-llcc", .data = &sc7280_cfgs },
{ .compatible = "qcom,sc8180x-llcc", .data = &sc8180x_cfgs },
@@ -1345,6 +4590,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
{ .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfgs },
{ .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfgs },
{ .compatible = "qcom,sm8650-llcc", .data = &sm8650_cfgs },
+ { .compatible = "qcom,sm8750-llcc", .data = &sm8750_cfgs },
{ .compatible = "qcom,x1e80100-llcc", .data = &x1e80100_cfgs },
{ }
};
@@ -1356,7 +4602,7 @@ static struct platform_driver qcom_llcc_driver = {
.of_match_table = qcom_llcc_of_match,
},
.probe = qcom_llcc_probe,
- .remove_new = qcom_llcc_remove,
+ .remove = qcom_llcc_remove,
};
module_platform_driver(qcom_llcc_driver);
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 6f177e46fa0f..b2c0fb55d4ae 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -7,6 +7,7 @@
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/elf.h>
#include <linux/firmware.h>
@@ -37,13 +38,12 @@ static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
{
const struct elf32_phdr *phdr = &phdrs[segment];
const struct firmware *seg_fw;
- char *seg_name;
ssize_t ret;
if (strlen(fw_name) < 4)
return -EINVAL;
- seg_name = kstrdup(fw_name, GFP_KERNEL);
+ char *seg_name __free(kfree) = kstrdup(fw_name, GFP_KERNEL);
if (!seg_name)
return -ENOMEM;
@@ -52,7 +52,6 @@ static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
ptr, phdr->p_filesz);
if (ret) {
dev_err(dev, "error %zd loading %s\n", ret, seg_name);
- kfree(seg_name);
return ret;
}
@@ -64,7 +63,6 @@ static ssize_t mdt_load_split_segment(void *ptr, const struct elf32_phdr *phdrs,
}
release_firmware(seg_fw);
- kfree(seg_name);
return ret;
}
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c
index e8841d247953..9c3bd37b6579 100644
--- a/drivers/soc/qcom/ocmem.c
+++ b/drivers/soc/qcom/ocmem.c
@@ -10,6 +10,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -185,23 +186,20 @@ static void update_range(struct ocmem *ocmem, struct ocmem_buf *buf,
struct ocmem *of_get_ocmem(struct device *dev)
{
struct platform_device *pdev;
- struct device_node *devnode;
struct ocmem *ocmem;
- devnode = of_parse_phandle(dev->of_node, "sram", 0);
+ struct device_node *devnode __free(device_node) = of_parse_phandle(dev->of_node,
+ "sram", 0);
if (!devnode || !devnode->parent) {
dev_err(dev, "Cannot look up sram phandle\n");
- of_node_put(devnode);
return ERR_PTR(-ENODEV);
}
pdev = of_find_device_by_node(devnode->parent);
if (!pdev) {
dev_err(dev, "Cannot find device node %s\n", devnode->name);
- of_node_put(devnode);
return ERR_PTR(-EPROBE_DEFER);
}
- of_node_put(devnode);
ocmem = platform_get_drvdata(pdev);
if (!ocmem) {
@@ -216,7 +214,6 @@ EXPORT_SYMBOL_GPL(of_get_ocmem);
struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
unsigned long size)
{
- struct ocmem_buf *buf;
int ret;
/* TODO: add support for other clients... */
@@ -229,7 +226,7 @@ struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
if (test_and_set_bit_lock(BIT(client), &ocmem->active_allocations))
return ERR_PTR(-EBUSY);
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ struct ocmem_buf *buf __free(kfree) = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto err_unlock;
@@ -247,7 +244,7 @@ struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
if (ret) {
dev_err(ocmem->dev, "could not lock: %d\n", ret);
ret = -EINVAL;
- goto err_kfree;
+ goto err_unlock;
}
} else {
ocmem_write(ocmem, OCMEM_REG_GFX_MPU_START, buf->offset);
@@ -258,10 +255,8 @@ struct ocmem_buf *ocmem_allocate(struct ocmem *ocmem, enum ocmem_client client,
dev_dbg(ocmem->dev, "using %ldK of OCMEM at 0x%08lx for client %d\n",
size / 1024, buf->addr, client);
- return buf;
+ return_ptr(buf);
-err_kfree:
- kfree(buf);
err_unlock:
clear_bit_unlock(BIT(client), &ocmem->active_allocations);
@@ -444,7 +439,7 @@ MODULE_DEVICE_TABLE(of, ocmem_of_match);
static struct platform_driver ocmem_driver = {
.probe = ocmem_dev_probe,
- .remove_new = ocmem_dev_remove,
+ .remove = ocmem_dev_remove,
.driver = {
.name = "ocmem",
.of_match_table = ocmem_of_match,
diff --git a/drivers/soc/qcom/pdr_interface.c b/drivers/soc/qcom/pdr_interface.c
index a1b6a4081dea..71be378d2e43 100644
--- a/drivers/soc/qcom/pdr_interface.c
+++ b/drivers/soc/qcom/pdr_interface.c
@@ -3,6 +3,7 @@
* Copyright (C) 2020 The Linux Foundation. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -74,24 +75,18 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
{
struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
locator_hdl);
- struct pdr_service *pds;
+ mutex_lock(&pdr->lock);
/* Create a local client port for QMI communication */
pdr->locator_addr.sq_family = AF_QIPCRTR;
pdr->locator_addr.sq_node = svc->node;
pdr->locator_addr.sq_port = svc->port;
- mutex_lock(&pdr->lock);
pdr->locator_init_complete = true;
mutex_unlock(&pdr->lock);
/* Service pending lookup requests */
- mutex_lock(&pdr->list_lock);
- list_for_each_entry(pds, &pdr->lookups, node) {
- if (pds->need_locator_lookup)
- schedule_work(&pdr->locator_work);
- }
- mutex_unlock(&pdr->list_lock);
+ schedule_work(&pdr->locator_work);
return 0;
}
@@ -104,10 +99,10 @@ static void pdr_locator_del_server(struct qmi_handle *qmi,
mutex_lock(&pdr->lock);
pdr->locator_init_complete = false;
- mutex_unlock(&pdr->lock);
pdr->locator_addr.sq_node = 0;
pdr->locator_addr.sq_port = 0;
+ mutex_unlock(&pdr->lock);
}
static const struct qmi_ops pdr_locator_ops = {
@@ -365,12 +360,14 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
if (ret < 0)
return ret;
+ mutex_lock(&pdr->lock);
ret = qmi_send_request(&pdr->locator_hdl,
&pdr->locator_addr,
&txn, SERVREG_GET_DOMAIN_LIST_REQ,
SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
servreg_get_domain_list_req_ei,
req);
+ mutex_unlock(&pdr->lock);
if (ret < 0) {
qmi_txn_cancel(&txn);
return ret;
@@ -394,13 +391,13 @@ static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
{
- struct servreg_get_domain_list_resp *resp;
struct servreg_get_domain_list_req req;
struct servreg_location_entry *entry;
int domains_read = 0;
int ret, i;
- resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+ struct servreg_get_domain_list_resp *resp __free(kfree) = kzalloc(sizeof(*resp),
+ GFP_KERNEL);
if (!resp)
return -ENOMEM;
@@ -413,9 +410,9 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
req.domain_offset = domains_read;
ret = pdr_get_domain_list(&req, resp, pdr);
if (ret < 0)
- goto out;
+ return ret;
- for (i = domains_read; i < resp->domain_list_len; i++) {
+ for (i = 0; i < resp->domain_list_len; i++) {
entry = &resp->domain_list[i];
if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
@@ -425,7 +422,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
pds->service_data_valid = entry->service_data_valid;
pds->service_data = entry->service_data;
pds->instance = entry->instance;
- goto out;
+ return 0;
}
}
@@ -438,8 +435,7 @@ static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
domains_read += resp->domain_list_len;
} while (domains_read < resp->total_domains);
-out:
- kfree(resp);
+
return ret;
}
@@ -515,8 +511,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
const char *service_name,
const char *service_path)
{
- struct pdr_service *pds, *tmp;
- int ret;
+ struct pdr_service *tmp;
if (IS_ERR_OR_NULL(pdr))
return ERR_PTR(-EINVAL);
@@ -525,7 +520,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
!service_path || strlen(service_path) > SERVREG_NAME_LENGTH)
return ERR_PTR(-EINVAL);
- pds = kzalloc(sizeof(*pds), GFP_KERNEL);
+ struct pdr_service *pds __free(kfree) = kzalloc(sizeof(*pds), GFP_KERNEL);
if (!pds)
return ERR_PTR(-ENOMEM);
@@ -540,8 +535,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
continue;
mutex_unlock(&pdr->list_lock);
- ret = -EALREADY;
- goto err;
+ return ERR_PTR(-EALREADY);
}
list_add(&pds->node, &pdr->lookups);
@@ -549,10 +543,7 @@ struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
schedule_work(&pdr->locator_work);
- return pds;
-err:
- kfree(pds);
- return ERR_PTR(ret);
+ return_ptr(pds);
}
EXPORT_SYMBOL_GPL(pdr_add_lookup);
@@ -649,13 +640,12 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
char *service_path,
void *priv), void *priv)
{
- struct pdr_handle *pdr;
int ret;
if (!status)
return ERR_PTR(-EINVAL);
- pdr = kzalloc(sizeof(*pdr), GFP_KERNEL);
+ struct pdr_handle *pdr __free(kfree) = kzalloc(sizeof(*pdr), GFP_KERNEL);
if (!pdr)
return ERR_PTR(-ENOMEM);
@@ -674,10 +664,8 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
INIT_WORK(&pdr->indack_work, pdr_indack_work);
pdr->notifier_wq = create_singlethread_workqueue("pdr_notifier_wq");
- if (!pdr->notifier_wq) {
- ret = -ENOMEM;
- goto free_pdr_handle;
- }
+ if (!pdr->notifier_wq)
+ return ERR_PTR(-ENOMEM);
pdr->indack_wq = alloc_ordered_workqueue("pdr_indack_wq", WQ_HIGHPRI);
if (!pdr->indack_wq) {
@@ -702,7 +690,7 @@ struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
if (ret < 0)
goto release_qmi_handle;
- return pdr;
+ return_ptr(pdr);
release_qmi_handle:
qmi_handle_release(&pdr->locator_hdl);
@@ -710,8 +698,6 @@ destroy_indack:
destroy_workqueue(pdr->indack_wq);
destroy_notifier:
destroy_workqueue(pdr->notifier_wq);
-free_pdr_handle:
- kfree(pdr);
return ERR_PTR(ret);
}
diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h
index 03c282b7f17e..039508c1bbf7 100644
--- a/drivers/soc/qcom/pdr_internal.h
+++ b/drivers/soc/qcom/pdr_internal.h
@@ -13,6 +13,8 @@
#define SERVREG_SET_ACK_REQ 0x23
#define SERVREG_RESTART_PD_REQ 0x24
+#define SERVREG_LOC_PFR_REQ 0x24
+
#define SERVREG_DOMAIN_LIST_LENGTH 32
#define SERVREG_RESTART_PD_REQ_MAX_LEN 67
#define SERVREG_REGISTER_LISTENER_REQ_LEN 71
@@ -20,6 +22,7 @@
#define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
#define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
#define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
+#define SERVREG_LOC_PFR_RESP_MAX_LEN 10
struct servreg_location_entry {
char name[SERVREG_NAME_LENGTH + 1];
@@ -28,83 +31,12 @@ struct servreg_location_entry {
u32 instance;
};
-static const struct qmi_elem_info servreg_location_entry_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- name),
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- instance),
- },
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- service_data_valid),
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0,
- .offset = offsetof(struct servreg_location_entry,
- service_data),
- },
- {}
-};
-
struct servreg_get_domain_list_req {
char service_name[SERVREG_NAME_LENGTH + 1];
u8 domain_offset_valid;
u32 domain_offset;
};
-static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_get_domain_list_req,
- service_name),
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_req,
- domain_offset_valid),
- },
- {
- .data_type = QMI_UNSIGNED_4_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_req,
- domain_offset),
- },
- {}
-};
-
struct servreg_get_domain_list_resp {
struct qmi_response_type_v01 resp;
u8 total_domains_valid;
@@ -116,264 +48,59 @@ struct servreg_get_domain_list_resp {
struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
};
-static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- total_domains_valid),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- total_domains),
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- db_rev_count_valid),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x11,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- db_rev_count),
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- domain_list_valid),
- },
- {
- .data_type = QMI_DATA_LEN,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- domain_list_len),
- },
- {
- .data_type = QMI_STRUCT,
- .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
- .elem_size = sizeof(struct servreg_location_entry),
- .array_type = VAR_LEN_ARRAY,
- .tlv_type = 0x12,
- .offset = offsetof(struct servreg_get_domain_list_resp,
- domain_list),
- .ei_array = servreg_location_entry_ei,
- },
- {}
-};
-
struct servreg_register_listener_req {
u8 enable;
char service_path[SERVREG_NAME_LENGTH + 1];
};
-static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
- {
- .data_type = QMI_UNSIGNED_1_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_register_listener_req,
- enable),
- },
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_register_listener_req,
- service_path),
- },
- {}
-};
-
struct servreg_register_listener_resp {
struct qmi_response_type_v01 resp;
u8 curr_state_valid;
enum servreg_service_state curr_state;
};
-static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_register_listener_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {
- .data_type = QMI_OPT_FLAG,
- .elem_len = 1,
- .elem_size = sizeof(u8),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_register_listener_resp,
- curr_state_valid),
- },
- {
- .data_type = QMI_SIGNED_4_BYTE_ENUM,
- .elem_len = 1,
- .elem_size = sizeof(enum servreg_service_state),
- .array_type = NO_ARRAY,
- .tlv_type = 0x10,
- .offset = offsetof(struct servreg_register_listener_resp,
- curr_state),
- },
- {}
-};
-
struct servreg_restart_pd_req {
char service_path[SERVREG_NAME_LENGTH + 1];
};
-static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_restart_pd_req,
- service_path),
- },
- {}
-};
-
struct servreg_restart_pd_resp {
struct qmi_response_type_v01 resp;
};
-static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_restart_pd_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {}
-};
-
struct servreg_state_updated_ind {
enum servreg_service_state curr_state;
char service_path[SERVREG_NAME_LENGTH + 1];
u16 transaction_id;
};
-static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
- {
- .data_type = QMI_SIGNED_4_BYTE_ENUM,
- .elem_len = 1,
- .elem_size = sizeof(u32),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_state_updated_ind,
- curr_state),
- },
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_state_updated_ind,
- service_path),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x03,
- .offset = offsetof(struct servreg_state_updated_ind,
- transaction_id),
- },
- {}
-};
-
struct servreg_set_ack_req {
char service_path[SERVREG_NAME_LENGTH + 1];
u16 transaction_id;
};
-static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
- {
- .data_type = QMI_STRING,
- .elem_len = SERVREG_NAME_LENGTH + 1,
- .elem_size = sizeof(char),
- .array_type = NO_ARRAY,
- .tlv_type = 0x01,
- .offset = offsetof(struct servreg_set_ack_req,
- service_path),
- },
- {
- .data_type = QMI_UNSIGNED_2_BYTE,
- .elem_len = 1,
- .elem_size = sizeof(u16),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_set_ack_req,
- transaction_id),
- },
- {}
-};
-
struct servreg_set_ack_resp {
struct qmi_response_type_v01 resp;
};
-static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
- {
- .data_type = QMI_STRUCT,
- .elem_len = 1,
- .elem_size = sizeof(struct qmi_response_type_v01),
- .array_type = NO_ARRAY,
- .tlv_type = 0x02,
- .offset = offsetof(struct servreg_set_ack_resp,
- resp),
- .ei_array = qmi_response_type_v01_ei,
- },
- {}
+struct servreg_loc_pfr_req {
+ char service[SERVREG_NAME_LENGTH + 1];
+ char reason[257];
};
+struct servreg_loc_pfr_resp {
+ struct qmi_response_type_v01 rsp;
+};
+
+extern const struct qmi_elem_info servreg_get_domain_list_req_ei[];
+extern const struct qmi_elem_info servreg_get_domain_list_resp_ei[];
+extern const struct qmi_elem_info servreg_register_listener_req_ei[];
+extern const struct qmi_elem_info servreg_register_listener_resp_ei[];
+extern const struct qmi_elem_info servreg_restart_pd_req_ei[];
+extern const struct qmi_elem_info servreg_restart_pd_resp_ei[];
+extern const struct qmi_elem_info servreg_state_updated_ind_ei[];
+extern const struct qmi_elem_info servreg_set_ack_req_ei[];
+extern const struct qmi_elem_info servreg_set_ack_resp_ei[];
+extern const struct qmi_elem_info servreg_loc_pfr_req_ei[];
+extern const struct qmi_elem_info servreg_loc_pfr_resp_ei[];
+
#endif
diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c
index f913e9bd57ed..0a6d325b195c 100644
--- a/drivers/soc/qcom/pmic_glink.c
+++ b/drivers/soc/qcom/pmic_glink.c
@@ -4,6 +4,8 @@
* Copyright (c) 2022, Linaro Ltd
*/
#include <linux/auxiliary_bus.h>
+#include <linux/cleanup.h>
+#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
@@ -11,6 +13,9 @@
#include <linux/slab.h>
#include <linux/soc/qcom/pdr.h>
#include <linux/soc/qcom/pmic_glink.h>
+#include <linux/spinlock.h>
+
+#define PMIC_GLINK_SEND_TIMEOUT (5 * HZ)
enum {
PMIC_GLINK_CLIENT_BATT = 0,
@@ -36,7 +41,7 @@ struct pmic_glink {
unsigned int pdr_state;
/* serializing clients list updates */
- struct mutex client_lock;
+ spinlock_t client_lock;
struct list_head clients;
};
@@ -58,17 +63,18 @@ static void _devm_pmic_glink_release_client(struct device *dev, void *res)
{
struct pmic_glink_client *client = (struct pmic_glink_client *)res;
struct pmic_glink *pg = client->pg;
+ unsigned long flags;
- mutex_lock(&pg->client_lock);
+ spin_lock_irqsave(&pg->client_lock, flags);
list_del(&client->node);
- mutex_unlock(&pg->client_lock);
+ spin_unlock_irqrestore(&pg->client_lock, flags);
}
-struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
- unsigned int id,
- void (*cb)(const void *, size_t, void *),
- void (*pdr)(void *, int),
- void *priv)
+struct pmic_glink_client *devm_pmic_glink_client_alloc(struct device *dev,
+ unsigned int id,
+ void (*cb)(const void *, size_t, void *),
+ void (*pdr)(void *, int),
+ void *priv)
{
struct pmic_glink_client *client;
struct pmic_glink *pg = dev_get_drvdata(dev->parent);
@@ -82,22 +88,57 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
client->cb = cb;
client->pdr_notify = pdr;
client->priv = priv;
-
- mutex_lock(&pg->client_lock);
- list_add(&client->node, &pg->clients);
- mutex_unlock(&pg->client_lock);
+ INIT_LIST_HEAD(&client->node);
devres_add(dev, client);
return client;
}
-EXPORT_SYMBOL_GPL(devm_pmic_glink_register_client);
+EXPORT_SYMBOL_GPL(devm_pmic_glink_client_alloc);
+
+void pmic_glink_client_register(struct pmic_glink_client *client)
+{
+ struct pmic_glink *pg = client->pg;
+ unsigned long flags;
+
+ guard(mutex)(&pg->state_lock);
+ spin_lock_irqsave(&pg->client_lock, flags);
+
+ list_add(&client->node, &pg->clients);
+ client->pdr_notify(client->priv, pg->client_state);
+
+ spin_unlock_irqrestore(&pg->client_lock, flags);
+}
+EXPORT_SYMBOL_GPL(pmic_glink_client_register);
int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
{
struct pmic_glink *pg = client->pg;
+ bool timeout_reached = false;
+ unsigned long start;
+ int ret;
+
+ guard(mutex)(&pg->state_lock);
+ if (!pg->ept) {
+ return -ECONNRESET;
+ }
+
+ start = jiffies;
+ for (;;) {
+ ret = rpmsg_send(pg->ept, data, len);
+ if (ret != -EAGAIN)
+ break;
- return rpmsg_send(pg->ept, data, len);
+ if (timeout_reached) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+
+ usleep_range(1000, 5000);
+ timeout_reached = time_after(jiffies, start + PMIC_GLINK_SEND_TIMEOUT);
+ }
+
+ return ret;
}
EXPORT_SYMBOL_GPL(pmic_glink_send);
@@ -107,6 +148,7 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
struct pmic_glink_client *client;
struct pmic_glink_hdr *hdr;
struct pmic_glink *pg = dev_get_drvdata(&rpdev->dev);
+ unsigned long flags;
if (len < sizeof(*hdr)) {
dev_warn(pg->dev, "ignoring truncated message\n");
@@ -115,10 +157,12 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
hdr = data;
+ spin_lock_irqsave(&pg->client_lock, flags);
list_for_each_entry(client, &pg->clients, node) {
if (client->id == le32_to_cpu(hdr->owner))
client->cb(data, len, client->priv);
}
+ spin_unlock_irqrestore(&pg->client_lock, flags);
return 0;
}
@@ -158,18 +202,21 @@ static void pmic_glink_state_notify_clients(struct pmic_glink *pg)
{
struct pmic_glink_client *client;
unsigned int new_state = pg->client_state;
+ unsigned long flags;
if (pg->client_state != SERVREG_SERVICE_STATE_UP) {
if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
new_state = SERVREG_SERVICE_STATE_UP;
} else {
- if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
+ if (pg->pdr_state == SERVREG_SERVICE_STATE_DOWN || !pg->ept)
new_state = SERVREG_SERVICE_STATE_DOWN;
}
if (new_state != pg->client_state) {
+ spin_lock_irqsave(&pg->client_lock, flags);
list_for_each_entry(client, &pg->clients, node)
client->pdr_notify(client->priv, new_state);
+ spin_unlock_irqrestore(&pg->client_lock, flags);
pg->client_state = new_state;
}
}
@@ -178,51 +225,42 @@ static void pmic_glink_pdr_callback(int state, char *svc_path, void *priv)
{
struct pmic_glink *pg = priv;
- mutex_lock(&pg->state_lock);
+ guard(mutex)(&pg->state_lock);
pg->pdr_state = state;
pmic_glink_state_notify_clients(pg);
- mutex_unlock(&pg->state_lock);
}
static int pmic_glink_rpmsg_probe(struct rpmsg_device *rpdev)
{
- struct pmic_glink *pg = __pmic_glink;
- int ret = 0;
+ struct pmic_glink *pg;
- mutex_lock(&__pmic_glink_lock);
- if (!pg) {
- ret = dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n");
- goto out_unlock;
- }
+ guard(mutex)(&__pmic_glink_lock);
+ pg = __pmic_glink;
+ if (!pg)
+ return dev_err_probe(&rpdev->dev, -ENODEV, "no pmic_glink device to attach to\n");
dev_set_drvdata(&rpdev->dev, pg);
- mutex_lock(&pg->state_lock);
+ guard(mutex)(&pg->state_lock);
pg->ept = rpdev->ept;
pmic_glink_state_notify_clients(pg);
- mutex_unlock(&pg->state_lock);
-out_unlock:
- mutex_unlock(&__pmic_glink_lock);
- return ret;
+ return 0;
}
static void pmic_glink_rpmsg_remove(struct rpmsg_device *rpdev)
{
struct pmic_glink *pg;
- mutex_lock(&__pmic_glink_lock);
+ guard(mutex)(&__pmic_glink_lock);
pg = __pmic_glink;
if (!pg)
- goto out_unlock;
+ return;
- mutex_lock(&pg->state_lock);
+ guard(mutex)(&pg->state_lock);
pg->ept = NULL;
pmic_glink_state_notify_clients(pg);
- mutex_unlock(&pg->state_lock);
-out_unlock:
- mutex_unlock(&__pmic_glink_lock);
}
static const struct rpmsg_device_id pmic_glink_rpmsg_id_match[] = {
@@ -256,7 +294,7 @@ static int pmic_glink_probe(struct platform_device *pdev)
pg->dev = &pdev->dev;
INIT_LIST_HEAD(&pg->clients);
- mutex_init(&pg->client_lock);
+ spin_lock_init(&pg->client_lock);
mutex_init(&pg->state_lock);
match_data = (unsigned long *)of_device_get_match_data(&pdev->dev);
@@ -329,21 +367,15 @@ static void pmic_glink_remove(struct platform_device *pdev)
if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
- mutex_lock(&__pmic_glink_lock);
+ guard(mutex)(&__pmic_glink_lock);
__pmic_glink = NULL;
- mutex_unlock(&__pmic_glink_lock);
}
-static const unsigned long pmic_glink_sc8180x_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
- BIT(PMIC_GLINK_CLIENT_ALTMODE);
-
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
BIT(PMIC_GLINK_CLIENT_UCSI);
static const struct of_device_id pmic_glink_of_match[] = {
- { .compatible = "qcom,sc8180x-pmic-glink", .data = &pmic_glink_sc8180x_client_mask },
- { .compatible = "qcom,sc8280xp-pmic-glink", .data = &pmic_glink_sc8180x_client_mask },
{ .compatible = "qcom,pmic-glink", .data = &pmic_glink_sm8450_client_mask },
{}
};
@@ -351,7 +383,7 @@ MODULE_DEVICE_TABLE(of, pmic_glink_of_match);
static struct platform_driver pmic_glink_driver = {
.probe = pmic_glink_probe,
- .remove_new = pmic_glink_remove,
+ .remove = pmic_glink_remove,
.driver = {
.name = "qcom_pmic_glink",
.of_match_table = pmic_glink_of_match,
@@ -360,8 +392,17 @@ static struct platform_driver pmic_glink_driver = {
static int pmic_glink_init(void)
{
- platform_driver_register(&pmic_glink_driver);
- register_rpmsg_driver(&pmic_glink_rpmsg_driver);
+ int ret;
+
+ ret = platform_driver_register(&pmic_glink_driver);
+ if (ret < 0)
+ return ret;
+
+ ret = register_rpmsg_driver(&pmic_glink_rpmsg_driver);
+ if (ret < 0) {
+ platform_driver_unregister(&pmic_glink_driver);
+ return ret;
+ }
return 0;
}
diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index b3808fc24c69..7f11acd33323 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -5,6 +5,7 @@
*/
#include <linux/auxiliary_bus.h>
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -20,7 +21,7 @@
#include <linux/soc/qcom/pmic_glink.h>
-#define PMIC_GLINK_MAX_PORTS 2
+#define PMIC_GLINK_MAX_PORTS 3
#define USBC_SC8180X_NOTIFY_IND 0x13
#define USBC_CMD_WRITE_REQ 0x15
@@ -114,7 +115,7 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm
* The USBC_CMD_WRITE_REQ ack doesn't identify the request, so wait for
* one ack at a time.
*/
- mutex_lock(&altmode->lock);
+ guard(mutex)(&altmode->lock);
req.hdr.owner = cpu_to_le32(altmode->owner_id);
req.hdr.type = cpu_to_le32(PMIC_GLINK_REQ_RESP);
@@ -125,18 +126,16 @@ static int pmic_glink_altmode_request(struct pmic_glink_altmode *altmode, u32 cm
ret = pmic_glink_send(altmode->client, &req, sizeof(req));
if (ret) {
dev_err(altmode->dev, "failed to send altmode request: %#x (%d)\n", cmd, ret);
- goto out_unlock;
+ return ret;
}
left = wait_for_completion_timeout(&altmode->pan_ack, 5 * HZ);
if (!left) {
dev_err(altmode->dev, "timeout waiting for altmode request ack for: %#x\n", cmd);
- ret = -ETIMEDOUT;
+ return -ETIMEDOUT;
}
-out_unlock:
- mutex_unlock(&altmode->lock);
- return ret;
+ return 0;
}
static void pmic_glink_altmode_enable_dp(struct pmic_glink_altmode *altmode,
@@ -219,21 +218,29 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
{
struct pmic_glink_altmode_port *alt_port = work_to_altmode_port(work);
struct pmic_glink_altmode *altmode = alt_port->altmode;
+ enum drm_connector_status conn_status;
typec_switch_set(alt_port->typec_switch, alt_port->orientation);
- if (alt_port->svid == USB_TYPEC_DP_SID && alt_port->mode == 0xff)
- pmic_glink_altmode_safe(altmode, alt_port);
- else if (alt_port->svid == USB_TYPEC_DP_SID)
- pmic_glink_altmode_enable_dp(altmode, alt_port, alt_port->mode,
- alt_port->hpd_state, alt_port->hpd_irq);
- else
- pmic_glink_altmode_enable_usb(altmode, alt_port);
+ if (alt_port->svid == USB_TYPEC_DP_SID) {
+ if (alt_port->mode == 0xff) {
+ pmic_glink_altmode_safe(altmode, alt_port);
+ } else {
+ pmic_glink_altmode_enable_dp(altmode, alt_port,
+ alt_port->mode,
+ alt_port->hpd_state,
+ alt_port->hpd_irq);
+ }
+
+ if (alt_port->hpd_state)
+ conn_status = connector_status_connected;
+ else
+ conn_status = connector_status_disconnected;
- drm_aux_hpd_bridge_notify(&alt_port->bridge->dev,
- alt_port->hpd_state ?
- connector_status_connected :
- connector_status_disconnected);
+ drm_aux_hpd_bridge_notify(&alt_port->bridge->dev, conn_status);
+ } else {
+ pmic_glink_altmode_enable_usb(altmode, alt_port);
+ }
pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index);
}
@@ -520,12 +527,17 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
return ret;
}
- altmode->client = devm_pmic_glink_register_client(dev,
- altmode->owner_id,
- pmic_glink_altmode_callback,
- pmic_glink_altmode_pdr_notify,
- altmode);
- return PTR_ERR_OR_ZERO(altmode->client);
+ altmode->client = devm_pmic_glink_client_alloc(dev,
+ altmode->owner_id,
+ pmic_glink_altmode_callback,
+ pmic_glink_altmode_pdr_notify,
+ altmode);
+ if (IS_ERR(altmode->client))
+ return PTR_ERR(altmode->client);
+
+ pmic_glink_client_register(altmode->client);
+
+ return 0;
}
static const struct auxiliary_device_id pmic_glink_altmode_id_table[] = {
diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.c b/drivers/soc/qcom/pmic_pdcharger_ulog.c
index 238cd38589dc..39f412bbf2c1 100644
--- a/drivers/soc/qcom/pmic_pdcharger_ulog.c
+++ b/drivers/soc/qcom/pmic_pdcharger_ulog.c
@@ -150,6 +150,10 @@ static const struct rpmsg_device_id pmic_pdcharger_ulog_rpmsg_id_match[] = {
{ "PMIC_LOGS_ADSP_APPS" },
{}
};
+/*
+ * No MODULE_DEVICE_TABLE intentionally: that's a debugging module, to be
+ * loaded manually only.
+ */
static struct rpmsg_driver pmic_pdcharger_ulog_rpmsg_driver = {
.probe = pmic_pdcharger_ulog_rpmsg_probe,
diff --git a/drivers/soc/qcom/pmic_pdcharger_ulog.h b/drivers/soc/qcom/pmic_pdcharger_ulog.h
index 152e3a6b5480..1cfa58f0e34c 100644
--- a/drivers/soc/qcom/pmic_pdcharger_ulog.h
+++ b/drivers/soc/qcom/pmic_pdcharger_ulog.h
@@ -18,7 +18,7 @@ TRACE_EVENT(pmic_pdcharger_ulog_msg,
__string(msg, msg)
),
TP_fast_assign(
- __assign_str(msg, msg);
+ __assign_str(msg);
),
TP_printk("%s", __get_str(msg))
);
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index 2e8f24d5da80..4cb959106efa 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -585,7 +585,8 @@ int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl)
for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) {
freq = clk_round_rate(se->clk, freq + 1);
- if (freq <= 0 || freq == se->clk_perf_tbl[i - 1])
+ if (freq <= 0 ||
+ (i > 0 && freq == se->clk_perf_tbl[i - 1]))
break;
se->clk_perf_tbl[i] = freq;
}
diff --git a/drivers/soc/qcom/qcom-pbs.c b/drivers/soc/qcom/qcom-pbs.c
index 6af49b5060e5..1cc5d045f9dd 100644
--- a/drivers/soc/qcom/qcom-pbs.c
+++ b/drivers/soc/qcom/qcom-pbs.c
@@ -3,6 +3,7 @@
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/module.h>
@@ -83,16 +84,16 @@ int qcom_pbs_trigger_event(struct pbs_dev *pbs, u8 bitmap)
if (IS_ERR_OR_NULL(pbs))
return -EINVAL;
- mutex_lock(&pbs->lock);
+ guard(mutex)(&pbs->lock);
ret = regmap_read(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, &val);
if (ret < 0)
- goto out;
+ return ret;
if (val == PBS_CLIENT_SCRATCH2_ERROR) {
/* PBS error - clear SCRATCH2 register */
ret = regmap_write(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, 0);
if (ret < 0)
- goto out;
+ return ret;
}
for (bit_pos = 0; bit_pos < 8; bit_pos++) {
@@ -103,37 +104,31 @@ int qcom_pbs_trigger_event(struct pbs_dev *pbs, u8 bitmap)
ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2,
BIT(bit_pos), 0);
if (ret < 0)
- goto out_clear_scratch1;
+ break;
/* Set the PBS sequence bit position */
ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1,
BIT(bit_pos), BIT(bit_pos));
if (ret < 0)
- goto out_clear_scratch1;
+ break;
/* Initiate the SW trigger */
ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_TRIG_CTL,
PBS_CLIENT_SW_TRIG_BIT, PBS_CLIENT_SW_TRIG_BIT);
if (ret < 0)
- goto out_clear_scratch1;
+ break;
ret = qcom_pbs_wait_for_ack(pbs, bit_pos);
if (ret < 0)
- goto out_clear_scratch1;
+ break;
/* Clear the PBS sequence bit position */
regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, BIT(bit_pos), 0);
regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH2, BIT(bit_pos), 0);
}
-out_clear_scratch1:
/* Clear all the requested bitmap */
- ret = regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, bitmap, 0);
-
-out:
- mutex_unlock(&pbs->lock);
-
- return ret;
+ return regmap_update_bits(pbs->regmap, pbs->base + PBS_CLIENT_SCRATCH1, bitmap, 0);
}
EXPORT_SYMBOL_GPL(qcom_pbs_trigger_event);
@@ -148,11 +143,11 @@ EXPORT_SYMBOL_GPL(qcom_pbs_trigger_event);
*/
struct pbs_dev *get_pbs_client_device(struct device *dev)
{
- struct device_node *pbs_dev_node;
struct platform_device *pdev;
struct pbs_dev *pbs;
- pbs_dev_node = of_parse_phandle(dev->of_node, "qcom,pbs", 0);
+ struct device_node *pbs_dev_node __free(device_node) = of_parse_phandle(dev->of_node,
+ "qcom,pbs", 0);
if (!pbs_dev_node) {
dev_err(dev, "Missing qcom,pbs property\n");
return ERR_PTR(-ENODEV);
@@ -161,28 +156,23 @@ struct pbs_dev *get_pbs_client_device(struct device *dev)
pdev = of_find_device_by_node(pbs_dev_node);
if (!pdev) {
dev_err(dev, "Unable to find PBS dev_node\n");
- pbs = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
pbs = platform_get_drvdata(pdev);
if (!pbs) {
dev_err(dev, "Cannot get pbs instance from %s\n", dev_name(&pdev->dev));
platform_device_put(pdev);
- pbs = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
pbs->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
if (!pbs->link) {
dev_err(&pdev->dev, "Failed to create device link to consumer %s\n", dev_name(dev));
platform_device_put(pdev);
- pbs = ERR_PTR(-EINVAL);
- goto out;
+ return ERR_PTR(-EINVAL);
}
-out:
- of_node_put(pbs_dev_node);
return pbs;
}
EXPORT_SYMBOL_GPL(get_pbs_client_device);
diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index ca2f6b7629ce..a543ab9bee6c 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/soc/qcom/qcom_aoss.h>
#define CREATE_TRACE_POINTS
@@ -358,7 +359,7 @@ static int qmp_cdev_set_cur_state(struct thermal_cooling_device *cdev,
return 0;
ret = qmp_send(qmp_cdev->qmp, "{class: volt_flr, event:zero_temp, res:%s, value:%s}",
- qmp_cdev->name, cdev_state ? "on" : "off");
+ qmp_cdev->name, str_on_off(cdev_state));
if (!ret)
qmp_cdev->state = cdev_state;
@@ -394,7 +395,7 @@ static int qmp_cooling_device_add(struct qmp *qmp,
static int qmp_cooling_devices_register(struct qmp *qmp)
{
- struct device_node *np, *child;
+ struct device_node *np;
int count = 0;
int ret;
@@ -407,15 +408,13 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
if (!qmp->cooling_devs)
return -ENOMEM;
- for_each_available_child_of_node(np, child) {
+ for_each_available_child_of_node_scoped(np, child) {
if (!of_property_present(child, "#cooling-cells"))
continue;
ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
child);
- if (ret) {
- of_node_put(child);
+ if (ret)
goto unroll;
- }
}
if (!count)
@@ -666,7 +665,7 @@ static struct platform_driver qmp_driver = {
.suppress_bind_attrs = true,
},
.probe = qmp_probe,
- .remove_new = qmp_remove,
+ .remove = qmp_remove,
};
module_platform_driver(qmp_driver);
diff --git a/drivers/soc/qcom/qcom_gsbi.c b/drivers/soc/qcom/qcom_gsbi.c
index f04b9a324ea9..8f1158e0c631 100644
--- a/drivers/soc/qcom/qcom_gsbi.c
+++ b/drivers/soc/qcom/qcom_gsbi.c
@@ -232,7 +232,7 @@ static struct platform_driver gsbi_driver = {
.of_match_table = gsbi_dt_match,
},
.probe = gsbi_probe,
- .remove_new = gsbi_remove,
+ .remove = gsbi_remove,
};
module_platform_driver(gsbi_driver);
diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
new file mode 100644
index 000000000000..3abea241b1c4
--- /dev/null
+++ b/drivers/soc/qcom/qcom_pd_mapper.c
@@ -0,0 +1,720 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Qualcomm Protection Domain mapper
+ *
+ * Copyright (c) 2023 Linaro Ltd.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/refcount.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/qmi.h>
+
+#include "pdr_internal.h"
+
+#define SERVREG_QMI_VERSION 0x101
+#define SERVREG_QMI_INSTANCE 0
+
+#define TMS_SERVREG_SERVICE "tms/servreg"
+
+struct qcom_pdm_domain_data {
+ const char *domain;
+ u32 instance_id;
+ /* NULL-terminated array */
+ const char * services[];
+};
+
+struct qcom_pdm_domain {
+ struct list_head list;
+ const char *name;
+ u32 instance_id;
+};
+
+struct qcom_pdm_service {
+ struct list_head list;
+ struct list_head domains;
+ const char *name;
+};
+
+struct qcom_pdm_data {
+ refcount_t refcnt;
+ struct qmi_handle handle;
+ struct list_head services;
+};
+
+static DEFINE_MUTEX(qcom_pdm_mutex); /* protects __qcom_pdm_data */
+static struct qcom_pdm_data *__qcom_pdm_data;
+
+static struct qcom_pdm_service *qcom_pdm_find(struct qcom_pdm_data *data,
+ const char *name)
+{
+ struct qcom_pdm_service *service;
+
+ list_for_each_entry(service, &data->services, list) {
+ if (!strcmp(service->name, name))
+ return service;
+ }
+
+ return NULL;
+}
+
+static int qcom_pdm_add_service_domain(struct qcom_pdm_data *data,
+ const char *service_name,
+ const char *domain_name,
+ u32 instance_id)
+{
+ struct qcom_pdm_service *service;
+ struct qcom_pdm_domain *domain;
+
+ service = qcom_pdm_find(data, service_name);
+ if (service) {
+ list_for_each_entry(domain, &service->domains, list) {
+ if (!strcmp(domain->name, domain_name))
+ return -EBUSY;
+ }
+ } else {
+ service = kzalloc(sizeof(*service), GFP_KERNEL);
+ if (!service)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&service->domains);
+ service->name = service_name;
+
+ list_add_tail(&service->list, &data->services);
+ }
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain) {
+ if (list_empty(&service->domains)) {
+ list_del(&service->list);
+ kfree(service);
+ }
+
+ return -ENOMEM;
+ }
+
+ domain->name = domain_name;
+ domain->instance_id = instance_id;
+ list_add_tail(&domain->list, &service->domains);
+
+ return 0;
+}
+
+static int qcom_pdm_add_domain(struct qcom_pdm_data *data,
+ const struct qcom_pdm_domain_data *domain)
+{
+ int ret;
+ int i;
+
+ ret = qcom_pdm_add_service_domain(data,
+ TMS_SERVREG_SERVICE,
+ domain->domain,
+ domain->instance_id);
+ if (ret)
+ return ret;
+
+ for (i = 0; domain->services[i]; i++) {
+ ret = qcom_pdm_add_service_domain(data,
+ domain->services[i],
+ domain->domain,
+ domain->instance_id);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+
+}
+
+static void qcom_pdm_free_domains(struct qcom_pdm_data *data)
+{
+ struct qcom_pdm_service *service, *tservice;
+ struct qcom_pdm_domain *domain, *tdomain;
+
+ list_for_each_entry_safe(service, tservice, &data->services, list) {
+ list_for_each_entry_safe(domain, tdomain, &service->domains, list) {
+ list_del(&domain->list);
+ kfree(domain);
+ }
+
+ list_del(&service->list);
+ kfree(service);
+ }
+}
+
+static void qcom_pdm_get_domain_list(struct qmi_handle *qmi,
+ struct sockaddr_qrtr *sq,
+ struct qmi_txn *txn,
+ const void *decoded)
+{
+ struct qcom_pdm_data *data = container_of(qmi, struct qcom_pdm_data, handle);
+ const struct servreg_get_domain_list_req *req = decoded;
+ struct servreg_get_domain_list_resp *rsp;
+ struct qcom_pdm_service *service;
+ u32 offset;
+ int ret;
+
+ rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
+ if (!rsp)
+ return;
+
+ offset = req->domain_offset_valid ? req->domain_offset : 0;
+
+ rsp->resp.result = QMI_RESULT_SUCCESS_V01;
+ rsp->resp.error = QMI_ERR_NONE_V01;
+
+ rsp->db_rev_count_valid = true;
+ rsp->db_rev_count = 1;
+
+ rsp->total_domains_valid = true;
+ rsp->total_domains = 0;
+
+ mutex_lock(&qcom_pdm_mutex);
+
+ service = qcom_pdm_find(data, req->service_name);
+ if (service) {
+ struct qcom_pdm_domain *domain;
+
+ rsp->domain_list_valid = true;
+ rsp->domain_list_len = 0;
+
+ list_for_each_entry(domain, &service->domains, list) {
+ u32 i = rsp->total_domains++;
+
+ if (i >= offset && i < SERVREG_DOMAIN_LIST_LENGTH) {
+ u32 j = rsp->domain_list_len++;
+
+ strscpy(rsp->domain_list[j].name, domain->name,
+ sizeof(rsp->domain_list[i].name));
+ rsp->domain_list[j].instance = domain->instance_id;
+
+ pr_debug("PDM: found %s / %d\n", domain->name,
+ domain->instance_id);
+ }
+ }
+ }
+
+ pr_debug("PDM: service '%s' offset %d returning %d domains (of %d)\n", req->service_name,
+ req->domain_offset_valid ? req->domain_offset : -1, rsp->domain_list_len, rsp->total_domains);
+
+ ret = qmi_send_response(qmi, sq, txn, SERVREG_GET_DOMAIN_LIST_REQ,
+ SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
+ servreg_get_domain_list_resp_ei, rsp);
+ if (ret)
+ pr_err("Error sending servreg response: %d\n", ret);
+
+ mutex_unlock(&qcom_pdm_mutex);
+
+ kfree(rsp);
+}
+
+static void qcom_pdm_pfr(struct qmi_handle *qmi,
+ struct sockaddr_qrtr *sq,
+ struct qmi_txn *txn,
+ const void *decoded)
+{
+ const struct servreg_loc_pfr_req *req = decoded;
+ struct servreg_loc_pfr_resp rsp = {};
+ int ret;
+
+ pr_warn_ratelimited("PDM: service '%s' crash: '%s'\n", req->service, req->reason);
+
+ rsp.rsp.result = QMI_RESULT_SUCCESS_V01;
+ rsp.rsp.error = QMI_ERR_NONE_V01;
+
+ ret = qmi_send_response(qmi, sq, txn, SERVREG_LOC_PFR_REQ,
+ SERVREG_LOC_PFR_RESP_MAX_LEN,
+ servreg_loc_pfr_resp_ei, &rsp);
+ if (ret)
+ pr_err("Error sending servreg response: %d\n", ret);
+}
+
+static const struct qmi_msg_handler qcom_pdm_msg_handlers[] = {
+ {
+ .type = QMI_REQUEST,
+ .msg_id = SERVREG_GET_DOMAIN_LIST_REQ,
+ .ei = servreg_get_domain_list_req_ei,
+ .decoded_size = sizeof(struct servreg_get_domain_list_req),
+ .fn = qcom_pdm_get_domain_list,
+ },
+ {
+ .type = QMI_REQUEST,
+ .msg_id = SERVREG_LOC_PFR_REQ,
+ .ei = servreg_loc_pfr_req_ei,
+ .decoded_size = sizeof(struct servreg_loc_pfr_req),
+ .fn = qcom_pdm_pfr,
+ },
+ { },
+};
+
+static const struct qcom_pdm_domain_data adsp_audio_pd = {
+ .domain = "msm/adsp/audio_pd",
+ .instance_id = 74,
+ .services = {
+ "avs/audio",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data adsp_charger_pd = {
+ .domain = "msm/adsp/charger_pd",
+ .instance_id = 74,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data adsp_root_pd = {
+ .domain = "msm/adsp/root_pd",
+ .instance_id = 74,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data adsp_root_pd_pdr = {
+ .domain = "msm/adsp/root_pd",
+ .instance_id = 74,
+ .services = {
+ "tms/pdr_enabled",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data adsp_sensor_pd = {
+ .domain = "msm/adsp/sensor_pd",
+ .instance_id = 74,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data msm8996_adsp_audio_pd = {
+ .domain = "msm/adsp/audio_pd",
+ .instance_id = 4,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data msm8996_adsp_root_pd = {
+ .domain = "msm/adsp/root_pd",
+ .instance_id = 4,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data cdsp_root_pd = {
+ .domain = "msm/cdsp/root_pd",
+ .instance_id = 76,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data slpi_root_pd = {
+ .domain = "msm/slpi/root_pd",
+ .instance_id = 90,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data slpi_sensor_pd = {
+ .domain = "msm/slpi/sensor_pd",
+ .instance_id = 90,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data mpss_root_pd = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 180,
+ .services = {
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data mpss_root_pd_gps = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 180,
+ .services = {
+ "gps/gps_service",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data mpss_root_pd_gps_pdr = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 180,
+ .services = {
+ "gps/gps_service",
+ "tms/pdr_enabled",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data msm8996_mpss_root_pd = {
+ .domain = "msm/modem/root_pd",
+ .instance_id = 100,
+ .services = { NULL },
+};
+
+static const struct qcom_pdm_domain_data mpss_wlan_pd = {
+ .domain = "msm/modem/wlan_pd",
+ .instance_id = 180,
+ .services = {
+ "kernel/elf_loader",
+ "wlan/fw",
+ NULL,
+ },
+};
+
+static const struct qcom_pdm_domain_data *msm8996_domains[] = {
+ &msm8996_adsp_audio_pd,
+ &msm8996_adsp_root_pd,
+ &msm8996_mpss_root_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *msm8998_domains[] = {
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *qcm2290_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *qcs404_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc7180_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_sensor_pd,
+ &mpss_root_pd_gps_pdr,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc7280_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_charger_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps_pdr,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc8180x_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_charger_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sc8280xp_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_charger_pd,
+ &cdsp_root_pd,
+ NULL,
+};
+
+/* Unlike SDM660, SDM630/636 lack CDSP */
+static const struct qcom_pdm_domain_data *sdm630_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sdm660_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sdm670_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sdm845_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd,
+ &mpss_wlan_pd,
+ &slpi_root_pd,
+ &slpi_sensor_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm6115_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm6350_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm7150_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8150_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &mpss_wlan_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8250_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &cdsp_root_pd,
+ &slpi_root_pd,
+ &slpi_sensor_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8350_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd_pdr,
+ &adsp_charger_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ &slpi_root_pd,
+ &slpi_sensor_pd,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *sm8550_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_charger_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ &mpss_root_pd_gps,
+ NULL,
+};
+
+static const struct qcom_pdm_domain_data *x1e80100_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_charger_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ NULL,
+};
+
+static const struct of_device_id qcom_pdm_domains[] __maybe_unused = {
+ { .compatible = "qcom,apq8016", .data = NULL, },
+ { .compatible = "qcom,apq8064", .data = NULL, },
+ { .compatible = "qcom,apq8074", .data = NULL, },
+ { .compatible = "qcom,apq8084", .data = NULL, },
+ { .compatible = "qcom,apq8096", .data = msm8996_domains, },
+ { .compatible = "qcom,msm8226", .data = NULL, },
+ { .compatible = "qcom,msm8909", .data = NULL, },
+ { .compatible = "qcom,msm8916", .data = NULL, },
+ { .compatible = "qcom,msm8939", .data = NULL, },
+ { .compatible = "qcom,msm8974", .data = NULL, },
+ { .compatible = "qcom,msm8996", .data = msm8996_domains, },
+ { .compatible = "qcom,msm8998", .data = msm8998_domains, },
+ { .compatible = "qcom,qcm2290", .data = qcm2290_domains, },
+ { .compatible = "qcom,qcm6490", .data = sc7280_domains, },
+ { .compatible = "qcom,qcs404", .data = qcs404_domains, },
+ { .compatible = "qcom,sc7180", .data = sc7180_domains, },
+ { .compatible = "qcom,sc7280", .data = sc7280_domains, },
+ { .compatible = "qcom,sc8180x", .data = sc8180x_domains, },
+ { .compatible = "qcom,sc8280xp", .data = sc8280xp_domains, },
+ { .compatible = "qcom,sdm630", .data = sdm630_domains, },
+ { .compatible = "qcom,sdm636", .data = sdm630_domains, },
+ { .compatible = "qcom,sda660", .data = sdm660_domains, },
+ { .compatible = "qcom,sdm660", .data = sdm660_domains, },
+ { .compatible = "qcom,sdm670", .data = sdm670_domains, },
+ { .compatible = "qcom,sdm845", .data = sdm845_domains, },
+ { .compatible = "qcom,sm4250", .data = sm6115_domains, },
+ { .compatible = "qcom,sm6115", .data = sm6115_domains, },
+ { .compatible = "qcom,sm6350", .data = sm6350_domains, },
+ { .compatible = "qcom,sm7150", .data = sm7150_domains, },
+ { .compatible = "qcom,sm7225", .data = sm6350_domains, },
+ { .compatible = "qcom,sm7325", .data = sc7280_domains, },
+ { .compatible = "qcom,sm8150", .data = sm8150_domains, },
+ { .compatible = "qcom,sm8250", .data = sm8250_domains, },
+ { .compatible = "qcom,sm8350", .data = sm8350_domains, },
+ { .compatible = "qcom,sm8450", .data = sm8350_domains, },
+ { .compatible = "qcom,sm8550", .data = sm8550_domains, },
+ { .compatible = "qcom,sm8650", .data = sm8550_domains, },
+ { .compatible = "qcom,x1e80100", .data = x1e80100_domains, },
+ { .compatible = "qcom,x1p42100", .data = x1e80100_domains, },
+ {},
+};
+
+static void qcom_pdm_stop(struct qcom_pdm_data *data)
+{
+ qcom_pdm_free_domains(data);
+
+ /* The server is removed automatically */
+ qmi_handle_release(&data->handle);
+
+ kfree(data);
+}
+
+static struct qcom_pdm_data *qcom_pdm_start(void)
+{
+ const struct qcom_pdm_domain_data * const *domains;
+ const struct of_device_id *match;
+ struct qcom_pdm_data *data;
+ struct device_node *root;
+ int ret, i;
+
+ root = of_find_node_by_path("/");
+ if (!root)
+ return ERR_PTR(-ENODEV);
+
+ match = of_match_node(qcom_pdm_domains, root);
+ of_node_put(root);
+ if (!match) {
+ pr_notice("PDM: no support for the platform, userspace daemon might be required.\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ domains = match->data;
+ if (!domains) {
+ pr_debug("PDM: no domains\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&data->services);
+
+ ret = qmi_handle_init(&data->handle, SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
+ NULL, qcom_pdm_msg_handlers);
+ if (ret) {
+ kfree(data);
+ return ERR_PTR(ret);
+ }
+
+ refcount_set(&data->refcnt, 1);
+
+ for (i = 0; domains[i]; i++) {
+ ret = qcom_pdm_add_domain(data, domains[i]);
+ if (ret)
+ goto err_stop;
+ }
+
+ ret = qmi_add_server(&data->handle, SERVREG_LOCATOR_SERVICE,
+ SERVREG_QMI_VERSION, SERVREG_QMI_INSTANCE);
+ if (ret) {
+ pr_err("PDM: error adding server %d\n", ret);
+ goto err_stop;
+ }
+
+ return data;
+
+err_stop:
+ qcom_pdm_stop(data);
+
+ return ERR_PTR(ret);
+}
+
+static int qcom_pdm_probe(struct auxiliary_device *auxdev,
+ const struct auxiliary_device_id *id)
+
+{
+ struct qcom_pdm_data *data;
+ int ret = 0;
+
+ mutex_lock(&qcom_pdm_mutex);
+
+ if (!__qcom_pdm_data) {
+ data = qcom_pdm_start();
+
+ if (IS_ERR(data))
+ ret = PTR_ERR(data);
+ else
+ __qcom_pdm_data = data;
+ } else {
+ refcount_inc(&__qcom_pdm_data->refcnt);
+ }
+
+ auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
+
+ mutex_unlock(&qcom_pdm_mutex);
+
+ return ret;
+}
+
+static void qcom_pdm_remove(struct auxiliary_device *auxdev)
+{
+ struct qcom_pdm_data *data;
+
+ data = auxiliary_get_drvdata(auxdev);
+ if (!data)
+ return;
+
+ if (refcount_dec_and_mutex_lock(&data->refcnt, &qcom_pdm_mutex)) {
+ __qcom_pdm_data = NULL;
+ qcom_pdm_stop(data);
+ mutex_unlock(&qcom_pdm_mutex);
+ }
+}
+
+static const struct auxiliary_device_id qcom_pdm_table[] = {
+ { .name = "qcom_common.pd-mapper" },
+ {},
+};
+MODULE_DEVICE_TABLE(auxiliary, qcom_pdm_table);
+
+static struct auxiliary_driver qcom_pdm_drv = {
+ .name = "qcom-pdm-mapper",
+ .id_table = qcom_pdm_table,
+ .probe = qcom_pdm_probe,
+ .remove = qcom_pdm_remove,
+};
+module_auxiliary_driver(qcom_pdm_drv);
+
+MODULE_DESCRIPTION("Qualcomm Protection Domain Mapper");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/qcom/qcom_pdr_msg.c b/drivers/soc/qcom/qcom_pdr_msg.c
new file mode 100644
index 000000000000..ca98932140d8
--- /dev/null
+++ b/drivers/soc/qcom/qcom_pdr_msg.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/soc/qcom/qmi.h>
+
+#include "pdr_internal.h"
+
+static const struct qmi_elem_info servreg_location_entry_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ name),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ instance),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ service_data_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct servreg_location_entry,
+ service_data),
+ },
+ {}
+};
+
+const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_get_domain_list_req,
+ service_name),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_req,
+ domain_offset_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_req,
+ domain_offset),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_get_domain_list_req_ei);
+
+const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ total_domains_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ total_domains),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ db_rev_count_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ db_rev_count),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ domain_list_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ domain_list_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
+ .elem_size = sizeof(struct servreg_location_entry),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct servreg_get_domain_list_resp,
+ domain_list),
+ .ei_array = servreg_location_entry_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_get_domain_list_resp_ei);
+
+const struct qmi_elem_info servreg_register_listener_req_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_register_listener_req,
+ enable),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_register_listener_req,
+ service_path),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_register_listener_req_ei);
+
+const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_register_listener_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_register_listener_resp,
+ curr_state_valid),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum servreg_service_state),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct servreg_register_listener_resp,
+ curr_state),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_register_listener_resp_ei);
+
+const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_restart_pd_req,
+ service_path),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_restart_pd_req_ei);
+
+const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_restart_pd_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_restart_pd_resp_ei);
+
+const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_state_updated_ind,
+ curr_state),
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_state_updated_ind,
+ service_path),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x03,
+ .offset = offsetof(struct servreg_state_updated_ind,
+ transaction_id),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_state_updated_ind_ei);
+
+const struct qmi_elem_info servreg_set_ack_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_set_ack_req,
+ service_path),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_set_ack_req,
+ transaction_id),
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_set_ack_req_ei);
+
+const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_set_ack_resp,
+ resp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_set_ack_resp_ei);
+
+const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x01,
+ .offset = offsetof(struct servreg_loc_pfr_req, service)
+ },
+ {
+ .data_type = QMI_STRING,
+ .elem_len = SERVREG_NAME_LENGTH + 1,
+ .elem_size = sizeof(char),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_loc_pfr_req, reason)
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_loc_pfr_req_ei);
+
+const struct qmi_elem_info servreg_loc_pfr_resp_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof_field(struct servreg_loc_pfr_resp, rsp),
+ .tlv_type = 0x02,
+ .offset = offsetof(struct servreg_loc_pfr_resp, rsp),
+ .ei_array = qmi_response_type_v01_ei,
+ },
+ {}
+};
+EXPORT_SYMBOL_GPL(servreg_loc_pfr_resp_ei);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Qualcomm Protection Domain messages data");
diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c
index 0216fc24f2ca..5de99cf59b9f 100644
--- a/drivers/soc/qcom/qcom_stats.c
+++ b/drivers/soc/qcom/qcom_stats.c
@@ -35,11 +35,15 @@ static const struct subsystem_data subsystems[] = {
{ "wpss", 605, 13 },
{ "adsp", 606, 2 },
{ "cdsp", 607, 5 },
+ { "cdsp1", 607, 12 },
+ { "gpdsp0", 607, 17 },
+ { "gpdsp1", 607, 18 },
{ "slpi", 608, 3 },
{ "gpu", 609, 0 },
{ "display", 610, 0 },
{ "adsp_island", 613, 2 },
{ "slpi_island", 613, 3 },
+ { "apss", 631, QCOM_SMEM_HOST_ANY },
};
struct stats_config {
@@ -270,7 +274,7 @@ MODULE_DEVICE_TABLE(of, qcom_stats_table);
static struct platform_driver qcom_stats = {
.probe = qcom_stats_probe,
- .remove_new = qcom_stats_remove,
+ .remove = qcom_stats_remove,
.driver = {
.name = "qcom_stats",
.of_match_table = qcom_stats_table,
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index bb98b06e87f8..bc6d6379d8b1 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -195,8 +195,8 @@ static void qmi_send_new_lookup(struct qmi_handle *qmi, struct qmi_service *svc)
* qmi_add_lookup() - register a new lookup with the name service
* @qmi: qmi handle
* @service: service id of the request
- * @instance: instance id of the request
* @version: version number of the request
+ * @instance: instance id of the request
*
* Registering a lookup query with the name server will cause the name server
* to send NEW_SERVER and DEL_SERVER control messages to this socket as
diff --git a/drivers/soc/qcom/ramp_controller.c b/drivers/soc/qcom/ramp_controller.c
index e9a0cca07189..349bdfbc61ef 100644
--- a/drivers/soc/qcom/ramp_controller.c
+++ b/drivers/soc/qcom/ramp_controller.c
@@ -331,8 +331,8 @@ static struct platform_driver qcom_ramp_controller_driver = {
.of_match_table = qcom_ramp_controller_match_table,
.suppress_bind_attrs = true,
},
- .probe = qcom_ramp_controller_probe,
- .remove_new = qcom_ramp_controller_remove,
+ .probe = qcom_ramp_controller_probe,
+ .remove = qcom_ramp_controller_remove,
};
static int __init qcom_ramp_controller_init(void)
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index df850d073102..1b32469f2789 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -125,7 +125,7 @@ static int qcom_rmtfs_mem_release(struct inode *inode, struct file *filp)
return 0;
}
-static struct class rmtfs_class = {
+static const struct class rmtfs_class = {
.name = "rmtfs",
};
@@ -315,7 +315,7 @@ MODULE_DEVICE_TABLE(of, qcom_rmtfs_mem_of_match);
static struct platform_driver qcom_rmtfs_mem_driver = {
.probe = qcom_rmtfs_mem_probe,
- .remove_new = qcom_rmtfs_mem_remove,
+ .remove = qcom_rmtfs_mem_remove,
.driver = {
.name = "qcom_rmtfs_mem",
.of_match_table = qcom_rmtfs_mem_of_match,
diff --git a/drivers/soc/qcom/rpm-proc.c b/drivers/soc/qcom/rpm-proc.c
index 2995d9b90190..2466d0400c2e 100644
--- a/drivers/soc/qcom/rpm-proc.c
+++ b/drivers/soc/qcom/rpm-proc.c
@@ -53,7 +53,7 @@ MODULE_DEVICE_TABLE(of, rpm_proc_of_match);
static struct platform_driver rpm_proc_driver = {
.probe = rpm_proc_probe,
- .remove_new = rpm_proc_remove,
+ .remove = rpm_proc_remove,
.driver = {
.name = "qcom-rpm-proc",
.of_match_table = rpm_proc_of_match,
diff --git a/drivers/soc/qcom/rpm_master_stats.c b/drivers/soc/qcom/rpm_master_stats.c
index 9ca13bcf67d3..49e4f9457279 100644
--- a/drivers/soc/qcom/rpm_master_stats.c
+++ b/drivers/soc/qcom/rpm_master_stats.c
@@ -148,10 +148,14 @@ static const struct of_device_id rpm_master_table[] = {
{ .compatible = "qcom,rpm-master-stats" },
{ },
};
+/*
+ * No MODULE_DEVICE_TABLE intentionally: that's a debugging module, to be
+ * loaded manually only.
+ */
static struct platform_driver master_stats_driver = {
.probe = master_stats_probe,
- .remove_new = master_stats_remove,
+ .remove = master_stats_remove,
.driver = {
.name = "qcom_rpm_master_stats",
.of_match_table = rpm_master_table,
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index a021dc71807b..cb82e887b51d 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME
@@ -557,7 +558,7 @@ static int check_for_req_inflight(struct rsc_drv *drv, struct tcs_group *tcs,
for_each_set_bit(j, &curr_enabled, MAX_CMDS_PER_TCS) {
addr = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], i, j);
for (k = 0; k < msg->num_cmds; k++) {
- if (addr == msg->cmds[k].addr)
+ if (cmd_db_match_resource_addr(msg->cmds[k].addr, addr))
return -EBUSY;
}
}
@@ -645,13 +646,14 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
{
struct tcs_group *tcs;
int tcs_id;
- unsigned long flags;
+
+ might_sleep();
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
- spin_lock_irqsave(&drv->lock, flags);
+ spin_lock_irq(&drv->lock);
/* Wait forever for a free tcs. It better be there eventually! */
wait_event_lock_irq(drv->tcs_wait,
@@ -669,7 +671,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0);
enable_tcs_irq(drv, tcs_id, true);
}
- spin_unlock_irqrestore(&drv->lock, flags);
+ spin_unlock_irq(&drv->lock);
/*
* These two can be done after the lock is released because:
@@ -1043,12 +1045,9 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
* do. To avoid adding this check to our children we'll do it now.
*/
ret = cmd_db_ready();
- if (ret) {
- if (ret != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Command DB not available (%d)\n",
- ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "Command DB not available\n");
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -1154,7 +1153,7 @@ static int __init rpmh_driver_init(void)
{
return platform_driver_register(&rpmh_driver);
}
-arch_initcall(rpmh_driver_init);
+core_initcall(rpmh_driver_init);
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPMh Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 9f26d7f9b9dc..8903ed956312 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -183,7 +183,6 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state,
}
if (state == RPMH_ACTIVE_ONLY_STATE) {
- WARN_ON(irqs_disabled());
ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg);
} else {
/* Clean up our call by spoofing tx_done */
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index b7056aed4c7d..f2b3e02abdf1 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -196,9 +196,6 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
{
struct qcom_smd_rpm *rpm;
- if (!rpdev->dev.of_node)
- return -EINVAL;
-
rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL);
if (!rpm)
return -ENOMEM;
@@ -218,18 +215,44 @@ static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
of_platform_depopulate(&rpdev->dev);
}
-static const struct rpmsg_device_id qcom_smd_rpm_id_table[] = {
- { .name = "rpm_requests", },
- { /* sentinel */ }
+static const struct of_device_id qcom_smd_rpm_of_match[] = {
+ { .compatible = "qcom,glink-smd-rpm" },
+ { .compatible = "qcom,smd-rpm" },
+ /*
+ * Don't add any more compatibles to the list, two previous entryes
+ * should match all defined devices.
+ */
+ { .compatible = "qcom,rpm-apq8084" },
+ { .compatible = "qcom,rpm-ipq6018" },
+ { .compatible = "qcom,rpm-ipq9574" },
+ { .compatible = "qcom,rpm-msm8226" },
+ { .compatible = "qcom,rpm-msm8909" },
+ { .compatible = "qcom,rpm-msm8916" },
+ { .compatible = "qcom,rpm-msm8936" },
+ { .compatible = "qcom,rpm-msm8953" },
+ { .compatible = "qcom,rpm-msm8974" },
+ { .compatible = "qcom,rpm-msm8976" },
+ { .compatible = "qcom,rpm-msm8994" },
+ { .compatible = "qcom,rpm-msm8996" },
+ { .compatible = "qcom,rpm-msm8998" },
+ { .compatible = "qcom,rpm-sdm660" },
+ { .compatible = "qcom,rpm-sm6115" },
+ { .compatible = "qcom,rpm-sm6125" },
+ { .compatible = "qcom,rpm-sm6375" },
+ { .compatible = "qcom,rpm-qcm2290" },
+ { .compatible = "qcom,rpm-qcs404" },
+ {}
};
-MODULE_DEVICE_TABLE(rpmsg, qcom_smd_rpm_id_table);
+MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
static struct rpmsg_driver qcom_smd_rpm_driver = {
.probe = qcom_smd_rpm_probe,
.remove = qcom_smd_rpm_remove,
.callback = qcom_smd_rpm_callback,
- .id_table = qcom_smd_rpm_id_table,
- .drv.name = "qcom_smd_rpm",
+ .drv = {
+ .name = "qcom_smd_rpm",
+ .of_match_table = qcom_smd_rpm_of_match,
+ },
};
static int __init qcom_smd_rpm_init(void)
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 7191fa0c087f..cf425930539e 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -86,7 +86,7 @@
#define SMEM_GLOBAL_HOST 0xfffe
/* Max number of processors/hosts in a system */
-#define SMEM_HOST_COUNT 20
+#define SMEM_HOST_COUNT 25
/**
* struct smem_proc_comm - proc_comm communication struct (legacy)
@@ -359,6 +359,32 @@ static struct qcom_smem *__smem;
/* Timeout (ms) for the trylock of remote spinlocks */
#define HWSPINLOCK_TIMEOUT 1000
+/* The qcom hwspinlock id is always plus one from the smem host id */
+#define SMEM_HOST_ID_TO_HWSPINLOCK_ID(__x) ((__x) + 1)
+
+/**
+ * qcom_smem_bust_hwspin_lock_by_host() - bust the smem hwspinlock for a host
+ * @host: remote processor id
+ *
+ * Busts the hwspin_lock for the given smem host id. This helper is intended
+ * for remoteproc drivers that manage remoteprocs with an equivalent smem
+ * driver instance in the remote firmware. Drivers can force a release of the
+ * smem hwspin_lock if the rproc unexpectedly goes into a bad state.
+ *
+ * Context: Process context.
+ *
+ * Returns: 0 on success, otherwise negative errno.
+ */
+int qcom_smem_bust_hwspin_lock_by_host(unsigned int host)
+{
+ /* This function is for remote procs, so ignore SMEM_HOST_APPS */
+ if (host == SMEM_HOST_APPS || host >= SMEM_HOST_COUNT)
+ return -EINVAL;
+
+ return hwspin_lock_bust(__smem->hwlock, SMEM_HOST_ID_TO_HWSPINLOCK_ID(host));
+}
+EXPORT_SYMBOL_GPL(qcom_smem_bust_hwspin_lock_by_host);
+
/**
* qcom_smem_is_available() - Check if SMEM is available
*
@@ -473,6 +499,8 @@ static int qcom_smem_alloc_global(struct qcom_smem *smem,
*
* Allocate space for a given smem item of size @size, given that the item is
* not yet allocated.
+ *
+ * Return: 0 on success, negative errno on failure.
*/
int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
{
@@ -651,6 +679,8 @@ invalid_canary:
*
* Looks up smem item and returns pointer to it. Size of smem
* item is returned in @size.
+ *
+ * Return: a pointer to an SMEM item on success, ERR_PTR() on failure.
*/
void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
{
@@ -683,6 +713,8 @@ EXPORT_SYMBOL_GPL(qcom_smem_get);
*
* To be used by smem clients as a quick way to determine if any new
* allocations has been made.
+ *
+ * Return: number of available bytes on success, negative errno on failure.
*/
int qcom_smem_get_free_space(unsigned host)
{
@@ -732,7 +764,7 @@ static bool addr_in_range(void __iomem *base, size_t size, void *addr)
* with an smem item pointer (previously returned by qcom_smem_get()
* @p: the virtual address to convert
*
- * Returns 0 if the pointer provided is not within any smem region.
+ * Return: physical address of the SMEM item (if found), 0 otherwise
*/
phys_addr_t qcom_smem_virt_to_phys(void *p)
{
@@ -795,6 +827,39 @@ int qcom_smem_get_soc_id(u32 *id)
}
EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id);
+/**
+ * qcom_smem_get_feature_code() - return the feature code
+ * @code: On success, return the feature code here.
+ *
+ * Look up the feature code identifier from SMEM and return it.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int qcom_smem_get_feature_code(u32 *code)
+{
+ struct socinfo *info;
+ u32 raw_code;
+
+ info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL);
+ if (IS_ERR(info))
+ return PTR_ERR(info);
+
+ /* This only makes sense for socinfo >= 16 */
+ if (__le32_to_cpu(info->fmt) < SOCINFO_VERSION(0, 16))
+ return -EOPNOTSUPP;
+
+ raw_code = __le32_to_cpu(info->feature_code);
+
+ /* Ensure the value makes sense */
+ if (raw_code > SOCINFO_FC_INT_MAX)
+ raw_code = SOCINFO_FC_UNKNOWN;
+
+ *code = raw_code;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_smem_get_feature_code);
+
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
{
struct smem_header *header;
@@ -1121,11 +1186,9 @@ static int qcom_smem_probe(struct platform_device *pdev)
}
hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
- if (hwlock_id < 0) {
- if (hwlock_id != -EPROBE_DEFER)
- dev_err(&pdev->dev, "failed to retrieve hwlock\n");
- return hwlock_id;
- }
+ if (hwlock_id < 0)
+ return dev_err_probe(&pdev->dev, hwlock_id,
+ "failed to retrieve hwlock\n");
smem->hwlock = hwspin_lock_request_specific(hwlock_id);
if (!smem->hwlock)
@@ -1192,7 +1255,7 @@ MODULE_DEVICE_TABLE(of, qcom_smem_of_match);
static struct platform_driver qcom_smem_driver = {
.probe = qcom_smem_probe,
- .remove_new = qcom_smem_remove,
+ .remove = qcom_smem_remove,
.driver = {
.name = "qcom-smem",
.of_match_table = qcom_smem_of_match,
diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c
index e848cc9a3cf8..cc5be8019b6a 100644
--- a/drivers/soc/qcom/smem_state.c
+++ b/drivers/soc/qcom/smem_state.c
@@ -3,6 +3,7 @@
* Copyright (c) 2015, Sony Mobile Communications Inc.
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -60,20 +61,15 @@ static struct qcom_smem_state *of_node_to_state(struct device_node *np)
{
struct qcom_smem_state *state;
- mutex_lock(&list_lock);
+ guard(mutex)(&list_lock);
list_for_each_entry(state, &smem_states, list) {
if (state->of_node == np) {
kref_get(&state->refcount);
- goto unlock;
+ return state;
}
}
- state = ERR_PTR(-EPROBE_DEFER);
-
-unlock:
- mutex_unlock(&list_lock);
-
- return state;
+ return ERR_PTR(-EPROBE_DEFER);
}
/**
@@ -116,7 +112,8 @@ struct qcom_smem_state *qcom_smem_state_get(struct device *dev,
if (args.args_count != 1) {
dev_err(dev, "invalid #qcom,smem-state-cells\n");
- return ERR_PTR(-EINVAL);
+ state = ERR_PTR(-EINVAL);
+ goto put;
}
state = of_node_to_state(args.np);
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index a21241cbeec7..cb515c2340c1 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/regmap.h>
+#include <linux/seq_file.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/smem_state.h>
#include <linux/spinlock.h>
@@ -160,6 +161,9 @@ struct qcom_smp2p {
struct list_head outbound;
};
+#define CREATE_TRACE_POINTS
+#include "trace-smp2p.h"
+
static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
{
/* Make sure any updated data is written before the kick */
@@ -191,6 +195,7 @@ static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p)
struct smp2p_smem_item *out = smp2p->out;
u32 val;
+ trace_smp2p_ssr_ack(smp2p->dev);
smp2p->ssr_ack = !smp2p->ssr_ack;
val = out->flags & ~BIT(SMP2P_FLAGS_RESTART_ACK_BIT);
@@ -213,6 +218,7 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
smp2p->ssr_ack_enabled = true;
smp2p->negotiation_done = true;
+ trace_smp2p_negotiate(smp2p->dev, out->features);
}
}
@@ -251,6 +257,8 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
status = val ^ entry->last_value;
entry->last_value = val;
+ trace_smp2p_notify_in(entry, status, val);
+
/* No changes of this entry? */
if (!status)
continue;
@@ -353,11 +361,19 @@ static int smp2p_set_irq_type(struct irq_data *irqd, unsigned int type)
return 0;
}
+static void smp2p_irq_print_chip(struct irq_data *irqd, struct seq_file *p)
+{
+ struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd);
+
+ seq_printf(p, "%8s", dev_name(entry->smp2p->dev));
+}
+
static struct irq_chip smp2p_irq_chip = {
.name = "smp2p",
.irq_mask = smp2p_mask_irq,
.irq_unmask = smp2p_unmask_irq,
.irq_set_type = smp2p_set_irq_type,
+ .irq_print_chip = smp2p_irq_print_chip,
};
static int smp2p_irq_map(struct irq_domain *d,
@@ -383,7 +399,7 @@ static int qcom_smp2p_inbound_entry(struct qcom_smp2p *smp2p,
struct smp2p_entry *entry,
struct device_node *node)
{
- entry->domain = irq_domain_add_linear(node, 32, &smp2p_irq_ops, entry);
+ entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smp2p_irq_ops, entry);
if (!entry->domain) {
dev_err(smp2p->dev, "failed to add irq_domain\n");
return -ENOMEM;
@@ -406,6 +422,8 @@ static int smp2p_update_bits(void *data, u32 mask, u32 value)
writel(val, entry->value);
spin_unlock_irqrestore(&entry->lock, flags);
+ trace_smp2p_update_bits(entry, orig, val);
+
if (val != orig)
qcom_smp2p_kick(entry->smp2p);
@@ -449,12 +467,9 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
int ret;
ret = qcom_smem_alloc(pid, smem_id, sizeof(*out));
- if (ret < 0 && ret != -EEXIST) {
- if (ret != -EPROBE_DEFER)
- dev_err(smp2p->dev,
- "unable to allocate local smp2p item\n");
- return ret;
- }
+ if (ret < 0 && ret != -EEXIST)
+ return dev_err_probe(smp2p->dev, ret,
+ "unable to allocate local smp2p item\n");
out = qcom_smem_get(pid, smem_id, NULL);
if (IS_ERR(out)) {
@@ -521,7 +536,6 @@ static int smp2p_parse_ipc(struct qcom_smp2p *smp2p)
static int qcom_smp2p_probe(struct platform_device *pdev)
{
struct smp2p_entry *entry;
- struct device_node *node;
struct qcom_smp2p *smp2p;
const char *key;
int irq;
@@ -561,7 +575,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
smp2p->mbox_client.knows_txdone = true;
smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0);
if (IS_ERR(smp2p->mbox_chan)) {
- if (PTR_ERR(smp2p->mbox_chan) != -ENODEV)
+ if (PTR_ERR(smp2p->mbox_chan) != -ENOENT)
return PTR_ERR(smp2p->mbox_chan);
smp2p->mbox_chan = NULL;
@@ -575,11 +589,10 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
if (ret < 0)
goto release_mbox;
- for_each_available_child_of_node(pdev->dev.of_node, node) {
+ for_each_available_child_of_node_scoped(pdev->dev.of_node, node) {
entry = devm_kzalloc(&pdev->dev, sizeof(*entry), GFP_KERNEL);
if (!entry) {
ret = -ENOMEM;
- of_node_put(node);
goto unwind_interfaces;
}
@@ -587,25 +600,19 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
spin_lock_init(&entry->lock);
ret = of_property_read_string(node, "qcom,entry-name", &entry->name);
- if (ret < 0) {
- of_node_put(node);
+ if (ret < 0)
goto unwind_interfaces;
- }
if (of_property_read_bool(node, "interrupt-controller")) {
ret = qcom_smp2p_inbound_entry(smp2p, entry, node);
- if (ret < 0) {
- of_node_put(node);
+ if (ret < 0)
goto unwind_interfaces;
- }
list_add(&entry->node, &smp2p->inbound);
} else {
ret = qcom_smp2p_outbound_entry(smp2p, entry, node);
- if (ret < 0) {
- of_node_put(node);
+ if (ret < 0)
goto unwind_interfaces;
- }
list_add(&entry->node, &smp2p->outbound);
}
@@ -617,7 +624,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, irq,
NULL, qcom_smp2p_intr,
IRQF_ONESHOT,
- "smp2p", (void *)smp2p);
+ NULL, (void *)smp2p);
if (ret) {
dev_err(&pdev->dev, "failed to request interrupt\n");
goto unwind_interfaces;
@@ -688,7 +695,7 @@ MODULE_DEVICE_TABLE(of, qcom_smp2p_of_match);
static struct platform_driver qcom_smp2p_driver = {
.probe = qcom_smp2p_probe,
- .remove_new = qcom_smp2p_remove,
+ .remove = qcom_smp2p_remove,
.driver = {
.name = "qcom_smp2p",
.of_match_table = qcom_smp2p_of_match,
diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c
index e7c7e9a640a6..021e9d1f61dc 100644
--- a/drivers/soc/qcom/smsm.c
+++ b/drivers/soc/qcom/smsm.c
@@ -5,6 +5,7 @@
*/
#include <linux/interrupt.h>
+#include <linux/mailbox_client.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_irq.h>
@@ -71,6 +72,7 @@ struct smsm_host;
* @lock: spinlock for read-modify-write of the outgoing state
* @entries: context for each of the entries
* @hosts: context for each of the hosts
+ * @mbox_client: mailbox client handle
*/
struct qcom_smsm {
struct device *dev;
@@ -88,6 +90,8 @@ struct qcom_smsm {
struct smsm_entry *entries;
struct smsm_host *hosts;
+
+ struct mbox_client mbox_client;
};
/**
@@ -120,11 +124,14 @@ struct smsm_entry {
* @ipc_regmap: regmap for outgoing interrupt
* @ipc_offset: offset in @ipc_regmap for outgoing interrupt
* @ipc_bit: bit in @ipc_regmap + @ipc_offset for outgoing interrupt
+ * @mbox_chan: apcs ipc mailbox channel handle
*/
struct smsm_host {
struct regmap *ipc_regmap;
int ipc_offset;
int ipc_bit;
+
+ struct mbox_chan *mbox_chan;
};
/**
@@ -172,7 +179,13 @@ static int smsm_update_bits(void *data, u32 mask, u32 value)
hostp = &smsm->hosts[host];
val = readl(smsm->subscription + host);
- if (val & changes && hostp->ipc_regmap) {
+ if (!(val & changes))
+ continue;
+
+ if (hostp->mbox_chan) {
+ mbox_send_message(hostp->mbox_chan, NULL);
+ mbox_client_txdone(hostp->mbox_chan, 0);
+ } else if (hostp->ipc_regmap) {
regmap_write(hostp->ipc_regmap,
hostp->ipc_offset,
BIT(hostp->ipc_bit));
@@ -353,6 +366,28 @@ static const struct irq_domain_ops smsm_irq_ops = {
};
/**
+ * smsm_parse_mbox() - requests an mbox channel
+ * @smsm: smsm driver context
+ * @host_id: index of the remote host to be resolved
+ *
+ * Requests the desired channel using the mbox interface which is needed for
+ * sending the outgoing interrupts to a remove hosts - identified by @host_id.
+ */
+static int smsm_parse_mbox(struct qcom_smsm *smsm, unsigned int host_id)
+{
+ struct smsm_host *host = &smsm->hosts[host_id];
+ int ret = 0;
+
+ host->mbox_chan = mbox_request_channel(&smsm->mbox_client, host_id);
+ if (IS_ERR(host->mbox_chan)) {
+ ret = PTR_ERR(host->mbox_chan);
+ host->mbox_chan = NULL;
+ }
+
+ return ret;
+}
+
+/**
* smsm_parse_ipc() - parses a qcom,ipc-%d device tree property
* @smsm: smsm driver context
* @host_id: index of the remote host to be resolved
@@ -421,7 +456,7 @@ static int smsm_inbound_entry(struct qcom_smsm *smsm,
return ret;
}
- entry->domain = irq_domain_add_linear(node, 32, &smsm_irq_ops, entry);
+ entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smsm_irq_ops, entry);
if (!entry->domain) {
dev_err(smsm->dev, "failed to add irq_domain\n");
return -ENOMEM;
@@ -521,8 +556,16 @@ static int qcom_smsm_probe(struct platform_device *pdev)
"qcom,local-host",
&smsm->local_host);
+ smsm->mbox_client.dev = &pdev->dev;
+ smsm->mbox_client.knows_txdone = true;
+
/* Parse the host properties */
for (id = 0; id < smsm->num_hosts; id++) {
+ /* Try using mbox interface first, otherwise fall back to syscon */
+ ret = smsm_parse_mbox(smsm, id);
+ if (!ret)
+ continue;
+
ret = smsm_parse_ipc(smsm, id);
if (ret < 0)
goto out_put;
@@ -609,6 +652,9 @@ unwind_interfaces:
qcom_smem_state_unregister(smsm->state);
out_put:
+ for (id = 0; id < smsm->num_hosts; id++)
+ mbox_free_channel(smsm->hosts[id].mbox_chan);
+
of_node_put(local_node);
return ret;
}
@@ -622,6 +668,9 @@ static void qcom_smsm_remove(struct platform_device *pdev)
if (smsm->entries[id].domain)
irq_domain_remove(smsm->entries[id].domain);
+ for (id = 0; id < smsm->num_hosts; id++)
+ mbox_free_channel(smsm->hosts[id].mbox_chan);
+
qcom_smem_state_unregister(smsm->state);
}
@@ -633,9 +682,9 @@ MODULE_DEVICE_TABLE(of, qcom_smsm_of_match);
static struct platform_driver qcom_smsm_driver = {
.probe = qcom_smsm_probe,
- .remove_new = qcom_smsm_remove,
- .driver = {
- .name = "qcom-smsm",
+ .remove = qcom_smsm_remove,
+ .driver = {
+ .name = "qcom-smsm",
.of_match_table = qcom_smsm_of_match,
},
};
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index e8ff9819ac47..8c4147737c35 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -17,18 +17,10 @@
#include <linux/sys_soc.h>
#include <linux/types.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <dt-bindings/arm/qcom,ids.h>
-/*
- * SoC version type with major number in the upper 16 bits and minor
- * number in the lower 16 bits.
- */
-#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff)
-#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
-#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
-
/* Helper macros to create soc_id table */
#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id)
#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name)
@@ -124,6 +116,7 @@ static const char *const pmic_models[] = {
[50] = "PM8350B",
[51] = "PMR735A",
[52] = "PMR735B",
+ [54] = "PM6350",
[55] = "PM4125",
[58] = "PM8450",
[65] = "PM8010",
@@ -133,6 +126,8 @@ static const char *const pmic_models[] = {
[72] = "PMR735D",
[73] = "PM8550",
[74] = "PMK8550",
+ [82] = "PMC8380",
+ [83] = "SMB2360",
};
struct socinfo_params {
@@ -347,6 +342,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SDA630) },
{ qcom_board_id(MSM8905) },
{ qcom_board_id(SDX202) },
+ { qcom_board_id(SDM670) },
{ qcom_board_id(SDM450) },
{ qcom_board_id(SM8150) },
{ qcom_board_id(SDA845) },
@@ -405,11 +401,13 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SA8540P) },
{ qcom_board_id(QCM4290) },
{ qcom_board_id(QCS4290) },
+ { qcom_board_id(SM7325) },
{ qcom_board_id_named(SM8450_2, "SM8450") },
{ qcom_board_id_named(SM8450_3, "SM8450") },
{ qcom_board_id(SC7280) },
{ qcom_board_id(SC7180P) },
{ qcom_board_id(QCM6490) },
+ { qcom_board_id(SM7325P) },
{ qcom_board_id(IPQ5000) },
{ qcom_board_id(IPQ0509) },
{ qcom_board_id(IPQ0518) },
@@ -424,14 +422,18 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(IPQ9510) },
{ qcom_board_id(QRB4210) },
{ qcom_board_id(QRB2210) },
+ { qcom_board_id(SAR2130P) },
{ qcom_board_id(SM8475) },
{ qcom_board_id(SM8475P) },
+ { qcom_board_id(SA8255P) },
{ qcom_board_id(SA8775P) },
{ qcom_board_id(QRU1000) },
{ qcom_board_id(SM8475_2) },
{ qcom_board_id(QDU1000) },
+ { qcom_board_id(X1E80100) },
{ qcom_board_id(SM8650) },
{ qcom_board_id(SM4450) },
+ { qcom_board_id(SAR1130P) },
{ qcom_board_id(QDU1010) },
{ qcom_board_id(QRU1032) },
{ qcom_board_id(QRU1052) },
@@ -442,7 +444,16 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(IPQ5302) },
{ qcom_board_id(QCS8550) },
{ qcom_board_id(QCM8550) },
+ { qcom_board_id(SM8750) },
{ qcom_board_id(IPQ5300) },
+ { qcom_board_id(IPQ5321) },
+ { qcom_board_id(IPQ5424) },
+ { qcom_board_id(IPQ5404) },
+ { qcom_board_id(QCS9100) },
+ { qcom_board_id(QCS8300) },
+ { qcom_board_id(QCS8275) },
+ { qcom_board_id(QCS9075) },
+ { qcom_board_id(QCS615) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
@@ -784,10 +795,16 @@ static int qcom_socinfo_probe(struct platform_device *pdev)
qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u",
SOCINFO_MAJOR(le32_to_cpu(info->ver)),
SOCINFO_MINOR(le32_to_cpu(info->ver)));
- if (offsetof(struct socinfo, serial_num) <= item_size)
+ if (!qs->attr.soc_id || !qs->attr.revision)
+ return -ENOMEM;
+
+ if (offsetofend(struct socinfo, serial_num) <= item_size) {
qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%u",
le32_to_cpu(info->serial_num));
+ if (!qs->attr.serial_number)
+ return -ENOMEM;
+ }
qs->soc_dev = soc_device_register(&qs->attr);
if (IS_ERR(qs->soc_dev))
@@ -814,7 +831,7 @@ static void qcom_socinfo_remove(struct platform_device *pdev)
static struct platform_driver qcom_socinfo_driver = {
.probe = qcom_socinfo_probe,
- .remove_new = qcom_socinfo_remove,
+ .remove = qcom_socinfo_remove,
.driver = {
.name = "qcom-socinfo",
},
diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c
index 06e2c4c2a4a8..f75659fff287 100644
--- a/drivers/soc/qcom/spm.c
+++ b/drivers/soc/qcom/spm.c
@@ -572,4 +572,5 @@ static int __init qcom_spm_init(void)
}
arch_initcall(qcom_spm_init);
+MODULE_DESCRIPTION("Qualcomm Subsystem Power Manager (SPM)");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/trace-aoss.h b/drivers/soc/qcom/trace-aoss.h
index 554029b33b44..fb5b0470c40d 100644
--- a/drivers/soc/qcom/trace-aoss.h
+++ b/drivers/soc/qcom/trace-aoss.h
@@ -18,7 +18,7 @@ TRACE_EVENT(aoss_send,
__string(msg, msg)
),
TP_fast_assign(
- __assign_str(msg, msg);
+ __assign_str(msg);
),
TP_printk("%s", __get_str(msg))
);
@@ -31,7 +31,7 @@ TRACE_EVENT(aoss_send_done,
__field(int, ret)
),
TP_fast_assign(
- __assign_str(msg, msg);
+ __assign_str(msg);
__entry->ret = ret;
),
TP_printk("%s: %d", __get_str(msg), __entry->ret)
diff --git a/drivers/soc/qcom/trace-rpmh.h b/drivers/soc/qcom/trace-rpmh.h
index be6b42ecc1f8..593ec1d4e010 100644
--- a/drivers/soc/qcom/trace-rpmh.h
+++ b/drivers/soc/qcom/trace-rpmh.h
@@ -26,7 +26,7 @@ TRACE_EVENT(rpmh_tx_done,
),
TP_fast_assign(
- __assign_str(name, d->name);
+ __assign_str(name);
__entry->m = m;
__entry->addr = r->cmds[0].addr;
__entry->data = r->cmds[0].data;
@@ -55,7 +55,7 @@ TRACE_EVENT(rpmh_send_msg,
),
TP_fast_assign(
- __assign_str(name, d->name);
+ __assign_str(name);
__entry->m = m;
__entry->state = state;
__entry->n = n;
diff --git a/drivers/soc/qcom/trace-smp2p.h b/drivers/soc/qcom/trace-smp2p.h
new file mode 100644
index 000000000000..9a6392043f10
--- /dev/null
+++ b/drivers/soc/qcom/trace-smp2p.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_smp2p
+
+#if !defined(__QCOM_SMP2P_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __QCOM_SMP2P_TRACE_H__
+
+#include <linux/device.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(smp2p_ssr_ack,
+ TP_PROTO(const struct device *dev),
+ TP_ARGS(dev),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(dev))
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ ),
+ TP_printk("%s: SSR detected", __get_str(dev_name))
+);
+
+TRACE_EVENT(smp2p_negotiate,
+ TP_PROTO(const struct device *dev, unsigned int features),
+ TP_ARGS(dev, features),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(dev))
+ __field(u32, out_features)
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __entry->out_features = features;
+ ),
+ TP_printk("%s: state=open out_features=%s", __get_str(dev_name),
+ __print_flags(__entry->out_features, "|",
+ {SMP2P_FEATURE_SSR_ACK, "SMP2P_FEATURE_SSR_ACK"})
+ )
+);
+
+TRACE_EVENT(smp2p_notify_in,
+ TP_PROTO(struct smp2p_entry *smp2p_entry, unsigned long status, u32 val),
+ TP_ARGS(smp2p_entry, status, val),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(smp2p_entry->smp2p->dev))
+ __string(client_name, smp2p_entry->name)
+ __field(unsigned long, status)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __assign_str(client_name);
+ __entry->status = status;
+ __entry->val = val;
+ ),
+ TP_printk("%s: %s: status:0x%0lx val:0x%0x",
+ __get_str(dev_name),
+ __get_str(client_name),
+ __entry->status,
+ __entry->val
+ )
+);
+
+TRACE_EVENT(smp2p_update_bits,
+ TP_PROTO(struct smp2p_entry *smp2p_entry, u32 orig, u32 val),
+ TP_ARGS(smp2p_entry, orig, val),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(smp2p_entry->smp2p->dev))
+ __string(client_name, smp2p_entry->name)
+ __field(u32, orig)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __assign_str(client_name);
+ __entry->orig = orig;
+ __entry->val = val;
+ ),
+ TP_printk("%s: %s: orig:0x%0x new:0x%0x",
+ __get_str(dev_name),
+ __get_str(client_name),
+ __entry->orig,
+ __entry->val
+ )
+);
+
+#endif /* __QCOM_SMP2P_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace-smp2p
+
+#include <trace/define_trace.h>
diff --git a/drivers/soc/qcom/trace_icc-bwmon.h b/drivers/soc/qcom/trace_icc-bwmon.h
new file mode 100644
index 000000000000..beb8e6b485a9
--- /dev/null
+++ b/drivers/soc/qcom/trace_icc-bwmon.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM icc_bwmon
+
+#if !defined(_TRACE_ICC_BWMON_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ICC_BWMON_H
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(qcom_bwmon_update,
+ TP_PROTO(const char *name,
+ unsigned int meas_kbps, unsigned int up_kbps, unsigned int down_kbps),
+
+ TP_ARGS(name, meas_kbps, up_kbps, down_kbps),
+
+ TP_STRUCT__entry(
+ __string(name, name)
+ __field(unsigned int, meas_kbps)
+ __field(unsigned int, up_kbps)
+ __field(unsigned int, down_kbps)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->meas_kbps = meas_kbps;
+ __entry->up_kbps = up_kbps;
+ __entry->down_kbps = down_kbps;
+ ),
+
+ TP_printk("name=%s meas_kbps=%u up_kbps=%u down_kbps=%u",
+ __get_str(name),
+ __entry->meas_kbps,
+ __entry->up_kbps,
+ __entry->down_kbps)
+);
+
+#endif /* _TRACE_ICC_BWMON_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../drivers/soc/qcom/
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace_icc-bwmon
+
+#include <trace/define_trace.h>
diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c
index 148bcbac332d..62b424e90d90 100644
--- a/drivers/soc/qcom/wcnss_ctrl.c
+++ b/drivers/soc/qcom/wcnss_ctrl.c
@@ -3,6 +3,7 @@
* Copyright (c) 2016, Linaro Ltd.
* Copyright (c) 2015, Sony Mobile Communications Inc.
*/
+#include <linux/cleanup.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -198,7 +199,6 @@ static int wcnss_request_version(struct wcnss_ctrl *wcnss)
*/
static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
{
- struct wcnss_download_nv_req *req;
const struct firmware *fw;
struct device *dev = wcnss->dev;
const char *nvbin = NVBIN_FILE;
@@ -206,18 +206,19 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
ssize_t left;
int ret;
- req = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE, GFP_KERNEL);
+ struct wcnss_download_nv_req *req __free(kfree) = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE,
+ GFP_KERNEL);
if (!req)
return -ENOMEM;
ret = of_property_read_string(dev->of_node, "firmware-name", &nvbin);
if (ret < 0 && ret != -EINVAL)
- goto free_req;
+ return ret;
ret = request_firmware(&fw, nvbin, dev);
if (ret < 0) {
dev_err(dev, "Failed to load nv file %s: %d\n", nvbin, ret);
- goto free_req;
+ return ret;
}
data = fw->data;
@@ -263,8 +264,6 @@ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
release_fw:
release_firmware(fw);
-free_req:
- kfree(req);
return ret;
}
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 5deca747fb77..fbc3b69d21a7 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -24,6 +24,7 @@ config ARCH_RCAR_GEN2
select RENESAS_IRQC
select RST_RCAR
select SYS_SUPPORTS_SH_CMT
+ select SYS_SUPPORTS_SH_TMU
config ARCH_RCAR_GEN3
bool
@@ -64,17 +65,20 @@ if ARM && ARCH_RENESAS
config ARCH_EMEV2
bool "ARM32 Platform support for Emma Mobile EV2"
+ default ARCH_RENESAS
select HAVE_ARM_SCU if SMP
select SYS_SUPPORTS_EM_STI
config ARCH_R8A7794
bool "ARM32 Platform support for R-Car E2"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A7794
config ARCH_R8A7779
bool "ARM32 Platform support for R-Car H1"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN1
select ARM_ERRATA_754322
select ARM_GLOBAL_TIMER
@@ -84,6 +88,7 @@ config ARCH_R8A7779
config ARCH_R8A7790
bool "ARM32 Platform support for R-Car H2"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
@@ -92,11 +97,13 @@ config ARCH_R8A7790
config ARCH_R8A7778
bool "ARM32 Platform support for R-Car M1A"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN1
select ARM_ERRATA_754322
config ARCH_R8A7793
bool "ARM32 Platform support for R-Car M2-N"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select I2C
@@ -104,6 +111,7 @@ config ARCH_R8A7793
config ARCH_R8A7791
bool "ARM32 Platform support for R-Car M2-W"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select I2C
@@ -111,18 +119,21 @@ config ARCH_R8A7791
config ARCH_R8A7792
bool "ARM32 Platform support for R-Car V2H"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7792
config ARCH_R8A7740
bool "ARM32 Platform support for R-Mobile A1"
+ default ARCH_RENESAS
select ARCH_RMOBILE
select ARM_ERRATA_754322
select RENESAS_INTC_IRQPIN
config ARCH_R8A73A4
bool "ARM32 Platform support for R-Mobile APE6"
+ default ARCH_RENESAS
select ARCH_RMOBILE
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
@@ -131,6 +142,7 @@ config ARCH_R8A73A4
config ARCH_R7S72100
bool "ARM32 Platform support for RZ/A1H"
+ default ARCH_RENESAS
select ARM_ERRATA_754322
select PM
select PM_GENERIC_DOMAINS
@@ -140,6 +152,7 @@ config ARCH_R7S72100
config ARCH_R7S9210
bool "ARM32 Platform support for RZ/A2"
+ default ARCH_RENESAS
select PM
select PM_GENERIC_DOMAINS
select RENESAS_OSTM
@@ -147,18 +160,21 @@ config ARCH_R7S9210
config ARCH_R8A77470
bool "ARM32 Platform support for RZ/G1C"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A77470
config ARCH_R8A7745
bool "ARM32 Platform support for RZ/G1E"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_814220
select SYSC_R8A7745
config ARCH_R8A7742
bool "ARM32 Platform support for RZ/G1H"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select ARM_ERRATA_814220
@@ -166,23 +182,27 @@ config ARCH_R8A7742
config ARCH_R8A7743
bool "ARM32 Platform support for RZ/G1M"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7743
config ARCH_R8A7744
bool "ARM32 Platform support for RZ/G1N"
+ default ARCH_RENESAS
select ARCH_RCAR_GEN2
select ARM_ERRATA_798181 if SMP
select SYSC_R8A7743
config ARCH_R9A06G032
bool "ARM32 Platform support for RZ/N1D"
+ default ARCH_RENESAS
select ARCH_RZN1
select ARM_ERRATA_814220
config ARCH_SH73A0
bool "ARM32 Platform support for SH-Mobile AG5"
+ default ARCH_RENESAS
select ARCH_RMOBILE
select ARM_ERRATA_754322
select ARM_GLOBAL_TIMER
@@ -196,6 +216,7 @@ if ARM64
config ARCH_R8A77995
bool "ARM64 Platform support for R-Car D3"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77995
help
@@ -204,6 +225,7 @@ config ARCH_R8A77995
config ARCH_R8A77990
bool "ARM64 Platform support for R-Car E3"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77990
help
@@ -212,6 +234,7 @@ config ARCH_R8A77990
config ARCH_R8A77951
bool "ARM64 Platform support for R-Car H3 ES2.0+"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A7795
help
@@ -221,6 +244,7 @@ config ARCH_R8A77951
config ARCH_R8A77965
bool "ARM64 Platform support for R-Car M3-N"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77965
help
@@ -229,6 +253,7 @@ config ARCH_R8A77965
config ARCH_R8A77960
bool "ARM64 Platform support for R-Car M3-W"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77960
help
@@ -236,6 +261,7 @@ config ARCH_R8A77960
config ARCH_R8A77961
bool "ARM64 Platform support for R-Car M3-W+"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77961
help
@@ -244,6 +270,7 @@ config ARCH_R8A77961
config ARCH_R8A779F0
bool "ARM64 Platform support for R-Car S4-8"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779F0
help
@@ -251,6 +278,7 @@ config ARCH_R8A779F0
config ARCH_R8A77980
bool "ARM64 Platform support for R-Car V3H"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77980
help
@@ -258,6 +286,7 @@ config ARCH_R8A77980
config ARCH_R8A77970
bool "ARM64 Platform support for R-Car V3M"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A77970
help
@@ -265,6 +294,7 @@ config ARCH_R8A77970
config ARCH_R8A779A0
bool "ARM64 Platform support for R-Car V3U"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779A0
help
@@ -272,6 +302,7 @@ config ARCH_R8A779A0
config ARCH_R8A779G0
bool "ARM64 Platform support for R-Car V4H"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779G0
help
@@ -279,6 +310,7 @@ config ARCH_R8A779G0
config ARCH_R8A779H0
bool "ARM64 Platform support for R-Car V4M"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN4
select SYSC_R8A779H0
help
@@ -286,6 +318,7 @@ config ARCH_R8A779H0
config ARCH_R8A774C0
bool "ARM64 Platform support for RZ/G2E"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774C0
help
@@ -293,6 +326,7 @@ config ARCH_R8A774C0
config ARCH_R8A774E1
bool "ARM64 Platform support for RZ/G2H"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774E1
help
@@ -300,6 +334,7 @@ config ARCH_R8A774E1
config ARCH_R8A774A1
bool "ARM64 Platform support for RZ/G2M"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774A1
help
@@ -307,6 +342,7 @@ config ARCH_R8A774A1
config ARCH_R8A774B1
bool "ARM64 Platform support for RZ/G2N"
+ default y if ARCH_RENESAS
select ARCH_RCAR_GEN3
select SYSC_R8A774B1
help
@@ -314,36 +350,64 @@ config ARCH_R8A774B1
config ARCH_R9A07G043
bool "ARM64 Platform support for RZ/G2UL"
+ default y if ARCH_RENESAS
select ARCH_RZG2L
help
This enables support for the Renesas RZ/G2UL SoC variants.
config ARCH_R9A07G044
bool "ARM64 Platform support for RZ/G2L"
+ default y if ARCH_RENESAS
select ARCH_RZG2L
help
This enables support for the Renesas RZ/G2L SoC variants.
config ARCH_R9A07G054
bool "ARM64 Platform support for RZ/V2L"
+ default y if ARCH_RENESAS
select ARCH_RZG2L
help
This enables support for the Renesas RZ/V2L SoC variants.
config ARCH_R9A08G045
bool "ARM64 Platform support for RZ/G3S"
+ default y if ARCH_RENESAS
select ARCH_RZG2L
+ select SYSC_R9A08G045
help
This enables support for the Renesas RZ/G3S SoC variants.
config ARCH_R9A09G011
bool "ARM64 Platform support for RZ/V2M"
+ default y if ARCH_RENESAS
select PM
select PM_GENERIC_DOMAINS
select PWC_RZV2M
help
This enables support for the Renesas RZ/V2M SoC.
+config ARCH_R9A09G047
+ bool "ARM64 Platform support for RZ/G3E"
+ default y if ARCH_RENESAS
+ select SYS_R9A09G047
+ help
+ This enables support for the Renesas RZ/G3E SoC variants.
+
+config ARCH_R9A09G056
+ bool "ARM64 Platform support for RZ/V2N"
+ default y if ARCH_RENESAS
+ select SYS_R9A09G056
+ help
+ This enables support for the Renesas RZ/V2N SoC variants.
+
+config ARCH_R9A09G057
+ bool "ARM64 Platform support for RZ/V2H(P)"
+ default y if ARCH_RENESAS
+ select RENESAS_RZV2H_ICU
+ select SYS_R9A09G057
+ help
+ This enables support for the Renesas RZ/V2H(P) SoC variants.
+
endif # ARM64
if RISCV
@@ -371,4 +435,23 @@ config PWC_RZV2M
config RST_RCAR
bool "Reset Controller support for R-Car" if COMPILE_TEST
+config SYSC_RZ
+ bool "System controller for RZ SoCs" if COMPILE_TEST
+
+config SYSC_R9A08G045
+ bool "Renesas RZ/G3S System controller support" if COMPILE_TEST
+ select SYSC_RZ
+
+config SYS_R9A09G047
+ bool "Renesas RZ/G3E System controller support" if COMPILE_TEST
+ select SYSC_RZ
+
+config SYS_R9A09G056
+ bool "Renesas RZ/V2N System controller support" if COMPILE_TEST
+ select SYSC_RZ
+
+config SYS_R9A09G057
+ bool "Renesas RZ/V2H System controller support" if COMPILE_TEST
+ select SYSC_RZ
+
endif # SOC_RENESAS
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index 734f8f8cefa4..3bdcc6a395d5 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -6,7 +6,12 @@ obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o
ifdef CONFIG_SMP
obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o
endif
+obj-$(CONFIG_SYSC_R9A08G045) += r9a08g045-sysc.o
+obj-$(CONFIG_SYS_R9A09G047) += r9a09g047-sys.o
+obj-$(CONFIG_SYS_R9A09G056) += r9a09g056-sys.o
+obj-$(CONFIG_SYS_R9A09G057) += r9a09g057-sys.o
# Family
obj-$(CONFIG_PWC_RZV2M) += pwc-rzv2m.o
obj-$(CONFIG_RST_RCAR) += rcar-rst.o
+obj-$(CONFIG_SYSC_RZ) += rz-sysc.o
diff --git a/drivers/soc/renesas/r9a08g045-sysc.c b/drivers/soc/renesas/r9a08g045-sysc.c
new file mode 100644
index 000000000000..f4db1431e036
--- /dev/null
+++ b/drivers/soc/renesas/r9a08g045-sysc.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G3S System controller driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#include <linux/bits.h>
+#include <linux/init.h>
+
+#include "rz-sysc.h"
+
+static const struct rz_sysc_soc_id_init_data rzg3s_sysc_soc_id_init_data __initconst = {
+ .family = "RZ/G3S",
+ .id = 0x85e0447,
+ .devid_offset = 0xa04,
+ .revision_mask = GENMASK(31, 28),
+ .specific_id_mask = GENMASK(27, 0),
+};
+
+const struct rz_sysc_init_data rzg3s_sysc_init_data __initconst = {
+ .soc_id_init_data = &rzg3s_sysc_soc_id_init_data,
+};
diff --git a/drivers/soc/renesas/r9a09g047-sys.c b/drivers/soc/renesas/r9a09g047-sys.c
new file mode 100644
index 000000000000..cd2eb7782cfe
--- /dev/null
+++ b/drivers/soc/renesas/r9a09g047-sys.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G3E System controller (SYS) driver
+ *
+ * Copyright (C) 2025 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include "rz-sysc.h"
+
+/* Register Offsets */
+#define SYS_LSI_MODE 0x300
+/*
+ * BOOTPLLCA[1:0]
+ * [0,0] => 1.1GHZ
+ * [0,1] => 1.5GHZ
+ * [1,0] => 1.6GHZ
+ * [1,1] => 1.7GHZ
+ */
+#define SYS_LSI_MODE_STAT_BOOTPLLCA55 GENMASK(12, 11)
+#define SYS_LSI_MODE_CA55_1_7GHZ 0x3
+
+#define SYS_LSI_PRR 0x308
+#define SYS_LSI_PRR_CA55_DIS BIT(8)
+#define SYS_LSI_PRR_NPU_DIS BIT(1)
+
+static void rzg3e_sys_print_id(struct device *dev,
+ void __iomem *sysc_base,
+ struct soc_device_attribute *soc_dev_attr)
+{
+ bool is_quad_core, npu_enabled;
+ u32 prr_val, mode_val;
+
+ prr_val = readl(sysc_base + SYS_LSI_PRR);
+ mode_val = readl(sysc_base + SYS_LSI_MODE);
+
+ /* Check CPU and NPU configuration */
+ is_quad_core = !(prr_val & SYS_LSI_PRR_CA55_DIS);
+ npu_enabled = !(prr_val & SYS_LSI_PRR_NPU_DIS);
+
+ dev_info(dev, "Detected Renesas %s Core %s %s Rev %s%s\n",
+ is_quad_core ? "Quad" : "Dual", soc_dev_attr->family,
+ soc_dev_attr->soc_id, soc_dev_attr->revision,
+ npu_enabled ? " with Ethos-U55" : "");
+
+ /* Check CA55 PLL configuration */
+ if (FIELD_GET(SYS_LSI_MODE_STAT_BOOTPLLCA55, mode_val) != SYS_LSI_MODE_CA55_1_7GHZ)
+ dev_warn(dev, "CA55 PLL is not set to 1.7GHz\n");
+}
+
+static const struct rz_sysc_soc_id_init_data rzg3e_sys_soc_id_init_data __initconst = {
+ .family = "RZ/G3E",
+ .id = 0x8679447,
+ .devid_offset = 0x304,
+ .revision_mask = GENMASK(31, 28),
+ .specific_id_mask = GENMASK(27, 0),
+ .print_id = rzg3e_sys_print_id,
+};
+
+const struct rz_sysc_init_data rzg3e_sys_init_data = {
+ .soc_id_init_data = &rzg3e_sys_soc_id_init_data,
+};
diff --git a/drivers/soc/renesas/r9a09g056-sys.c b/drivers/soc/renesas/r9a09g056-sys.c
new file mode 100644
index 000000000000..3ad1422eba36
--- /dev/null
+++ b/drivers/soc/renesas/r9a09g056-sys.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/V2N System controller (SYS) driver
+ *
+ * Copyright (C) 2025 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include "rz-sysc.h"
+
+/* Register Offsets */
+#define SYS_LSI_MODE 0x300
+#define SYS_LSI_MODE_SEC_EN BIT(16)
+/*
+ * BOOTPLLCA[1:0]
+ * [0,0] => 1.1GHZ
+ * [0,1] => 1.5GHZ
+ * [1,0] => 1.6GHZ
+ * [1,1] => 1.7GHZ
+ */
+#define SYS_LSI_MODE_STAT_BOOTPLLCA55 GENMASK(12, 11)
+#define SYS_LSI_MODE_CA55_1_7GHZ 0x3
+
+#define SYS_LSI_PRR 0x308
+#define SYS_LSI_PRR_GPU_DIS BIT(0)
+#define SYS_LSI_PRR_ISP_DIS BIT(4)
+
+#define SYS_RZV2N_FEATURE_G31 BIT(0)
+#define SYS_RZV2N_FEATURE_C55 BIT(1)
+#define SYS_RZV2N_FEATURE_SEC BIT(2)
+
+static void rzv2n_sys_print_id(struct device *dev,
+ void __iomem *sysc_base,
+ struct soc_device_attribute *soc_dev_attr)
+{
+ u32 prr_val, mode_val;
+ u8 feature_flags;
+
+ prr_val = readl(sysc_base + SYS_LSI_PRR);
+ mode_val = readl(sysc_base + SYS_LSI_MODE);
+
+ /* Check GPU, ISP and Cryptographic configuration */
+ feature_flags = !(prr_val & SYS_LSI_PRR_GPU_DIS) ? SYS_RZV2N_FEATURE_G31 : 0;
+ feature_flags |= !(prr_val & SYS_LSI_PRR_ISP_DIS) ? SYS_RZV2N_FEATURE_C55 : 0;
+ feature_flags |= (mode_val & SYS_LSI_MODE_SEC_EN) ? SYS_RZV2N_FEATURE_SEC : 0;
+
+ dev_info(dev, "Detected Renesas %s %sn%d Rev %s%s%s%s%s\n", soc_dev_attr->family,
+ soc_dev_attr->soc_id, 41 + feature_flags, soc_dev_attr->revision,
+ feature_flags ? " with" : "",
+ feature_flags & SYS_RZV2N_FEATURE_G31 ? " GE3D (Mali-G31)" : "",
+ feature_flags & SYS_RZV2N_FEATURE_SEC ? " Cryptographic engine" : "",
+ feature_flags & SYS_RZV2N_FEATURE_C55 ? " ISP (Mali-C55)" : "");
+
+ /* Check CA55 PLL configuration */
+ if (FIELD_GET(SYS_LSI_MODE_STAT_BOOTPLLCA55, mode_val) != SYS_LSI_MODE_CA55_1_7GHZ)
+ dev_warn(dev, "CA55 PLL is not set to 1.7GHz\n");
+}
+
+static const struct rz_sysc_soc_id_init_data rzv2n_sys_soc_id_init_data __initconst = {
+ .family = "RZ/V2N",
+ .id = 0x867d447,
+ .devid_offset = 0x304,
+ .revision_mask = GENMASK(31, 28),
+ .specific_id_mask = GENMASK(27, 0),
+ .print_id = rzv2n_sys_print_id,
+};
+
+const struct rz_sysc_init_data rzv2n_sys_init_data = {
+ .soc_id_init_data = &rzv2n_sys_soc_id_init_data,
+};
diff --git a/drivers/soc/renesas/r9a09g057-sys.c b/drivers/soc/renesas/r9a09g057-sys.c
new file mode 100644
index 000000000000..4c21cc29edbc
--- /dev/null
+++ b/drivers/soc/renesas/r9a09g057-sys.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/V2H System controller (SYS) driver
+ *
+ * Copyright (C) 2025 Renesas Electronics Corp.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include "rz-sysc.h"
+
+/* Register Offsets */
+#define SYS_LSI_MODE 0x300
+/*
+ * BOOTPLLCA[1:0]
+ * [0,0] => 1.1GHZ
+ * [0,1] => 1.5GHZ
+ * [1,0] => 1.6GHZ
+ * [1,1] => 1.7GHZ
+ */
+#define SYS_LSI_MODE_STAT_BOOTPLLCA55 GENMASK(12, 11)
+#define SYS_LSI_MODE_CA55_1_7GHZ 0x3
+
+#define SYS_LSI_PRR 0x308
+#define SYS_LSI_PRR_GPU_DIS BIT(0)
+#define SYS_LSI_PRR_ISP_DIS BIT(4)
+
+static void rzv2h_sys_print_id(struct device *dev,
+ void __iomem *sysc_base,
+ struct soc_device_attribute *soc_dev_attr)
+{
+ bool gpu_enabled, isp_enabled;
+ u32 prr_val, mode_val;
+
+ prr_val = readl(sysc_base + SYS_LSI_PRR);
+ mode_val = readl(sysc_base + SYS_LSI_MODE);
+
+ /* Check GPU and ISP configuration */
+ gpu_enabled = !(prr_val & SYS_LSI_PRR_GPU_DIS);
+ isp_enabled = !(prr_val & SYS_LSI_PRR_ISP_DIS);
+
+ dev_info(dev, "Detected Renesas %s %s Rev %s%s%s\n",
+ soc_dev_attr->family, soc_dev_attr->soc_id, soc_dev_attr->revision,
+ gpu_enabled ? " with GE3D (Mali-G31)" : "",
+ isp_enabled ? " with ISP (Mali-C55)" : "");
+
+ /* Check CA55 PLL configuration */
+ if (FIELD_GET(SYS_LSI_MODE_STAT_BOOTPLLCA55, mode_val) != SYS_LSI_MODE_CA55_1_7GHZ)
+ dev_warn(dev, "CA55 PLL is not set to 1.7GHz\n");
+}
+
+static const struct rz_sysc_soc_id_init_data rzv2h_sys_soc_id_init_data __initconst = {
+ .family = "RZ/V2H",
+ .id = 0x847a447,
+ .devid_offset = 0x304,
+ .revision_mask = GENMASK(31, 28),
+ .specific_id_mask = GENMASK(27, 0),
+ .print_id = rzv2h_sys_print_id,
+};
+
+const struct rz_sysc_init_data rzv2h_sys_init_data = {
+ .soc_id_init_data = &rzv2h_sys_soc_id_init_data,
+};
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 8f9b8d3736dc..df2b38417b80 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -71,10 +71,6 @@ static const struct renesas_family fam_rzg2ul __initconst __maybe_unused = {
.name = "RZ/G2UL",
};
-static const struct renesas_family fam_rzg3s __initconst __maybe_unused = {
- .name = "RZ/G3S",
-};
-
static const struct renesas_family fam_rzv2l __initconst __maybe_unused = {
.name = "RZ/V2L",
};
@@ -172,11 +168,6 @@ static const struct renesas_soc soc_rz_g2ul __initconst __maybe_unused = {
.id = 0x8450447,
};
-static const struct renesas_soc soc_rz_g3s __initconst __maybe_unused = {
- .family = &fam_rzg3s,
- .id = 0x85e0447,
-};
-
static const struct renesas_soc soc_rz_v2l __initconst __maybe_unused = {
.family = &fam_rzv2l,
.id = 0x8447447,
@@ -280,7 +271,6 @@ static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
.id = 0x37,
};
-
static const struct of_device_id renesas_socs[] __initconst __maybe_unused = {
#ifdef CONFIG_ARCH_R7S72100
{ .compatible = "renesas,r7s72100", .data = &soc_rz_a1h },
@@ -401,9 +391,6 @@ static const struct of_device_id renesas_socs[] __initconst __maybe_unused = {
#ifdef CONFIG_ARCH_R9A07G054
{ .compatible = "renesas,r9a07g054", .data = &soc_rz_v2l },
#endif
-#ifdef CONFIG_ARCH_R9A08G045
- { .compatible = "renesas,r9a08g045", .data = &soc_rz_g3s },
-#endif
#ifdef CONFIG_ARCH_R9A09G011
{ .compatible = "renesas,r9a09g011", .data = &soc_rz_v2m },
#endif
diff --git a/drivers/soc/renesas/rz-sysc.c b/drivers/soc/renesas/rz-sysc.c
new file mode 100644
index 000000000000..ffa65fb4dade
--- /dev/null
+++ b/drivers/soc/renesas/rz-sysc.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ System controller driver
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+
+#include "rz-sysc.h"
+
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
+/**
+ * struct rz_sysc - RZ SYSC private data structure
+ * @base: SYSC base address
+ * @dev: SYSC device pointer
+ */
+struct rz_sysc {
+ void __iomem *base;
+ struct device *dev;
+};
+
+static int rz_sysc_soc_init(struct rz_sysc *sysc, const struct of_device_id *match)
+{
+ const struct rz_sysc_init_data *sysc_data = match->data;
+ const struct rz_sysc_soc_id_init_data *soc_data = sysc_data->soc_id_init_data;
+ struct soc_device_attribute *soc_dev_attr;
+ const char *soc_id_start, *soc_id_end;
+ u32 val, revision, specific_id;
+ struct soc_device *soc_dev;
+ char soc_id[32] = {0};
+ size_t size;
+
+ soc_id_start = strchr(match->compatible, ',') + 1;
+ soc_id_end = strchr(match->compatible, '-');
+ size = soc_id_end - soc_id_start + 1;
+ if (size > 32)
+ size = sizeof(soc_id);
+ strscpy(soc_id, soc_id_start, size);
+
+ soc_dev_attr = devm_kzalloc(sysc->dev, sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return -ENOMEM;
+
+ soc_dev_attr->family = devm_kstrdup(sysc->dev, soc_data->family, GFP_KERNEL);
+ if (!soc_dev_attr->family)
+ return -ENOMEM;
+
+ soc_dev_attr->soc_id = devm_kstrdup(sysc->dev, soc_id, GFP_KERNEL);
+ if (!soc_dev_attr->soc_id)
+ return -ENOMEM;
+
+ val = readl(sysc->base + soc_data->devid_offset);
+ revision = field_get(soc_data->revision_mask, val);
+ specific_id = field_get(soc_data->specific_id_mask, val);
+ soc_dev_attr->revision = devm_kasprintf(sysc->dev, GFP_KERNEL, "%u", revision);
+ if (!soc_dev_attr->revision)
+ return -ENOMEM;
+
+ if (soc_data->id && specific_id != soc_data->id) {
+ dev_warn(sysc->dev, "SoC mismatch (product = 0x%x)\n", specific_id);
+ return -ENODEV;
+ }
+
+ /* Try to call SoC-specific device identification */
+ if (soc_data->print_id) {
+ soc_data->print_id(sysc->dev, sysc->base, soc_dev_attr);
+ } else {
+ dev_info(sysc->dev, "Detected Renesas %s %s Rev %s\n",
+ soc_dev_attr->family, soc_dev_attr->soc_id, soc_dev_attr->revision);
+ }
+
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev))
+ return PTR_ERR(soc_dev);
+
+ return 0;
+}
+
+static const struct of_device_id rz_sysc_match[] = {
+#ifdef CONFIG_SYSC_R9A08G045
+ { .compatible = "renesas,r9a08g045-sysc", .data = &rzg3s_sysc_init_data },
+#endif
+#ifdef CONFIG_SYS_R9A09G047
+ { .compatible = "renesas,r9a09g047-sys", .data = &rzg3e_sys_init_data },
+#endif
+#ifdef CONFIG_SYS_R9A09G056
+ { .compatible = "renesas,r9a09g056-sys", .data = &rzv2n_sys_init_data },
+#endif
+#ifdef CONFIG_SYS_R9A09G057
+ { .compatible = "renesas,r9a09g057-sys", .data = &rzv2h_sys_init_data },
+#endif
+ { }
+};
+MODULE_DEVICE_TABLE(of, rz_sysc_match);
+
+static int rz_sysc_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct device *dev = &pdev->dev;
+ struct rz_sysc *sysc;
+
+ match = of_match_node(rz_sysc_match, dev->of_node);
+ if (!match)
+ return -ENODEV;
+
+ sysc = devm_kzalloc(dev, sizeof(*sysc), GFP_KERNEL);
+ if (!sysc)
+ return -ENOMEM;
+
+ sysc->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(sysc->base))
+ return PTR_ERR(sysc->base);
+
+ sysc->dev = dev;
+ return rz_sysc_soc_init(sysc, match);
+}
+
+static struct platform_driver rz_sysc_driver = {
+ .driver = {
+ .name = "renesas-rz-sysc",
+ .suppress_bind_attrs = true,
+ .of_match_table = rz_sysc_match
+ },
+ .probe = rz_sysc_probe
+};
+
+static int __init rz_sysc_init(void)
+{
+ return platform_driver_register(&rz_sysc_driver);
+}
+subsys_initcall(rz_sysc_init);
+
+MODULE_DESCRIPTION("Renesas RZ System Controller Driver");
+MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/renesas/rz-sysc.h b/drivers/soc/renesas/rz-sysc.h
new file mode 100644
index 000000000000..56bc047a1bff
--- /dev/null
+++ b/drivers/soc/renesas/rz-sysc.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Renesas RZ System Controller
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+
+#ifndef __SOC_RENESAS_RZ_SYSC_H__
+#define __SOC_RENESAS_RZ_SYSC_H__
+
+#include <linux/device.h>
+#include <linux/sys_soc.h>
+#include <linux/types.h>
+
+/**
+ * struct rz_syc_soc_id_init_data - RZ SYSC SoC identification initialization data
+ * @family: RZ SoC family
+ * @id: RZ SoC expected ID
+ * @devid_offset: SYSC SoC ID register offset
+ * @revision_mask: SYSC SoC ID revision mask
+ * @specific_id_mask: SYSC SoC ID specific ID mask
+ * @print_id: print SoC-specific extended device identification
+ */
+struct rz_sysc_soc_id_init_data {
+ const char * const family;
+ u32 id;
+ u32 devid_offset;
+ u32 revision_mask;
+ u32 specific_id_mask;
+ void (*print_id)(struct device *dev, void __iomem *sysc_base,
+ struct soc_device_attribute *soc_dev_attr);
+};
+
+/**
+ * struct rz_sysc_init_data - RZ SYSC initialization data
+ * @soc_id_init_data: RZ SYSC SoC ID initialization data
+ */
+struct rz_sysc_init_data {
+ const struct rz_sysc_soc_id_init_data *soc_id_init_data;
+};
+
+extern const struct rz_sysc_init_data rzg3e_sys_init_data;
+extern const struct rz_sysc_init_data rzg3s_sysc_init_data;
+extern const struct rz_sysc_init_data rzv2h_sys_init_data;
+extern const struct rz_sysc_init_data rzv2n_sys_init_data;
+
+#endif /* __SOC_RENESAS_RZ_SYSC_H__ */
diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c
index 5fd62046b28a..1eab4bb0eacf 100644
--- a/drivers/soc/rockchip/grf.c
+++ b/drivers/soc/rockchip/grf.c
@@ -41,9 +41,11 @@ static const struct rockchip_grf_info rk3036_grf __initconst = {
};
#define RK3128_GRF_SOC_CON0 0x140
+#define RK3128_GRF_SOC_CON1 0x144
static const struct rockchip_grf_value rk3128_defaults[] __initconst = {
{ "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) },
+ { "vpu main clock", RK3128_GRF_SOC_CON1, HIWORD_UPDATE(0, 1, 10) },
};
static const struct rockchip_grf_info rk3128_grf __initconst = {
@@ -121,6 +123,29 @@ static const struct rockchip_grf_info rk3566_pipegrf __initconst = {
.num_values = ARRAY_SIZE(rk3566_defaults),
};
+#define RK3576_SYSGRF_SOC_CON1 0x0004
+
+static const struct rockchip_grf_value rk3576_defaults_sys_grf[] __initconst = {
+ { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 6) },
+ { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 8) },
+};
+
+static const struct rockchip_grf_info rk3576_sysgrf __initconst = {
+ .values = rk3576_defaults_sys_grf,
+ .num_values = ARRAY_SIZE(rk3576_defaults_sys_grf),
+};
+
+#define RK3576_IOCGRF_MISC_CON 0x04F0
+
+static const struct rockchip_grf_value rk3576_defaults_ioc_grf[] __initconst = {
+ { "jtag switching", RK3576_IOCGRF_MISC_CON, HIWORD_UPDATE(0, 1, 1) },
+};
+
+static const struct rockchip_grf_info rk3576_iocgrf __initconst = {
+ .values = rk3576_defaults_ioc_grf,
+ .num_values = ARRAY_SIZE(rk3576_defaults_ioc_grf),
+};
+
#define RK3588_GRF_SOC_CON6 0x0318
static const struct rockchip_grf_value rk3588_defaults[] __initconst = {
@@ -132,7 +157,6 @@ static const struct rockchip_grf_info rk3588_sysgrf __initconst = {
.num_values = ARRAY_SIZE(rk3588_defaults),
};
-
static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
{
.compatible = "rockchip,rk3036-grf",
@@ -159,6 +183,12 @@ static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
.compatible = "rockchip,rk3566-pipe-grf",
.data = (void *)&rk3566_pipegrf,
}, {
+ .compatible = "rockchip,rk3576-sys-grf",
+ .data = (void *)&rk3576_sysgrf,
+ }, {
+ .compatible = "rockchip,rk3576-ioc-grf",
+ .data = (void *)&rk3576_iocgrf,
+ }, {
.compatible = "rockchip,rk3588-sys-grf",
.data = (void *)&rk3588_sysgrf,
},
diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c
index 18f809c160a7..f94985a905c2 100644
--- a/drivers/soc/rockchip/io-domain.c
+++ b/drivers/soc/rockchip/io-domain.c
@@ -39,6 +39,10 @@
#define RK3288_SOC_CON2_FLASH0 BIT(7)
#define RK3288_SOC_FLASH_SUPPLY_NUM 2
+#define RK3308_SOC_CON0 0x300
+#define RK3308_SOC_CON0_VCCIO3 BIT(8)
+#define RK3308_SOC_VCCIO3_SUPPLY_NUM 3
+
#define RK3328_SOC_CON4 0x410
#define RK3328_SOC_CON4_VCCIO2 BIT(7)
#define RK3328_SOC_VCCIO2_SUPPLY_NUM 1
@@ -229,6 +233,25 @@ static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
}
+static void rk3308_iodomain_init(struct rockchip_iodomain *iod)
+{
+ int ret;
+ u32 val;
+
+ /* if no vccio3 supply we should leave things alone */
+ if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg)
+ return;
+
+ /*
+ * set vccio3 iodomain to also use this framework
+ * instead of a special gpio.
+ */
+ val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16);
+ ret = regmap_write(iod->grf, RK3308_SOC_CON0, val);
+ if (ret < 0)
+ dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n");
+}
+
static void rk3328_iodomain_init(struct rockchip_iodomain *iod)
{
int ret;
@@ -376,6 +399,19 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
.init = rk3288_iodomain_init,
};
+static const struct rockchip_iodomain_soc_data soc_data_rk3308 = {
+ .grf_offset = 0x300,
+ .supply_names = {
+ "vccio0",
+ "vccio1",
+ "vccio2",
+ "vccio3",
+ "vccio4",
+ "vccio5",
+ },
+ .init = rk3308_iodomain_init,
+};
+
static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
.grf_offset = 0x410,
.supply_names = {
@@ -529,6 +565,10 @@ static const struct of_device_id rockchip_iodomain_match[] = {
.data = &soc_data_rk3288
},
{
+ .compatible = "rockchip,rk3308-io-voltage-domain",
+ .data = &soc_data_rk3308
+ },
+ {
.compatible = "rockchip,rk3328-io-voltage-domain",
.data = &soc_data_rk3328
},
@@ -702,10 +742,10 @@ static void rockchip_iodomain_remove(struct platform_device *pdev)
}
static struct platform_driver rockchip_iodomain_driver = {
- .probe = rockchip_iodomain_probe,
- .remove_new = rockchip_iodomain_remove,
- .driver = {
- .name = "rockchip-iodomain",
+ .probe = rockchip_iodomain_probe,
+ .remove = rockchip_iodomain_remove,
+ .driver = {
+ .name = "rockchip-iodomain",
.of_match_table = rockchip_iodomain_match,
},
};
diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
index d60af8acc391..8e681f519526 100644
--- a/drivers/soc/samsung/exynos-asv.c
+++ b/drivers/soc/samsung/exynos-asv.c
@@ -9,8 +9,10 @@
* Samsung Exynos SoC Adaptive Supply Voltage support
*/
+#include <linux/array_size.h>
#include <linux/cpu.h>
#include <linux/device.h>
+#include <linux/energy_model.h>
#include <linux/errno.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
@@ -97,9 +99,16 @@ static int exynos_asv_update_opps(struct exynos_asv *asv)
last_opp_table = opp_table;
ret = exynos_asv_update_cpu_opps(asv, cpu);
- if (ret < 0)
+ if (!ret) {
+ /*
+ * Update EM power values since OPP
+ * voltage values may have changed.
+ */
+ em_dev_update_chip_binning(cpu);
+ } else {
dev_err(asv->dev, "Couldn't udate OPPs for cpu%d\n",
cpuid);
+ }
}
dev_pm_opp_put_opp_table(opp_table);
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
index b1118d37779e..c86f1058ceed 100644
--- a/drivers/soc/samsung/exynos-chipid.c
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -12,6 +12,7 @@
* Samsung Exynos SoC Adaptive Supply Voltage and Chip ID support
*/
+#include <linux/array_size.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/mfd/syscon.h>
@@ -55,9 +56,14 @@ static const struct exynos_soc_id {
{ "EXYNOS5440", 0xE5440000 },
{ "EXYNOS5800", 0xE5422000 },
{ "EXYNOS7420", 0xE7420000 },
+ { "EXYNOS7870", 0xE7870000 },
/* Compatible with: samsung,exynos850-chipid */
+ { "EXYNOS2200", 0xE9925000 },
{ "EXYNOS7885", 0xE7885000 },
{ "EXYNOS850", 0xE3830000 },
+ { "EXYNOS8895", 0xE8895000 },
+ { "EXYNOS9810", 0xE9810000 },
+ { "EXYNOS990", 0xE9830000 },
{ "EXYNOSAUTOV9", 0xAAA80000 },
{ "EXYNOSAUTOV920", 0x0A920000 },
};
@@ -131,6 +137,8 @@ static int exynos_chipid_probe(struct platform_device *pdev)
soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"%x", soc_info.revision);
+ if (!soc_dev_attr->revision)
+ return -ENOMEM;
soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id);
if (!soc_dev_attr->soc_id) {
pr_err("Unknown SoC\n");
@@ -195,8 +203,8 @@ static struct platform_driver exynos_chipid_driver = {
.name = "exynos-chipid",
.of_match_table = exynos_chipid_of_device_ids,
},
- .probe = exynos_chipid_probe,
- .remove_new = exynos_chipid_remove,
+ .probe = exynos_chipid_probe,
+ .remove = exynos_chipid_remove,
};
module_platform_driver(exynos_chipid_driver);
diff --git a/drivers/soc/samsung/exynos-pmu.c b/drivers/soc/samsung/exynos-pmu.c
index fd8b6ac06656..a77288f49d24 100644
--- a/drivers/soc/samsung/exynos-pmu.c
+++ b/drivers/soc/samsung/exynos-pmu.c
@@ -5,7 +5,9 @@
//
// Exynos - CPU PMU(Power Management Unit) support
+#include <linux/array_size.h>
#include <linux/arm-smccc.h>
+#include <linux/cpuhotplug.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/mfd/core.h>
@@ -32,6 +34,7 @@ struct exynos_pmu_context {
struct device *dev;
const struct exynos_pmu_data *pmu_data;
struct regmap *pmureg;
+ struct regmap *pmuintrgen;
};
void __iomem *pmu_base_addr;
@@ -126,17 +129,33 @@ static int tensor_set_bits_atomic(void *ctx, unsigned int offset, u32 val,
if (ret)
return ret;
}
- return ret;
+ return 0;
}
-static int tensor_sec_update_bits(void *ctx, unsigned int reg,
- unsigned int mask, unsigned int val)
+static bool tensor_is_atomic(unsigned int reg)
{
/*
* Use atomic operations for PMU_ALIVE registers (offset 0~0x3FFF)
- * as the target registers can be accessed by multiple masters.
+ * as the target registers can be accessed by multiple masters. SFRs
+ * that don't support atomic are added to the switch statement below.
*/
if (reg > PMUALIVE_MASK)
+ return false;
+
+ switch (reg) {
+ case GS101_SYSIP_DAT0:
+ case GS101_SYSTEM_CONFIGURATION:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int tensor_sec_update_bits(void *ctx, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+
+ if (!tensor_is_atomic(reg))
return tensor_sec_reg_rmw(ctx, reg, mask, val);
return tensor_set_bits_atomic(ctx, reg, val, mask);
@@ -204,18 +223,9 @@ static const struct regmap_config regmap_smccfg = {
.reg_update_bits = tensor_sec_update_bits,
};
-static const struct regmap_config regmap_mmiocfg = {
- .name = "pmu_regs",
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .fast_io = true,
- .use_single_read = true,
- .use_single_write = true,
-};
-
static const struct exynos_pmu_data gs101_pmu_data = {
- .pmu_secure = true
+ .pmu_secure = true,
+ .pmu_cpuhp = true,
};
/*
@@ -290,7 +300,6 @@ EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap);
struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
const char *propname)
{
- struct exynos_pmu_context *ctx;
struct device_node *pmu_np;
struct device *dev;
@@ -316,12 +325,63 @@ struct regmap *exynos_get_pmu_regmap_by_phandle(struct device_node *np,
if (!dev)
return ERR_PTR(-EPROBE_DEFER);
- ctx = dev_get_drvdata(dev);
-
- return ctx->pmureg;
+ return syscon_node_to_regmap(pmu_np);
}
EXPORT_SYMBOL_GPL(exynos_get_pmu_regmap_by_phandle);
+/*
+ * CPU_INFORM register hint values which are used by
+ * EL3 firmware (el3mon).
+ */
+#define CPU_INFORM_CLEAR 0
+#define CPU_INFORM_C2 1
+
+static int gs101_cpuhp_pmu_online(unsigned int cpu)
+{
+ unsigned int cpuhint = smp_processor_id();
+ u32 reg, mask;
+
+ /* clear cpu inform hint */
+ regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint),
+ CPU_INFORM_CLEAR);
+
+ mask = BIT(cpu);
+
+ regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE,
+ mask, (0 << cpu));
+
+ regmap_read(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_UPEND, &reg);
+
+ regmap_write(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_CLEAR,
+ reg & mask);
+
+ return 0;
+}
+
+static int gs101_cpuhp_pmu_offline(unsigned int cpu)
+{
+ u32 reg, mask;
+ unsigned int cpuhint = smp_processor_id();
+
+ /* set cpu inform hint */
+ regmap_write(pmu_context->pmureg, GS101_CPU_INFORM(cpuhint),
+ CPU_INFORM_C2);
+
+ mask = BIT(cpu);
+ regmap_update_bits(pmu_context->pmuintrgen, GS101_GRP2_INTR_BID_ENABLE,
+ mask, BIT(cpu));
+
+ regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg);
+ regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR,
+ reg & mask);
+
+ mask = (BIT(cpu + 8));
+ regmap_read(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_UPEND, &reg);
+ regmap_write(pmu_context->pmuintrgen, GS101_GRP1_INTR_BID_CLEAR,
+ reg & mask);
+ return 0;
+}
+
static int exynos_pmu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -355,22 +415,45 @@ static int exynos_pmu_probe(struct platform_device *pdev)
regmap = devm_regmap_init(dev, NULL,
(void *)(uintptr_t)res->start,
&pmu_regmcfg);
+
+ if (IS_ERR(regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
+ "regmap init failed\n");
+
+ ret = of_syscon_register_regmap(dev->of_node, regmap);
+ if (ret)
+ return ret;
} else {
- /* All other SoCs use a MMIO regmap */
- pmu_regmcfg = regmap_mmiocfg;
- pmu_regmcfg.max_register = resource_size(res) -
- pmu_regmcfg.reg_stride;
- regmap = devm_regmap_init_mmio(dev, pmu_base_addr,
- &pmu_regmcfg);
+ /* let syscon create mmio regmap */
+ regmap = syscon_node_to_regmap(dev->of_node);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
+ "syscon_node_to_regmap failed\n");
}
- if (IS_ERR(regmap))
- return dev_err_probe(&pdev->dev, PTR_ERR(regmap),
- "regmap init failed\n");
-
pmu_context->pmureg = regmap;
pmu_context->dev = dev;
+ if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_cpuhp) {
+ pmu_context->pmuintrgen = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "google,pmu-intr-gen-syscon");
+ if (IS_ERR(pmu_context->pmuintrgen)) {
+ /*
+ * To maintain support for older DTs that didn't specify syscon phandle
+ * just issue a warning rather than fail to probe.
+ */
+ dev_warn(&pdev->dev, "pmu-intr-gen syscon unavailable\n");
+ } else {
+ cpuhp_setup_state(CPUHP_BP_PREPARE_DYN,
+ "soc/exynos-pmu:prepare",
+ gs101_cpuhp_pmu_online, NULL);
+
+ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+ "soc/exynos-pmu:online",
+ NULL, gs101_cpuhp_pmu_offline);
+ }
+ }
+
if (pmu_context->pmu_data && pmu_context->pmu_data->pmu_init)
pmu_context->pmu_data->pmu_init();
diff --git a/drivers/soc/samsung/exynos-pmu.h b/drivers/soc/samsung/exynos-pmu.h
index 0a49a2c9a08e..0938bb4fe15f 100644
--- a/drivers/soc/samsung/exynos-pmu.h
+++ b/drivers/soc/samsung/exynos-pmu.h
@@ -22,6 +22,7 @@ struct exynos_pmu_data {
const struct exynos_pmu_conf *pmu_config;
const struct exynos_pmu_conf *pmu_config_extra;
bool pmu_secure;
+ bool pmu_cpuhp;
void (*pmu_init)(void);
void (*powerdown_conf)(enum sys_powerdown);
diff --git a/drivers/soc/samsung/exynos-usi.c b/drivers/soc/samsung/exynos-usi.c
index 114352695ac2..5f7bdf3bab05 100644
--- a/drivers/soc/samsung/exynos-usi.c
+++ b/drivers/soc/samsung/exynos-usi.c
@@ -6,6 +6,7 @@
* Samsung Exynos USI driver (Universal Serial Interface).
*/
+#include <linux/array_size.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
@@ -16,6 +17,18 @@
#include <dt-bindings/soc/samsung,exynos-usi.h>
+/* USIv1: System Register: SW_CONF register bits */
+#define USI_V1_SW_CONF_NONE 0x0
+#define USI_V1_SW_CONF_I2C0 0x1
+#define USI_V1_SW_CONF_I2C1 0x2
+#define USI_V1_SW_CONF_I2C0_1 0x3
+#define USI_V1_SW_CONF_SPI 0x4
+#define USI_V1_SW_CONF_UART 0x8
+#define USI_V1_SW_CONF_UART_I2C1 0xa
+#define USI_V1_SW_CONF_MASK (USI_V1_SW_CONF_I2C0 | USI_V1_SW_CONF_I2C1 | \
+ USI_V1_SW_CONF_I2C0_1 | USI_V1_SW_CONF_SPI | \
+ USI_V1_SW_CONF_UART | USI_V1_SW_CONF_UART_I2C1)
+
/* USIv2: System Register: SW_CONF register bits */
#define USI_V2_SW_CONF_NONE 0x0
#define USI_V2_SW_CONF_UART BIT(0)
@@ -34,7 +47,8 @@
#define USI_OPTION_CLKSTOP_ON BIT(2)
enum exynos_usi_ver {
- USI_VER2 = 2,
+ USI_VER1 = 0,
+ USI_VER2,
};
struct exynos_usi_variant {
@@ -66,19 +80,39 @@ struct exynos_usi_mode {
unsigned int val; /* mode register value */
};
-static const struct exynos_usi_mode exynos_usi_modes[] = {
- [USI_V2_NONE] = { .name = "none", .val = USI_V2_SW_CONF_NONE },
- [USI_V2_UART] = { .name = "uart", .val = USI_V2_SW_CONF_UART },
- [USI_V2_SPI] = { .name = "spi", .val = USI_V2_SW_CONF_SPI },
- [USI_V2_I2C] = { .name = "i2c", .val = USI_V2_SW_CONF_I2C },
+#define USI_MODES_MAX (USI_MODE_UART_I2C1 + 1)
+static const struct exynos_usi_mode exynos_usi_modes[][USI_MODES_MAX] = {
+ [USI_VER1] = {
+ [USI_MODE_NONE] = { .name = "none", .val = USI_V1_SW_CONF_NONE },
+ [USI_MODE_UART] = { .name = "uart", .val = USI_V1_SW_CONF_UART },
+ [USI_MODE_SPI] = { .name = "spi", .val = USI_V1_SW_CONF_SPI },
+ [USI_MODE_I2C] = { .name = "i2c", .val = USI_V1_SW_CONF_I2C0 },
+ [USI_MODE_I2C1] = { .name = "i2c1", .val = USI_V1_SW_CONF_I2C1 },
+ [USI_MODE_I2C0_1] = { .name = "i2c0_1", .val = USI_V1_SW_CONF_I2C0_1 },
+ [USI_MODE_UART_I2C1] = { .name = "uart_i2c1", .val = USI_V1_SW_CONF_UART_I2C1 },
+ }, [USI_VER2] = {
+ [USI_MODE_NONE] = { .name = "none", .val = USI_V2_SW_CONF_NONE },
+ [USI_MODE_UART] = { .name = "uart", .val = USI_V2_SW_CONF_UART },
+ [USI_MODE_SPI] = { .name = "spi", .val = USI_V2_SW_CONF_SPI },
+ [USI_MODE_I2C] = { .name = "i2c", .val = USI_V2_SW_CONF_I2C },
+ },
};
static const char * const exynos850_usi_clk_names[] = { "pclk", "ipclk" };
static const struct exynos_usi_variant exynos850_usi_data = {
.ver = USI_VER2,
.sw_conf_mask = USI_V2_SW_CONF_MASK,
- .min_mode = USI_V2_NONE,
- .max_mode = USI_V2_I2C,
+ .min_mode = USI_MODE_NONE,
+ .max_mode = USI_MODE_I2C,
+ .num_clks = ARRAY_SIZE(exynos850_usi_clk_names),
+ .clk_names = exynos850_usi_clk_names,
+};
+
+static const struct exynos_usi_variant exynos8895_usi_data = {
+ .ver = USI_VER1,
+ .sw_conf_mask = USI_V1_SW_CONF_MASK,
+ .min_mode = USI_MODE_NONE,
+ .max_mode = USI_MODE_UART_I2C1,
.num_clks = ARRAY_SIZE(exynos850_usi_clk_names),
.clk_names = exynos850_usi_clk_names,
};
@@ -87,6 +121,9 @@ static const struct of_device_id exynos_usi_dt_match[] = {
{
.compatible = "samsung,exynos850-usi",
.data = &exynos850_usi_data,
+ }, {
+ .compatible = "samsung,exynos8895-usi",
+ .data = &exynos8895_usi_data,
},
{ } /* sentinel */
};
@@ -109,14 +146,15 @@ static int exynos_usi_set_sw_conf(struct exynos_usi *usi, size_t mode)
if (mode < usi->data->min_mode || mode > usi->data->max_mode)
return -EINVAL;
- val = exynos_usi_modes[mode].val;
+ val = exynos_usi_modes[usi->data->ver][mode].val;
ret = regmap_update_bits(usi->sysreg, usi->sw_conf,
usi->data->sw_conf_mask, val);
if (ret)
return ret;
usi->mode = mode;
- dev_dbg(usi->dev, "protocol: %s\n", exynos_usi_modes[usi->mode].name);
+ dev_dbg(usi->dev, "protocol: %s\n",
+ exynos_usi_modes[usi->data->ver][usi->mode].name);
return 0;
}
@@ -168,10 +206,42 @@ static int exynos_usi_configure(struct exynos_usi *usi)
if (ret)
return ret;
- if (usi->data->ver == USI_VER2)
- return exynos_usi_enable(usi);
+ if (usi->data->ver == USI_VER1)
+ ret = clk_bulk_prepare_enable(usi->data->num_clks,
+ usi->clks);
+ else if (usi->data->ver == USI_VER2)
+ ret = exynos_usi_enable(usi);
- return 0;
+ return ret;
+}
+
+static void exynos_usi_unconfigure(void *data)
+{
+ struct exynos_usi *usi = data;
+ u32 val;
+ int ret;
+
+ if (usi->data->ver == USI_VER1) {
+ clk_bulk_disable_unprepare(usi->data->num_clks, usi->clks);
+ return;
+ }
+
+ ret = clk_bulk_prepare_enable(usi->data->num_clks, usi->clks);
+ if (ret)
+ return;
+
+ /* Make sure that we've stopped providing the clock to USI IP */
+ val = readl(usi->regs + USI_OPTION);
+ val &= ~USI_OPTION_CLKREQ_ON;
+ val |= USI_OPTION_CLKSTOP_ON;
+ writel(val, usi->regs + USI_OPTION);
+
+ /* Set USI block state to reset */
+ val = readl(usi->regs + USI_CON);
+ val |= USI_CON_RESET;
+ writel(val, usi->regs + USI_CON);
+
+ clk_bulk_disable_unprepare(usi->data->num_clks, usi->clks);
}
static int exynos_usi_parse_dt(struct device_node *np, struct exynos_usi *usi)
@@ -186,15 +256,11 @@ static int exynos_usi_parse_dt(struct device_node *np, struct exynos_usi *usi)
return -EINVAL;
usi->mode = mode;
- usi->sysreg = syscon_regmap_lookup_by_phandle(np, "samsung,sysreg");
+ usi->sysreg = syscon_regmap_lookup_by_phandle_args(np, "samsung,sysreg",
+ 1, &usi->sw_conf);
if (IS_ERR(usi->sysreg))
return PTR_ERR(usi->sysreg);
- ret = of_property_read_u32_index(np, "samsung,sysreg", 1,
- &usi->sw_conf);
- if (ret)
- return ret;
-
usi->clkreq_on = of_property_read_bool(np, "samsung,clkreq-on");
return 0;
@@ -255,6 +321,10 @@ static int exynos_usi_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = devm_add_action_or_reset(&pdev->dev, exynos_usi_unconfigure, usi);
+ if (ret)
+ return ret;
+
/* Make it possible to embed protocol nodes into USI np */
return of_platform_populate(np, NULL, NULL, dev);
}
diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c
index 30f230ed1769..4bad12a99542 100644
--- a/drivers/soc/samsung/exynos3250-pmu.c
+++ b/drivers/soc/samsung/exynos3250-pmu.c
@@ -5,6 +5,7 @@
//
// Exynos3250 - CPU PMU (Power Management Unit) support
+#include <linux/array_size.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include <linux/soc/samsung/exynos-pmu.h>
diff --git a/drivers/soc/samsung/exynos5250-pmu.c b/drivers/soc/samsung/exynos5250-pmu.c
index 7a2d50be6b4a..2ae5c3e1b07a 100644
--- a/drivers/soc/samsung/exynos5250-pmu.c
+++ b/drivers/soc/samsung/exynos5250-pmu.c
@@ -5,6 +5,7 @@
//
// Exynos5250 - CPU PMU (Power Management Unit) support
+#include <linux/array_size.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include <linux/soc/samsung/exynos-pmu.h>
diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c
index 6fedcd78cb45..58a2209795f7 100644
--- a/drivers/soc/samsung/exynos5420-pmu.c
+++ b/drivers/soc/samsung/exynos5420-pmu.c
@@ -5,6 +5,7 @@
//
// Exynos5420 - CPU PMU (Power Management Unit) support
+#include <linux/array_size.h>
#include <linux/pm.h>
#include <linux/soc/samsung/exynos-regs-pmu.h>
#include <linux/soc/samsung/exynos-pmu.h>
diff --git a/drivers/soc/sophgo/Kconfig b/drivers/soc/sophgo/Kconfig
new file mode 100644
index 000000000000..45f78b270c91
--- /dev/null
+++ b/drivers/soc/sophgo/Kconfig
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Sophgo SoC drivers
+#
+
+if ARCH_SOPHGO || COMPILE_TEST
+menu "Sophgo SoC drivers"
+
+config SOPHGO_CV1800_RTCSYS
+ tristate "Sophgo CV1800 RTC MFD"
+ select MFD_CORE
+ help
+ If you say yes here you get support the RTC MFD driver for Sophgo
+ CV1800 series SoC. The RTC module comprises a 32kHz oscillator,
+ Power-on-Reset (PoR) sub-module, HW state machine to control chip
+ power-on, power-off and reset. Furthermore, the 8051 subsystem is
+ located within RTCSYS including associated SRAM block.
+
+ This driver can also be built as a module. If so, the module will be
+ called cv1800-rtcsys.
+
+config SOPHGO_SG2044_TOPSYS
+ tristate "Sophgo SG2044 TOP syscon driver"
+ select MFD_CORE
+ help
+ This is the core driver for the Sophgo SG2044 TOP system
+ controller device. This driver provide PLL clock device
+ for the SoC.
+
+ This driver can also be built as a module. If so, the module
+ will be called sg2044-topsys.
+
+endmenu
+endif
diff --git a/drivers/soc/sophgo/Makefile b/drivers/soc/sophgo/Makefile
new file mode 100644
index 000000000000..27f68df22c4d
--- /dev/null
+++ b/drivers/soc/sophgo/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SOPHGO_CV1800_RTCSYS) += cv1800-rtcsys.o
+obj-$(CONFIG_SOPHGO_SG2044_TOPSYS) += sg2044-topsys.o
diff --git a/drivers/soc/sophgo/cv1800-rtcsys.c b/drivers/soc/sophgo/cv1800-rtcsys.c
new file mode 100644
index 000000000000..fdae2e2a61c5
--- /dev/null
+++ b/drivers/soc/sophgo/cv1800-rtcsys.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Sophgo CV1800 series SoC RTC subsystem
+ *
+ * The RTC module comprises a 32kHz oscillator, Power-on-Reset (PoR) sub-module,
+ * HW state machine to control chip power-on, power-off and reset. Furthermore,
+ * the 8051 subsystem is located within RTCSYS including associated SRAM block.
+ *
+ * Copyright (C) 2025 Alexander Sverdlin <alexander.sverdlin@gmail.com>
+ *
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/property.h>
+
+static struct resource cv1800_rtcsys_irq_resources[] = {
+ DEFINE_RES_IRQ_NAMED(0, "alarm"),
+};
+
+static const struct mfd_cell cv1800_rtcsys_subdev[] = {
+ {
+ .name = "cv1800b-rtc",
+ .num_resources = 1,
+ .resources = &cv1800_rtcsys_irq_resources[0],
+ },
+};
+
+static int cv1800_rtcsys_probe(struct platform_device *pdev)
+{
+ int irq;
+
+ irq = platform_get_irq_byname(pdev, "alarm");
+ if (irq < 0)
+ return irq;
+ cv1800_rtcsys_irq_resources[0].start = irq;
+ cv1800_rtcsys_irq_resources[0].end = irq;
+
+ return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+ cv1800_rtcsys_subdev,
+ ARRAY_SIZE(cv1800_rtcsys_subdev),
+ NULL, 0, NULL);
+}
+
+static const struct of_device_id cv1800_rtcsys_of_match[] = {
+ { .compatible = "sophgo,cv1800b-rtc" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cv1800_rtcsys_of_match);
+
+static struct platform_driver cv1800_rtcsys_mfd = {
+ .probe = cv1800_rtcsys_probe,
+ .driver = {
+ .name = "cv1800_rtcsys",
+ .of_match_table = cv1800_rtcsys_of_match,
+ },
+};
+module_platform_driver(cv1800_rtcsys_mfd);
+
+MODULE_AUTHOR("Alexander Sverdlin <alexander.sverdlin@gmail.com>");
+MODULE_DESCRIPTION("Sophgo CV1800 series SoC RTC subsystem driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/sophgo/sg2044-topsys.c b/drivers/soc/sophgo/sg2044-topsys.c
new file mode 100644
index 000000000000..179f2620b2a9
--- /dev/null
+++ b/drivers/soc/sophgo/sg2044-topsys.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sophgo SG2044 multi-function system controller driver
+ *
+ * Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com>
+ */
+
+#include <linux/mfd/core.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/resource.h>
+
+static const struct mfd_cell sg2044_topsys_subdev[] = {
+ {
+ .name = "sg2044-pll",
+ },
+};
+
+static int sg2044_topsys_probe(struct platform_device *pdev)
+{
+ return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+ sg2044_topsys_subdev,
+ ARRAY_SIZE(sg2044_topsys_subdev),
+ NULL, 0, NULL);
+}
+
+static const struct of_device_id sg2044_topsys_of_match[] = {
+ { .compatible = "sophgo,sg2044-top-syscon" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sg2044_topsys_of_match);
+
+static struct platform_driver sg2044_topsys_driver = {
+ .probe = sg2044_topsys_probe,
+ .driver = {
+ .name = "sg2044-topsys",
+ .of_match_table = sg2044_topsys_of_match,
+ },
+};
+module_platform_driver(sg2044_topsys_driver);
+
+MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>");
+MODULE_DESCRIPTION("Sophgo SG2044 multi-function system controller driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 6eb6cf06278e..2781a091a6a6 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -33,7 +33,6 @@ struct sunxi_sram_data {
u8 offset;
u8 width;
struct sunxi_sram_func *func;
- struct list_head list;
};
struct sunxi_sram_desc {
@@ -103,7 +102,6 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
};
static struct device *sram_dev;
-static LIST_HEAD(claimed_sram);
static DEFINE_SPINLOCK(sram_lock);
static void __iomem *base;
@@ -346,7 +344,7 @@ static void sunxi_sram_unlock(void *_lock)
spin_unlock(lock);
}
-static struct regmap_config sunxi_sram_regmap_config = {
+static const struct regmap_config sunxi_sram_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
diff --git a/drivers/soc/tegra/cbb/tegra-cbb.c b/drivers/soc/tegra/cbb/tegra-cbb.c
index 84ab46c9d9f5..6215c6a84fbe 100644
--- a/drivers/soc/tegra/cbb/tegra-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra-cbb.c
@@ -69,19 +69,12 @@ static int tegra_cbb_err_show(struct seq_file *file, void *data)
}
DEFINE_SHOW_ATTRIBUTE(tegra_cbb_err);
-static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb)
+static void tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb)
{
static struct dentry *root;
- if (!root) {
+ if (!root)
root = debugfs_create_file("tegra_cbb_err", 0444, NULL, cbb, &tegra_cbb_err_fops);
- if (IS_ERR_OR_NULL(root)) {
- pr_err("%s(): could not create debugfs node\n", __func__);
- return PTR_ERR(root);
- }
- }
-
- return 0;
}
void tegra_cbb_stall_enable(struct tegra_cbb *cbb)
@@ -148,13 +141,8 @@ int tegra_cbb_register(struct tegra_cbb *cbb)
{
int ret;
- if (IS_ENABLED(CONFIG_DEBUG_FS)) {
- ret = tegra_cbb_err_debugfs_init(cbb);
- if (ret) {
- dev_err(cbb->dev, "failed to create debugfs\n");
- return ret;
- }
- }
+ if (IS_ENABLED(CONFIG_DEBUG_FS))
+ tegra_cbb_err_debugfs_init(cbb);
/* register interrupt handler for errors due to different initiators */
ret = cbb->ops->interrupt_enable(cbb);
diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c
index 9cbc562ae7d3..846b17ffc2f9 100644
--- a/drivers/soc/tegra/cbb/tegra194-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra194-cbb.c
@@ -2330,7 +2330,7 @@ static const struct dev_pm_ops tegra194_cbb_pm = {
static struct platform_driver tegra194_cbb_driver = {
.probe = tegra194_cbb_probe,
- .remove_new = tegra194_cbb_remove,
+ .remove = tegra194_cbb_remove,
.driver = {
.name = "tegra194-cbb",
.of_match_table = of_match_ptr(tegra194_cbb_match),
diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c
index 5cf0e8c34164..c74629af9bb5 100644
--- a/drivers/soc/tegra/cbb/tegra234-cbb.c
+++ b/drivers/soc/tegra/cbb/tegra234-cbb.c
@@ -277,7 +277,7 @@ static void tegra234_lookup_slave_timeout(struct seq_file *file, struct tegra234
* which timed out.
* a) Get block number from the index of set bit in
* <FABRIC>_SN_AXI2APB_<>_BLOCK_TMO_STATUS_0 register.
- * b) Get address of register repective to block number i.e.
+ * b) Get address of register respective to block number i.e.
* <FABRIC>_SN_AXI2APB_<>_BLOCK<index-set-bit>_TMO_0.
* c) Read the register in above step to get client_id which
* timed out as per the set bits.
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index b6bfd6729df3..d27667283846 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -127,8 +127,8 @@ static void tegra_fuse_print_sku_info(struct tegra_sku_info *tegra_sku_info)
static int tegra_fuse_add_lookups(struct tegra_fuse *fuse)
{
- fuse->lookups = kmemdup_array(fuse->soc->lookups, sizeof(*fuse->lookups),
- fuse->soc->num_lookups, GFP_KERNEL);
+ fuse->lookups = kmemdup_array(fuse->soc->lookups, fuse->soc->num_lookups,
+ sizeof(*fuse->lookups), GFP_KERNEL);
if (!fuse->lookups)
return -ENOMEM;
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index eb14e5ff5a0a..e24ab5f7d2bf 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -647,15 +647,20 @@ static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = {
};
static const struct nvmem_keepout tegra234_fuse_keepouts[] = {
- { .start = 0x01c, .end = 0x0c8 },
- { .start = 0x12c, .end = 0x184 },
+ { .start = 0x01c, .end = 0x064 },
+ { .start = 0x084, .end = 0x0a0 },
+ { .start = 0x0a4, .end = 0x0c8 },
+ { .start = 0x12c, .end = 0x164 },
+ { .start = 0x16c, .end = 0x184 },
{ .start = 0x190, .end = 0x198 },
{ .start = 0x1a0, .end = 0x204 },
- { .start = 0x21c, .end = 0x250 },
- { .start = 0x25c, .end = 0x2f0 },
+ { .start = 0x21c, .end = 0x2f0 },
{ .start = 0x310, .end = 0x3d8 },
- { .start = 0x400, .end = 0x4f0 },
- { .start = 0x4f8, .end = 0x7e8 },
+ { .start = 0x400, .end = 0x420 },
+ { .start = 0x444, .end = 0x490 },
+ { .start = 0x4bc, .end = 0x4f0 },
+ { .start = 0x4f8, .end = 0x54c },
+ { .start = 0x57c, .end = 0x7e8 },
{ .start = 0x8d0, .end = 0x8d8 },
{ .start = 0xacc, .end = 0xf00 }
};
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index d6bfcea5ee65..e0d67bfe955c 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -47,6 +47,7 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/string_choices.h>
#include <linux/syscore_ops.h>
#include <soc/tegra/common.h>
@@ -1181,7 +1182,7 @@ static int powergate_show(struct seq_file *s, void *data)
continue;
seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
- status ? "yes" : "no");
+ str_yes_no(status));
}
return 0;
@@ -1438,7 +1439,7 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
struct device_node *parent)
{
struct of_phandle_args child_args, parent_args;
- struct device_node *np, *child;
+ struct device_node *np;
int err = 0;
/*
@@ -1457,12 +1458,10 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
if (!np)
return 0;
- for_each_child_of_node(np, child) {
+ for_each_child_of_node_scoped(np, child) {
err = tegra_powergate_add(pmc, child);
- if (err < 0) {
- of_node_put(child);
+ if (err < 0)
break;
- }
if (of_parse_phandle_with_args(child, "power-domains",
"#power-domain-cells",
@@ -1474,10 +1473,8 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
err = of_genpd_add_subdomain(&parent_args, &child_args);
of_node_put(parent_args.np);
- if (err) {
- of_node_put(child);
+ if (err)
break;
- }
}
of_node_put(np);
@@ -2503,8 +2500,9 @@ static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
pmc->irq.irq_set_type = pmc->soc->irq_set_type;
pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;
- pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
- &tegra_pmc_irq_domain_ops, pmc);
+ pmc->domain = irq_domain_create_hierarchy(parent, 0, 96,
+ of_fwnode_handle(pmc->dev->of_node),
+ &tegra_pmc_irq_domain_ops, pmc);
if (!pmc->domain) {
dev_err(pmc->dev, "failed to allocate domain\n");
return -ENOMEM;
@@ -2891,15 +2889,11 @@ static int tegra_pmc_probe(struct platform_device *pdev)
pmc->aotag = base;
pmc->scratch = base;
} else {
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "wake");
- pmc->wake = devm_ioremap_resource(&pdev->dev, res);
+ pmc->wake = devm_platform_ioremap_resource_byname(pdev, "wake");
if (IS_ERR(pmc->wake))
return PTR_ERR(pmc->wake);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "aotag");
- pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
+ pmc->aotag = devm_platform_ioremap_resource_byname(pdev, "aotag");
if (IS_ERR(pmc->aotag))
return PTR_ERR(pmc->aotag);
@@ -4074,6 +4068,7 @@ static const char * const tegra194_reset_sources[] = {
};
static const struct tegra_wake_event tegra194_wake_events[] = {
+ TEGRA_WAKE_GPIO("eqos", 20, 0, TEGRA194_MAIN_GPIO(G, 4)),
TEGRA_WAKE_IRQ("pmu", 24, 209),
TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
TEGRA_WAKE_IRQ("rtc", 73, 10),
@@ -4210,6 +4205,7 @@ static const char * const tegra234_reset_sources[] = {
static const struct tegra_wake_event tegra234_wake_events[] = {
TEGRA_WAKE_GPIO("sd-wake", 8, 0, TEGRA234_MAIN_GPIO(G, 7)),
+ TEGRA_WAKE_GPIO("eqos", 20, 0, TEGRA234_MAIN_GPIO(G, 4)),
TEGRA_WAKE_IRQ("pmu", 24, 209),
TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)),
TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)),
diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c
index fd4251d75935..7602b8a909b0 100644
--- a/drivers/soc/ti/k3-ringacc.c
+++ b/drivers/soc/ti/k3-ringacc.c
@@ -161,7 +161,7 @@ struct k3_ring {
struct k3_ringacc_proxy_target_regs __iomem *proxy;
dma_addr_t ring_mem_dma;
void *ring_mem_virt;
- struct k3_ring_ops *ops;
+ const struct k3_ring_ops *ops;
u32 size;
enum k3_ring_size elm_size;
enum k3_ring_mode mode;
@@ -268,17 +268,17 @@ static int k3_ringacc_ring_pop_mem(struct k3_ring *ring, void *elem);
static int k3_dmaring_fwd_pop(struct k3_ring *ring, void *elem);
static int k3_dmaring_reverse_pop(struct k3_ring *ring, void *elem);
-static struct k3_ring_ops k3_ring_mode_ring_ops = {
+static const struct k3_ring_ops k3_ring_mode_ring_ops = {
.push_tail = k3_ringacc_ring_push_mem,
.pop_head = k3_ringacc_ring_pop_mem,
};
-static struct k3_ring_ops k3_dmaring_fwd_ops = {
+static const struct k3_ring_ops k3_dmaring_fwd_ops = {
.push_tail = k3_ringacc_ring_push_mem,
.pop_head = k3_dmaring_fwd_pop,
};
-static struct k3_ring_ops k3_dmaring_reverse_ops = {
+static const struct k3_ring_ops k3_dmaring_reverse_ops = {
/* Reverse side of the DMA ring can only be popped by SW */
.pop_head = k3_dmaring_reverse_pop,
};
@@ -288,7 +288,7 @@ static int k3_ringacc_ring_pop_io(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_push_head_io(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_pop_tail_io(struct k3_ring *ring, void *elem);
-static struct k3_ring_ops k3_ring_mode_msg_ops = {
+static const struct k3_ring_ops k3_ring_mode_msg_ops = {
.push_tail = k3_ringacc_ring_push_io,
.push_head = k3_ringacc_ring_push_head_io,
.pop_tail = k3_ringacc_ring_pop_tail_io,
@@ -300,7 +300,7 @@ static int k3_ringacc_ring_push_tail_proxy(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_pop_head_proxy(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_pop_tail_proxy(struct k3_ring *ring, void *elem);
-static struct k3_ring_ops k3_ring_mode_proxy_ops = {
+static const struct k3_ring_ops k3_ring_mode_proxy_ops = {
.push_tail = k3_ringacc_ring_push_tail_proxy,
.push_head = k3_ringacc_ring_push_head_proxy,
.pop_tail = k3_ringacc_ring_pop_tail_proxy,
@@ -1291,7 +1291,7 @@ struct k3_ringacc *of_k3_ringacc_get_by_phandle(struct device_node *np,
mutex_lock(&k3_ringacc_list_lock);
list_for_each_entry(entry, &k3_ringacc_list, list)
- if (entry->dev->of_node == ringacc_np) {
+ if (device_match_of_node(entry->dev, ringacc_np)) {
ringacc = entry;
break;
}
@@ -1562,7 +1562,7 @@ static void k3_ringacc_remove(struct platform_device *pdev)
static struct platform_driver k3_ringacc_driver = {
.probe = k3_ringacc_probe,
- .remove_new = k3_ringacc_remove,
+ .remove = k3_ringacc_remove,
.driver = {
.name = "k3-ringacc",
.of_match_table = k3_ringacc_of_match,
diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c
index 59101bf7cf23..d716be113c84 100644
--- a/drivers/soc/ti/k3-socinfo.c
+++ b/drivers/soc/ti/k3-socinfo.c
@@ -43,6 +43,7 @@
#define JTAG_ID_PARTNO_AM62AX 0xBB8D
#define JTAG_ID_PARTNO_AM62PX 0xBB9D
#define JTAG_ID_PARTNO_J722S 0xBBA0
+#define JTAG_ID_PARTNO_AM62LX 0xBBA7
static const struct k3_soc_id {
unsigned int id;
@@ -58,10 +59,11 @@ static const struct k3_soc_id {
{ JTAG_ID_PARTNO_AM62AX, "AM62AX" },
{ JTAG_ID_PARTNO_AM62PX, "AM62PX" },
{ JTAG_ID_PARTNO_J722S, "J722S" },
+ { JTAG_ID_PARTNO_AM62LX, "AM62LX" },
};
static const char * const j721e_rev_string_map[] = {
- "1.0", "1.1",
+ "1.0", "1.1", "2.0",
};
static int
@@ -105,6 +107,12 @@ err_unknown_variant:
return -ENODEV;
}
+static const struct regmap_config k3_chipinfo_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int k3_chipinfo_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -112,13 +120,18 @@ static int k3_chipinfo_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct soc_device *soc_dev;
struct regmap *regmap;
+ void __iomem *base;
u32 partno_id;
u32 variant;
u32 jtag_id;
u32 mfg;
int ret;
- regmap = device_node_to_regmap(node);
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = regmap_init_mmio(dev, base, &k3_chipinfo_regmap_cfg);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c
index 6023006685fc..a25ebe6cd503 100644
--- a/drivers/soc/ti/knav_dma.c
+++ b/drivers/soc/ti/knav_dma.c
@@ -602,7 +602,7 @@ static int dma_init(struct device_node *cloud, struct device_node *dma_node)
unsigned max_tx_chan, max_rx_chan, max_rx_flow, max_tx_sched;
struct device_node *node = dma_node;
struct knav_dma_device *dma;
- int ret, len, num_chan = 0;
+ int ret, num_chan = 0;
resource_size_t size;
u32 timeout;
u32 i;
@@ -615,25 +615,13 @@ static int dma_init(struct device_node *cloud, struct device_node *dma_node)
INIT_LIST_HEAD(&dma->list);
INIT_LIST_HEAD(&dma->chan_list);
- if (!of_find_property(cloud, "ti,navigator-cloud-address", &len)) {
- dev_err(kdev->dev, "unspecified navigator cloud addresses\n");
- return -ENODEV;
- }
-
- dma->logical_queue_managers = len / sizeof(u32);
- if (dma->logical_queue_managers > DMA_MAX_QMS) {
- dev_warn(kdev->dev, "too many queue mgrs(>%d) rest ignored\n",
- dma->logical_queue_managers);
- dma->logical_queue_managers = DMA_MAX_QMS;
- }
-
- ret = of_property_read_u32_array(cloud, "ti,navigator-cloud-address",
- dma->qm_base_address,
- dma->logical_queue_managers);
- if (ret) {
+ ret = of_property_read_variable_u32_array(cloud, "ti,navigator-cloud-address",
+ dma->qm_base_address, 1, DMA_MAX_QMS);
+ if (ret < 0) {
dev_err(kdev->dev, "invalid navigator cloud addresses\n");
return -ENODEV;
}
+ dma->logical_queue_managers = ret;
dma->reg_global = pktdma_get_regs(dma, node, 0, &size);
if (IS_ERR(dma->reg_global))
@@ -795,8 +783,8 @@ MODULE_DEVICE_TABLE(of, of_match);
static struct platform_driver knav_dma_driver = {
.probe = knav_dma_probe,
- .remove_new = knav_dma_remove,
- .driver = {
+ .remove = knav_dma_remove,
+ .driver = {
.name = "keystone-navigator-dma",
.of_match_table = of_match,
},
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h
index a01eda720bf6..9325e8ce2e25 100644
--- a/drivers/soc/ti/knav_qmss.h
+++ b/drivers/soc/ti/knav_qmss.h
@@ -333,7 +333,7 @@ struct knav_range_info {
void *queue_base_inst;
unsigned flags;
struct list_head list;
- struct knav_range_ops *ops;
+ const struct knav_range_ops *ops;
struct knav_acc_info acc_info;
struct knav_acc_channel *acc;
unsigned num_irqs;
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index 3d388646ed43..269b4e75ae40 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -450,7 +450,7 @@ static int knav_acc_free_range(struct knav_range_info *range)
return 0;
}
-static struct knav_range_ops knav_acc_range_ops = {
+static const struct knav_range_ops knav_acc_range_ops = {
.set_notify = knav_acc_set_notify,
.init_queue = knav_acc_init_queue,
.open_queue = knav_acc_open_queue,
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index 06fb5505c22c..6e56e7609ccd 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -119,11 +119,10 @@ static int knav_queue_setup_irq(struct knav_range_info *range,
if (range->flags & RANGE_HAS_IRQ) {
irq = range->irqs[queue].irq;
- ret = request_irq(irq, knav_queue_int_handler, 0,
- inst->irq_name, inst);
+ ret = request_irq(irq, knav_queue_int_handler, IRQF_NO_AUTOEN,
+ inst->irq_name, inst);
if (ret)
return ret;
- disable_irq(irq);
if (range->irqs[queue].cpu_mask) {
ret = irq_set_affinity_hint(irq, range->irqs[queue].cpu_mask);
if (ret) {
@@ -253,8 +252,7 @@ static struct knav_queue *__knav_queue_open(struct knav_queue_inst *inst,
return qh;
err:
- if (qh->stats)
- free_percpu(qh->stats);
+ free_percpu(qh->stats);
devm_kfree(inst->kdev->dev, qh);
return ERR_PTR(ret);
}
@@ -411,7 +409,7 @@ static int knav_gp_close_queue(struct knav_range_info *range,
return 0;
}
-static struct knav_range_ops knav_gp_range_ops = {
+static const struct knav_range_ops knav_gp_range_ops = {
.set_notify = knav_gp_set_notify,
.open_queue = knav_gp_open_queue,
.close_queue = knav_gp_close_queue,
@@ -723,7 +721,6 @@ static void kdesc_empty_pool(struct knav_pool *pool)
if (!desc) {
dev_dbg(pool->kdev->dev,
"couldn't unmap desc, continuing\n");
- continue;
}
}
WARN_ON(i != pool->num_desc);
@@ -1076,14 +1073,20 @@ static const char *knav_queue_find_name(struct device_node *node)
}
static int knav_queue_setup_regions(struct knav_device *kdev,
- struct device_node *regions)
+ struct device_node *node)
{
struct device *dev = kdev->dev;
+ struct device_node *regions __free(device_node) =
+ of_get_child_by_name(node, "descriptor-regions");
struct knav_region *region;
struct device_node *child;
u32 temp[2];
int ret;
+ if (!regions)
+ return dev_err_probe(dev, -ENODEV,
+ "descriptor-regions not specified\n");
+
for_each_child_of_node(regions, child) {
region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
if (!region) {
@@ -1104,11 +1107,6 @@ static int knav_queue_setup_regions(struct knav_device *kdev,
continue;
}
- if (!of_get_property(child, "link-index", NULL)) {
- dev_err(dev, "No link info for %s\n", region->name);
- devm_kfree(dev, region);
- continue;
- }
ret = of_property_read_u32(child, "link-index",
&region->link_index);
if (ret) {
@@ -1121,10 +1119,9 @@ static int knav_queue_setup_regions(struct knav_device *kdev,
INIT_LIST_HEAD(&region->pools);
list_add_tail(&region->list, &kdev->regions);
}
- if (list_empty(&kdev->regions)) {
- dev_err(dev, "no valid region information found\n");
- return -ENODEV;
- }
+ if (list_empty(&kdev->regions))
+ return dev_err_probe(dev, -ENODEV,
+ "no valid region information found\n");
/* Next, we run through the regions and set things up */
for_each_region(kdev, region)
@@ -1306,10 +1303,16 @@ static int knav_setup_queue_range(struct knav_device *kdev,
}
static int knav_setup_queue_pools(struct knav_device *kdev,
- struct device_node *queue_pools)
+ struct device_node *node)
{
+ struct device_node *queue_pools __free(device_node) =
+ of_get_child_by_name(node, "queue-pools");
struct device_node *type, *range;
+ if (!queue_pools)
+ return dev_err_probe(kdev->dev, -ENODEV,
+ "queue-pools not specified\n");
+
for_each_child_of_node(queue_pools, type) {
for_each_child_of_node(type, range) {
/* return value ignored, we init the rest... */
@@ -1318,10 +1321,9 @@ static int knav_setup_queue_pools(struct knav_device *kdev,
}
/* ... and barf if they all failed! */
- if (list_empty(&kdev->queue_ranges)) {
- dev_err(kdev->dev, "no valid queue range found\n");
- return -ENODEV;
- }
+ if (list_empty(&kdev->queue_ranges))
+ return dev_err_probe(kdev->dev, -ENODEV,
+ "no valid queue range found\n");
return 0;
}
@@ -1389,14 +1391,20 @@ static void __iomem *knav_queue_map_reg(struct knav_device *kdev,
}
static int knav_queue_init_qmgrs(struct knav_device *kdev,
- struct device_node *qmgrs)
+ struct device_node *node)
{
struct device *dev = kdev->dev;
+ struct device_node *qmgrs __free(device_node) =
+ of_get_child_by_name(node, "qmgrs");
struct knav_qmgr_info *qmgr;
struct device_node *child;
u32 temp[2];
int ret;
+ if (!qmgrs)
+ return dev_err_probe(dev, -ENODEV,
+ "queue manager info not specified\n");
+
for_each_child_of_node(qmgrs, child) {
qmgr = devm_kzalloc(dev, sizeof(*qmgr), GFP_KERNEL);
if (!qmgr) {
@@ -1668,6 +1676,26 @@ static int knav_queue_start_pdsps(struct knav_device *kdev)
return 0;
}
+static int knav_queue_setup_pdsps(struct knav_device *kdev,
+ struct device_node *node)
+{
+ struct device_node *pdsps __free(device_node) =
+ of_get_child_by_name(node, "pdsps");
+
+ if (pdsps) {
+ int ret;
+
+ ret = knav_queue_init_pdsps(kdev, pdsps);
+ if (ret)
+ return ret;
+
+ ret = knav_queue_start_pdsps(kdev);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
static inline struct knav_qmgr_info *knav_find_qmgr(unsigned id)
{
struct knav_qmgr_info *qmgr;
@@ -1755,7 +1783,6 @@ MODULE_DEVICE_TABLE(of, keystone_qmss_of_match);
static int knav_queue_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct device_node *qmgrs, *queue_pools, *regions, *pdsps;
struct device *dev = &pdev->dev;
u32 temp[2];
int ret;
@@ -1799,39 +1826,17 @@ static int knav_queue_probe(struct platform_device *pdev)
kdev->num_queues = temp[1];
/* Initialize queue managers using device tree configuration */
- qmgrs = of_get_child_by_name(node, "qmgrs");
- if (!qmgrs) {
- dev_err(dev, "queue manager info not specified\n");
- ret = -ENODEV;
- goto err;
- }
- ret = knav_queue_init_qmgrs(kdev, qmgrs);
- of_node_put(qmgrs);
+ ret = knav_queue_init_qmgrs(kdev, node);
if (ret)
goto err;
/* get pdsp configuration values from device tree */
- pdsps = of_get_child_by_name(node, "pdsps");
- if (pdsps) {
- ret = knav_queue_init_pdsps(kdev, pdsps);
- if (ret)
- goto err;
-
- ret = knav_queue_start_pdsps(kdev);
- if (ret)
- goto err;
- }
- of_node_put(pdsps);
+ ret = knav_queue_setup_pdsps(kdev, node);
+ if (ret)
+ goto err;
/* get usable queue range values from device tree */
- queue_pools = of_get_child_by_name(node, "queue-pools");
- if (!queue_pools) {
- dev_err(dev, "queue-pools not specified\n");
- ret = -ENODEV;
- goto err;
- }
- ret = knav_setup_queue_pools(kdev, queue_pools);
- of_node_put(queue_pools);
+ ret = knav_setup_queue_pools(kdev, node);
if (ret)
goto err;
@@ -1853,14 +1858,7 @@ static int knav_queue_probe(struct platform_device *pdev)
if (ret)
goto err;
- regions = of_get_child_by_name(node, "descriptor-regions");
- if (!regions) {
- dev_err(dev, "descriptor-regions not specified\n");
- ret = -ENODEV;
- goto err;
- }
- ret = knav_queue_setup_regions(kdev, regions);
- of_node_put(regions);
+ ret = knav_queue_setup_regions(kdev, node);
if (ret)
goto err;
@@ -1893,7 +1891,7 @@ static void knav_queue_remove(struct platform_device *pdev)
static struct platform_driver keystone_qmss_driver = {
.probe = knav_queue_probe,
- .remove_new = knav_queue_remove,
+ .remove = knav_queue_remove,
.driver = {
.name = "keystone-navigator-qmss",
.of_match_table = keystone_qmss_of_match,
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index 8e983c3c4e03..dfdff186c805 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -383,54 +383,44 @@ static void am33xx_pm_free_sram(void)
*/
static int am33xx_pm_alloc_sram(void)
{
- struct device_node *np;
- int ret = 0;
+ struct device_node *np __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "ti,omap3-mpu");
- np = of_find_compatible_node(NULL, NULL, "ti,omap3-mpu");
if (!np) {
np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu");
- if (!np) {
- dev_err(pm33xx_dev, "PM: %s: Unable to find device node for mpu\n",
- __func__);
- return -ENODEV;
- }
+ if (!np)
+ return dev_err_probe(pm33xx_dev, -ENODEV,
+ "PM: %s: Unable to find device node for mpu\n",
+ __func__);
}
sram_pool = of_gen_pool_get(np, "pm-sram", 0);
- if (!sram_pool) {
- dev_err(pm33xx_dev, "PM: %s: Unable to get sram pool for ocmcram\n",
- __func__);
- ret = -ENODEV;
- goto mpu_put_node;
- }
+ if (!sram_pool)
+ return dev_err_probe(pm33xx_dev, -ENODEV,
+ "PM: %s: Unable to get sram pool for ocmcram\n",
+ __func__);
sram_pool_data = of_gen_pool_get(np, "pm-sram", 1);
- if (!sram_pool_data) {
- dev_err(pm33xx_dev, "PM: %s: Unable to get sram data pool for ocmcram\n",
- __func__);
- ret = -ENODEV;
- goto mpu_put_node;
- }
+ if (!sram_pool_data)
+ return dev_err_probe(pm33xx_dev, -ENODEV,
+ "PM: %s: Unable to get sram data pool for ocmcram\n",
+ __func__);
ocmcram_location = gen_pool_alloc(sram_pool, *pm_sram->do_wfi_sz);
- if (!ocmcram_location) {
- dev_err(pm33xx_dev, "PM: %s: Unable to allocate memory from ocmcram\n",
- __func__);
- ret = -ENOMEM;
- goto mpu_put_node;
- }
+ if (!ocmcram_location)
+ return dev_err_probe(pm33xx_dev, -ENOMEM,
+ "PM: %s: Unable to allocate memory from ocmcram\n",
+ __func__);
ocmcram_location_data = gen_pool_alloc(sram_pool_data,
sizeof(struct emif_regs_amx3));
if (!ocmcram_location_data) {
- dev_err(pm33xx_dev, "PM: Unable to allocate memory from ocmcram\n");
gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz);
- ret = -ENOMEM;
+ return dev_err_probe(pm33xx_dev, -ENOMEM,
+ "PM: Unable to allocate memory from ocmcram\n");
}
-mpu_put_node:
- of_node_put(np);
- return ret;
+ return 0;
}
static int am33xx_pm_rtc_setup(void)
@@ -450,14 +440,14 @@ static int am33xx_pm_rtc_setup(void)
rtc_base_virt = of_iomap(np, 0);
if (!rtc_base_virt) {
- pr_warn("PM: could not iomap rtc");
+ pr_warn("PM: could not iomap rtc\n");
error = -ENODEV;
goto err_clk_put;
}
omap_rtc = rtc_class_open("rtc0");
if (!omap_rtc) {
- pr_warn("PM: rtc0 not available");
+ pr_warn("PM: rtc0 not available\n");
error = -EPROBE_DEFER;
goto err_iounmap;
}
@@ -601,7 +591,7 @@ static struct platform_driver am33xx_pm_driver = {
.name = "pm33xx",
},
.probe = am33xx_pm_probe,
- .remove_new = am33xx_pm_remove,
+ .remove = am33xx_pm_remove,
};
module_platform_driver(am33xx_pm_driver);
diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
index 24a42e0b645c..d7634bf5413a 100644
--- a/drivers/soc/ti/pruss.c
+++ b/drivers/soc/ti/pruss.c
@@ -380,39 +380,81 @@ put_clk_mux_np:
static int pruss_clk_init(struct pruss *pruss, struct device_node *cfg_node)
{
- const struct pruss_private_data *data;
- struct device_node *clks_np;
struct device *dev = pruss->dev;
- int ret = 0;
-
- data = of_device_get_match_data(dev);
+ struct device_node *clks_np __free(device_node) =
+ of_get_child_by_name(cfg_node, "clocks");
+ const struct pruss_private_data *data = of_device_get_match_data(dev);
+ int ret;
- clks_np = of_get_child_by_name(cfg_node, "clocks");
- if (!clks_np) {
- dev_err(dev, "%pOF is missing its 'clocks' node\n", cfg_node);
- return -ENODEV;
- }
+ if (!clks_np)
+ return dev_err_probe(dev, -ENODEV,
+ "%pOF is missing its 'clocks' node\n",
+ cfg_node);
if (data && data->has_core_mux_clock) {
ret = pruss_clk_mux_setup(pruss, pruss->core_clk_mux,
"coreclk-mux", clks_np);
- if (ret) {
- dev_err(dev, "failed to setup coreclk-mux\n");
- goto put_clks_node;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to setup coreclk-mux\n");
}
ret = pruss_clk_mux_setup(pruss, pruss->iep_clk_mux, "iepclk-mux",
clks_np);
- if (ret) {
- dev_err(dev, "failed to setup iepclk-mux\n");
- goto put_clks_node;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to setup iepclk-mux\n");
-put_clks_node:
- of_node_put(clks_np);
+ return 0;
+}
- return ret;
+static int pruss_of_setup_memories(struct device *dev, struct pruss *pruss)
+{
+ struct device_node *np = dev_of_node(dev);
+ struct device_node *child __free(device_node) =
+ of_get_child_by_name(np, "memories");
+ const struct pruss_private_data *data = of_device_get_match_data(dev);
+ const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
+ int i;
+
+ if (!child)
+ return dev_err_probe(dev, -ENODEV,
+ "%pOF is missing its 'memories' node\n",
+ child);
+
+ for (i = 0; i < PRUSS_MEM_MAX; i++) {
+ struct resource res;
+ int index;
+
+ /*
+ * On AM437x one of two PRUSS units don't contain Shared RAM,
+ * skip it
+ */
+ if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2)
+ continue;
+
+ index = of_property_match_string(child, "reg-names",
+ mem_names[i]);
+ if (index < 0)
+ return index;
+
+ if (of_address_to_resource(child, index, &res))
+ return -EINVAL;
+
+ pruss->mem_regions[i].va = devm_ioremap(dev, res.start,
+ resource_size(&res));
+ if (!pruss->mem_regions[i].va)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to parse and map memory resource %d %s\n",
+ i, mem_names[i]);
+ pruss->mem_regions[i].pa = res.start;
+ pruss->mem_regions[i].size = resource_size(&res);
+
+ dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
+ mem_names[i], &pruss->mem_regions[i].pa,
+ pruss->mem_regions[i].size, pruss->mem_regions[i].va);
+ }
+
+ return 0;
}
static struct regmap_config regmap_conf = {
@@ -424,26 +466,21 @@ static struct regmap_config regmap_conf = {
static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss)
{
struct device_node *np = dev_of_node(dev);
- struct device_node *child;
+ struct device_node *child __free(device_node) =
+ of_get_child_by_name(np, "cfg");
struct resource res;
int ret;
- child = of_get_child_by_name(np, "cfg");
- if (!child) {
- dev_err(dev, "%pOF is missing its 'cfg' node\n", child);
- return -ENODEV;
- }
+ if (!child)
+ return dev_err_probe(dev, -ENODEV,
+ "%pOF is missing its 'cfg' node\n", child);
- if (of_address_to_resource(child, 0, &res)) {
- ret = -ENOMEM;
- goto node_put;
- }
+ if (of_address_to_resource(child, 0, &res))
+ return -ENOMEM;
pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res));
- if (!pruss->cfg_base) {
- ret = -ENOMEM;
- goto node_put;
- }
+ if (!pruss->cfg_base)
+ return -ENOMEM;
regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child,
(u64)res.start);
@@ -452,34 +489,22 @@ static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss)
pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base,
&regmap_conf);
kfree(regmap_conf.name);
- if (IS_ERR(pruss->cfg_regmap)) {
- dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n",
- PTR_ERR(pruss->cfg_regmap));
- ret = PTR_ERR(pruss->cfg_regmap);
- goto node_put;
- }
+ if (IS_ERR(pruss->cfg_regmap))
+ return dev_err_probe(dev, PTR_ERR(pruss->cfg_regmap),
+ "regmap_init_mmio failed for cfg\n");
ret = pruss_clk_init(pruss, child);
if (ret)
- dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret);
+ return dev_err_probe(dev, ret, "pruss_clk_init failed\n");
-node_put:
- of_node_put(child);
- return ret;
+ return 0;
}
static int pruss_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev_of_node(dev);
- struct device_node *child;
struct pruss *pruss;
- struct resource res;
- int ret, i, index;
- const struct pruss_private_data *data;
- const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
-
- data = of_device_get_match_data(&pdev->dev);
+ int ret;
ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (ret) {
@@ -494,48 +519,9 @@ static int pruss_probe(struct platform_device *pdev)
pruss->dev = dev;
mutex_init(&pruss->lock);
- child = of_get_child_by_name(np, "memories");
- if (!child) {
- dev_err(dev, "%pOF is missing its 'memories' node\n", child);
- return -ENODEV;
- }
-
- for (i = 0; i < PRUSS_MEM_MAX; i++) {
- /*
- * On AM437x one of two PRUSS units don't contain Shared RAM,
- * skip it
- */
- if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2)
- continue;
-
- index = of_property_match_string(child, "reg-names",
- mem_names[i]);
- if (index < 0) {
- of_node_put(child);
- return index;
- }
-
- if (of_address_to_resource(child, index, &res)) {
- of_node_put(child);
- return -EINVAL;
- }
-
- pruss->mem_regions[i].va = devm_ioremap(dev, res.start,
- resource_size(&res));
- if (!pruss->mem_regions[i].va) {
- dev_err(dev, "failed to parse and map memory resource %d %s\n",
- i, mem_names[i]);
- of_node_put(child);
- return -ENOMEM;
- }
- pruss->mem_regions[i].pa = res.start;
- pruss->mem_regions[i].size = resource_size(&res);
-
- dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
- mem_names[i], &pruss->mem_regions[i].pa,
- pruss->mem_regions[i].size, pruss->mem_regions[i].va);
- }
- of_node_put(child);
+ ret = pruss_of_setup_memories(dev, pruss);
+ if (ret < 0)
+ return ret;
platform_set_drvdata(pdev, pruss);
@@ -607,8 +593,8 @@ static struct platform_driver pruss_driver = {
.name = "pruss",
.of_match_table = pruss_of_match,
},
- .probe = pruss_probe,
- .remove_new = pruss_remove,
+ .probe = pruss_probe,
+ .remove = pruss_remove,
};
module_platform_driver(pruss_driver);
diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c
index d6219060b616..ced3a73929e3 100644
--- a/drivers/soc/ti/smartreflex.c
+++ b/drivers/soc/ti/smartreflex.c
@@ -202,10 +202,10 @@ static int sr_late_init(struct omap_sr *sr_info)
if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq,
- sr_interrupt, 0, sr_info->name, sr_info);
+ sr_interrupt, IRQF_NO_AUTOEN,
+ sr_info->name, sr_info);
if (ret)
goto error;
- disable_irq(sr_info->irq);
}
return ret;
@@ -969,7 +969,7 @@ MODULE_DEVICE_TABLE(of, omap_sr_match);
static struct platform_driver smartreflex_driver = {
.probe = omap_sr_probe,
- .remove_new = omap_sr_remove,
+ .remove = omap_sr_remove,
.shutdown = omap_sr_shutdown,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/soc/ti/ti_sci_inta_msi.c b/drivers/soc/ti/ti_sci_inta_msi.c
index c36364522157..193266f5e3f9 100644
--- a/drivers/soc/ti/ti_sci_inta_msi.c
+++ b/drivers/soc/ti/ti_sci_inta_msi.c
@@ -103,19 +103,15 @@ int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev,
if (ret)
return ret;
- msi_lock_descs(dev);
+ guard(msi_descs_lock)(dev);
nvec = ti_sci_inta_msi_alloc_descs(dev, res);
- if (nvec <= 0) {
- ret = nvec;
- goto unlock;
- }
+ if (nvec <= 0)
+ return nvec;
/* Use alloc ALL as it's unclear whether there are gaps in the indices */
ret = msi_domain_alloc_irqs_all_locked(dev, MSI_DEFAULT_DOMAIN, nvec);
if (ret)
dev_err(dev, "Failed to allocate IRQs %d\n", ret);
-unlock:
- msi_unlock_descs(dev);
return ret;
}
EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_alloc_irqs);
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index 6a1c6b34c414..5845fc652adc 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -16,7 +16,6 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/omap-mailbox.h>
#include <linux/platform_device.h>
#include <linux/remoteproc.h>
#include <linux/suspend.h>
@@ -314,7 +313,6 @@ static irqreturn_t wkup_m3_txev_handler(int irq, void *ipc_data)
static int wkup_m3_ping(struct wkup_m3_ipc *m3_ipc)
{
struct device *dev = m3_ipc->dev;
- mbox_msg_t dummy_msg = 0;
int ret;
if (!m3_ipc->mbox) {
@@ -330,7 +328,7 @@ static int wkup_m3_ping(struct wkup_m3_ipc *m3_ipc)
* the RX callback to avoid multiple interrupts being received
* by the CM3.
*/
- ret = mbox_send_message(m3_ipc->mbox, &dummy_msg);
+ ret = mbox_send_message(m3_ipc->mbox, NULL);
if (ret < 0) {
dev_err(dev, "%s: mbox_send_message() failed: %d\n",
__func__, ret);
@@ -352,7 +350,6 @@ static int wkup_m3_ping(struct wkup_m3_ipc *m3_ipc)
static int wkup_m3_ping_noirq(struct wkup_m3_ipc *m3_ipc)
{
struct device *dev = m3_ipc->dev;
- mbox_msg_t dummy_msg = 0;
int ret;
if (!m3_ipc->mbox) {
@@ -361,7 +358,7 @@ static int wkup_m3_ping_noirq(struct wkup_m3_ipc *m3_ipc)
return -EIO;
}
- ret = mbox_send_message(m3_ipc->mbox, &dummy_msg);
+ ret = mbox_send_message(m3_ipc->mbox, NULL);
if (ret < 0) {
dev_err(dev, "%s: mbox_send_message() failed: %d\n",
__func__, ret);
@@ -647,11 +644,9 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
m3_ipc->mbox = mbox_request_channel(&m3_ipc->mbox_client, 0);
- if (IS_ERR(m3_ipc->mbox)) {
- dev_err(dev, "IPC Request for A8->M3 Channel failed! %ld\n",
- PTR_ERR(m3_ipc->mbox));
- return PTR_ERR(m3_ipc->mbox);
- }
+ if (IS_ERR(m3_ipc->mbox))
+ return dev_err_probe(dev, PTR_ERR(m3_ipc->mbox),
+ "IPC Request for A8->M3 Channel failed!\n");
if (of_property_read_u32(dev->of_node, "ti,rproc", &rproc_phandle)) {
dev_err(&pdev->dev, "could not get rproc phandle\n");
@@ -758,7 +753,7 @@ MODULE_DEVICE_TABLE(of, wkup_m3_ipc_of_match);
static struct platform_driver wkup_m3_ipc_driver = {
.probe = wkup_m3_ipc_probe,
- .remove_new = wkup_m3_ipc_remove,
+ .remove = wkup_m3_ipc_remove,
.driver = {
.name = "wkup_m3_ipc",
.of_match_table = wkup_m3_ipc_of_match,
diff --git a/drivers/soc/versatile/Kconfig b/drivers/soc/versatile/Kconfig
index c3792c0a84ac..7bbf54a8d879 100644
--- a/drivers/soc/versatile/Kconfig
+++ b/drivers/soc/versatile/Kconfig
@@ -4,7 +4,7 @@
#
config SOC_INTEGRATOR_CM
bool "SoC bus device for the ARM Integrator platform core modules"
- depends on ARCH_INTEGRATOR
+ depends on ARCH_INTEGRATOR || COMPILE_TEST
select SOC_BUS
help
Include support for the SoC bus on the ARM Integrator platform
@@ -13,7 +13,7 @@ config SOC_INTEGRATOR_CM
config SOC_REALVIEW
bool "SoC bus device for the ARM RealView platforms"
- depends on ARCH_REALVIEW
+ depends on ARCH_REALVIEW || COMPILE_TEST
select SOC_BUS
help
Include support for the SoC bus on the ARM RealView platforms
diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c
index bab4ad87aa75..d5099a3386b4 100644
--- a/drivers/soc/versatile/soc-integrator.c
+++ b/drivers/soc/versatile/soc-integrator.c
@@ -113,6 +113,7 @@ static int __init integrator_soc_init(void)
return -ENODEV;
syscon_regmap = syscon_node_to_regmap(np);
+ of_node_put(np);
if (IS_ERR(syscon_regmap))
return PTR_ERR(syscon_regmap);
diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c
index c6876d232d8f..cf91abe07d38 100644
--- a/drivers/soc/versatile/soc-realview.c
+++ b/drivers/soc/versatile/soc-realview.c
@@ -4,6 +4,7 @@
*
* Author: Linus Walleij <linus.walleij@linaro.org>
*/
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -81,6 +82,13 @@ static struct attribute *realview_attrs[] = {
ATTRIBUTE_GROUPS(realview);
+static void realview_soc_socdev_release(void *data)
+{
+ struct soc_device *soc_dev = data;
+
+ soc_device_unregister(soc_dev);
+}
+
static int realview_soc_probe(struct platform_device *pdev)
{
struct regmap *syscon_regmap;
@@ -93,7 +101,7 @@ static int realview_soc_probe(struct platform_device *pdev)
if (IS_ERR(syscon_regmap))
return PTR_ERR(syscon_regmap);
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
@@ -106,10 +114,14 @@ static int realview_soc_probe(struct platform_device *pdev)
soc_dev_attr->family = "Versatile";
soc_dev_attr->custom_attr_group = realview_groups[0];
soc_dev = soc_device_register(soc_dev_attr);
- if (IS_ERR(soc_dev)) {
- kfree(soc_dev_attr);
+ if (IS_ERR(soc_dev))
return -ENODEV;
- }
+
+ ret = devm_add_action_or_reset(&pdev->dev, realview_soc_socdev_release,
+ soc_dev);
+ if (ret)
+ return ret;
+
ret = regmap_read(syscon_regmap, REALVIEW_SYS_ID_OFFSET,
&realview_coreid);
if (ret)
diff --git a/drivers/soc/vt8500/Kconfig b/drivers/soc/vt8500/Kconfig
new file mode 100644
index 000000000000..b4cc0ba1128b
--- /dev/null
+++ b/drivers/soc/vt8500/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_VT8500 || COMPILE_TEST
+
+menu "VIA/WonderMedia SoC drivers"
+
+config WMT_SOCINFO
+ bool "VIA/WonderMedia SoC Information driver"
+ default ARCH_VT8500
+ select SOC_BUS
+ help
+ Say yes to support decoding of VIA/WonderMedia system configuration
+ register information. This currently includes just the chip ID register
+ which helps identify the exact hardware revision of the SoC the kernel
+ is running on (to know if any revision-specific quirks are required)
+
+endmenu
+
+endif
diff --git a/drivers/soc/vt8500/Makefile b/drivers/soc/vt8500/Makefile
new file mode 100644
index 000000000000..05964c5f2890
--- /dev/null
+++ b/drivers/soc/vt8500/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_WMT_SOCINFO) += wmt-socinfo.o
diff --git a/drivers/soc/vt8500/wmt-socinfo.c b/drivers/soc/vt8500/wmt-socinfo.c
new file mode 100644
index 000000000000..461f8c1ae56e
--- /dev/null
+++ b/drivers/soc/vt8500/wmt-socinfo.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2025 Alexey Charkov <alchark@gmail.com>
+ * Based on aspeed-socinfo.c
+ */
+
+#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+
+static const struct {
+ const char *name;
+ const u32 id;
+} chip_id_table[] = {
+ /* VIA */
+ { "VT8420", 0x3300 },
+ { "VT8430", 0x3357 },
+ { "VT8500", 0x3400 },
+
+ /* WonderMedia */
+ { "WM8425", 0x3429 },
+ { "WM8435", 0x3437 },
+ { "WM8440", 0x3451 },
+ { "WM8505", 0x3426 },
+ { "WM8650", 0x3465 },
+ { "WM8750", 0x3445 },
+ { "WM8850", 0x3481 },
+ { "WM8880", 0x3498 },
+};
+
+static const char *sccid_to_name(u32 sccid)
+{
+ u32 id = sccid >> 16;
+ unsigned int i;
+
+ for (i = 0 ; i < ARRAY_SIZE(chip_id_table) ; ++i) {
+ if (chip_id_table[i].id == id)
+ return chip_id_table[i].name;
+ }
+
+ return "Unknown";
+}
+
+static int wmt_socinfo_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct soc_device_attribute *attrs;
+ struct soc_device *soc_dev;
+ char letter, digit;
+ void __iomem *reg;
+ u32 sccid;
+
+ reg = devm_of_iomap(&pdev->dev, np, 0, NULL);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ sccid = readl(reg);
+
+ attrs = devm_kzalloc(&pdev->dev, sizeof(*attrs), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ /*
+ * Machine: VIA APC Rock
+ * Family: WM8850
+ * Revision: A2
+ * SoC ID: raw silicon revision id (34810103 in hexadecimal)
+ */
+
+ attrs->family = sccid_to_name(sccid);
+
+ letter = (sccid >> 8) & 0xf;
+ letter = (letter - 1) + 'A';
+ digit = sccid & 0xff;
+ digit = (digit - 1) + '0';
+ attrs->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "%c%c", letter, digit);
+
+ attrs->soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%08x", sccid);
+
+ if (!attrs->revision || !attrs->soc_id)
+ return -ENOMEM;
+
+ soc_dev = soc_device_register(attrs);
+ if (IS_ERR(soc_dev))
+ return PTR_ERR(soc_dev);
+
+ dev_info(&pdev->dev,
+ "VIA/WonderMedia %s rev %s (%s)\n",
+ attrs->family,
+ attrs->revision,
+ attrs->soc_id);
+
+ platform_set_drvdata(pdev, soc_dev);
+ return 0;
+}
+
+static void wmt_socinfo_remove(struct platform_device *pdev)
+{
+ struct soc_device *soc_dev = platform_get_drvdata(pdev);
+
+ soc_device_unregister(soc_dev);
+}
+
+static const struct of_device_id wmt_socinfo_ids[] = {
+ { .compatible = "via,vt8500-scc-id" },
+ { /* Sentinel */ },
+};
+
+static struct platform_driver wmt_socinfo = {
+ .probe = wmt_socinfo_probe,
+ .remove = wmt_socinfo_remove,
+ .driver = {
+ .name = "wmt-socinfo",
+ .of_match_table = wmt_socinfo_ids,
+ },
+};
+module_platform_driver(wmt_socinfo);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("VIA/WonderMedia socinfo driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/soc/xilinx/xlnx_event_manager.c b/drivers/soc/xilinx/xlnx_event_manager.c
index 253299e4214d..a572d15f6161 100644
--- a/drivers/soc/xilinx/xlnx_event_manager.c
+++ b/drivers/soc/xilinx/xlnx_event_manager.c
@@ -3,6 +3,7 @@
* Xilinx Event Management Driver
*
* Copyright (C) 2021 Xilinx, Inc.
+ * Copyright (C) 2024 Advanced Micro Devices, Inc.
*
* Abhyuday Godhasara <abhyuday.godhasara@xilinx.com>
*/
@@ -19,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-static DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number1);
+static DEFINE_PER_CPU_READ_MOSTLY(int, dummy_cpu_number);
static int virq_sgi;
static int event_manager_availability = -EACCES;
@@ -35,7 +36,6 @@ static int event_manager_availability = -EACCES;
#define MAX_BITS (32U) /* Number of bits available for error mask */
-#define FIRMWARE_VERSION_MASK (0xFFFFU)
#define REGISTER_NOTIFIER_FIRMWARE_VERSION (2U)
static DEFINE_HASHTABLE(reg_driver_map, REGISTERED_DRIVER_MAX_ORDER);
@@ -188,8 +188,10 @@ static int xlnx_add_cb_for_suspend(event_cb_func_t cb_fun, void *data)
INIT_LIST_HEAD(&eve_data->cb_list_head);
cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL);
- if (!cb_data)
+ if (!cb_data) {
+ kfree(eve_data);
return -ENOMEM;
+ }
cb_data->eve_cb = cb_fun;
cb_data->agent_data = data;
@@ -570,7 +572,6 @@ static void xlnx_disable_percpu_irq(void *data)
static int xlnx_event_init_sgi(struct platform_device *pdev)
{
int ret = 0;
- int cpu;
/*
* IRQ related structures are used for the following:
* for each SGI interrupt ensure its mapped by GIC IRQ domain
@@ -607,11 +608,8 @@ static int xlnx_event_init_sgi(struct platform_device *pdev)
sgi_fwspec.param[0] = sgi_num;
virq_sgi = irq_create_fwspec_mapping(&sgi_fwspec);
- cpu = get_cpu();
- per_cpu(cpu_number1, cpu) = cpu;
ret = request_percpu_irq(virq_sgi, xlnx_event_handler, "xlnx_event_mgmt",
- &cpu_number1);
- put_cpu();
+ &dummy_cpu_number);
WARN_ON(ret);
if (ret) {
@@ -627,16 +625,12 @@ static int xlnx_event_init_sgi(struct platform_device *pdev)
static void xlnx_event_cleanup_sgi(struct platform_device *pdev)
{
- int cpu = smp_processor_id();
-
- per_cpu(cpu_number1, cpu) = cpu;
-
cpuhp_remove_state(CPUHP_AP_ONLINE_DYN);
on_each_cpu(xlnx_disable_percpu_irq, NULL, 1);
irq_clear_status_flags(virq_sgi, IRQ_PER_CPU);
- free_percpu_irq(virq_sgi, &cpu_number1);
+ free_percpu_irq(virq_sgi, &dummy_cpu_number);
irq_dispose_mapping(virq_sgi);
}
@@ -717,7 +711,7 @@ static void xlnx_event_manager_remove(struct platform_device *pdev)
static struct platform_driver xlnx_event_manager_driver = {
.probe = xlnx_event_manager_probe,
- .remove_new = xlnx_event_manager_remove,
+ .remove = xlnx_event_manager_remove,
.driver = {
.name = "xlnx_event_manager",
},
diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c
index 965b1143936a..ae59bf16659a 100644
--- a/drivers/soc/xilinx/zynqmp_power.c
+++ b/drivers/soc/xilinx/zynqmp_power.c
@@ -30,9 +30,27 @@ struct zynqmp_pm_work_struct {
u32 args[CB_ARG_CNT];
};
-static struct zynqmp_pm_work_struct *zynqmp_pm_init_suspend_work;
+/**
+ * struct zynqmp_pm_event_info - event related information
+ * @cb_fun: Function pointer to store the callback function.
+ * @cb_type: Type of callback from pm_api_cb_id,
+ * PM_NOTIFY_CB - for Error Events,
+ * PM_INIT_SUSPEND_CB - for suspend callback.
+ * @node_id: Node-Id related to event.
+ * @event: Event Mask for the Error Event.
+ * @wake: Flag specifying whether the subsystem should be woken upon
+ * event notification.
+ */
+struct zynqmp_pm_event_info {
+ event_cb_func_t cb_fun;
+ enum pm_api_cb_id cb_type;
+ u32 node_id;
+ u32 event;
+ bool wake;
+};
+
+static struct zynqmp_pm_work_struct *zynqmp_pm_init_suspend_work, *zynqmp_pm_init_restart_work;
static struct mbox_chan *rx_chan;
-static bool event_registered;
enum pm_suspend_mode {
PM_SUSPEND_MODE_FIRST = 0,
@@ -54,6 +72,19 @@ static void zynqmp_pm_get_callback_data(u32 *buf)
zynqmp_pm_invoke_fn(GET_CALLBACK_DATA, buf, 0);
}
+static void subsystem_restart_event_callback(const u32 *payload, void *data)
+{
+ /* First element is callback API ID, others are callback arguments */
+ if (work_pending(&zynqmp_pm_init_restart_work->callback_work))
+ return;
+
+ /* Copy callback arguments into work's structure */
+ memcpy(zynqmp_pm_init_restart_work->args, &payload[0],
+ sizeof(zynqmp_pm_init_restart_work->args));
+
+ queue_work(system_unbound_wq, &zynqmp_pm_init_restart_work->callback_work);
+}
+
static void suspend_event_callback(const u32 *payload, void *data)
{
/* First element is callback API ID, others are callback arguments */
@@ -120,6 +151,37 @@ static void ipi_receive_callback(struct mbox_client *cl, void *data)
}
/**
+ * zynqmp_pm_subsystem_restart_work_fn - Initiate Subsystem restart
+ * @work: Pointer to work_struct
+ *
+ * Bottom-half of PM callback IRQ handler.
+ */
+static void zynqmp_pm_subsystem_restart_work_fn(struct work_struct *work)
+{
+ int ret;
+ struct zynqmp_pm_work_struct *pm_work = container_of(work, struct zynqmp_pm_work_struct,
+ callback_work);
+
+ /* First element is callback API ID, others are callback arguments */
+ if (pm_work->args[0] == PM_NOTIFY_CB) {
+ if (pm_work->args[2] == EVENT_SUBSYSTEM_RESTART) {
+ ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
+ ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM);
+ if (ret) {
+ pr_err("unable to set shutdown scope\n");
+ return;
+ }
+
+ kernel_restart(NULL);
+ } else {
+ pr_err("%s Unsupported Event - %d\n", __func__, pm_work->args[2]);
+ }
+ } else {
+ pr_err("%s() Unsupported Callback %d\n", __func__, pm_work->args[0]);
+ }
+}
+
+/**
* zynqmp_pm_init_suspend_work_fn - Initialize suspend
* @work: Pointer to work_struct
*
@@ -184,13 +246,51 @@ static ssize_t suspend_mode_store(struct device *dev,
static DEVICE_ATTR_RW(suspend_mode);
+static void unregister_event(struct device *dev, void *res)
+{
+ struct zynqmp_pm_event_info *event_info = res;
+
+ xlnx_unregister_event(event_info->cb_type, event_info->node_id,
+ event_info->event, event_info->cb_fun, NULL);
+}
+
+static int register_event(struct device *dev, const enum pm_api_cb_id cb_type, const u32 node_id,
+ const u32 event, const bool wake, event_cb_func_t cb_fun)
+{
+ int ret;
+ struct zynqmp_pm_event_info *event_info;
+
+ event_info = devres_alloc(unregister_event, sizeof(struct zynqmp_pm_event_info),
+ GFP_KERNEL);
+ if (!event_info)
+ return -ENOMEM;
+
+ event_info->cb_type = cb_type;
+ event_info->node_id = node_id;
+ event_info->event = event;
+ event_info->wake = wake;
+ event_info->cb_fun = cb_fun;
+
+ ret = xlnx_register_event(event_info->cb_type, event_info->node_id,
+ event_info->event, event_info->wake, event_info->cb_fun, NULL);
+ if (ret) {
+ devres_free(event_info);
+ return ret;
+ }
+
+ devres_add(dev, event_info);
+ return 0;
+}
+
static int zynqmp_pm_probe(struct platform_device *pdev)
{
int ret, irq;
- u32 pm_api_version;
+ u32 pm_api_version, pm_family_code, pm_sub_family_code, node_id;
struct mbox_client *client;
- zynqmp_pm_get_api_version(&pm_api_version);
+ ret = zynqmp_pm_get_api_version(&pm_api_version);
+ if (ret)
+ return ret;
/* Check PM API version number */
if (pm_api_version < ZYNQMP_PM_VERSION)
@@ -203,21 +303,43 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
* is not available to use) or -ENODEV(Xilinx Event Manager not compiled),
* then use ipi-mailbox or interrupt method.
*/
- ret = xlnx_register_event(PM_INIT_SUSPEND_CB, 0, 0, false,
- suspend_event_callback, NULL);
+ ret = register_event(&pdev->dev, PM_INIT_SUSPEND_CB, 0, 0, false,
+ suspend_event_callback);
if (!ret) {
zynqmp_pm_init_suspend_work = devm_kzalloc(&pdev->dev,
sizeof(struct zynqmp_pm_work_struct),
GFP_KERNEL);
- if (!zynqmp_pm_init_suspend_work) {
- xlnx_unregister_event(PM_INIT_SUSPEND_CB, 0, 0,
- suspend_event_callback, NULL);
+ if (!zynqmp_pm_init_suspend_work)
return -ENOMEM;
- }
- event_registered = true;
INIT_WORK(&zynqmp_pm_init_suspend_work->callback_work,
zynqmp_pm_init_suspend_work_fn);
+
+ ret = zynqmp_pm_get_family_info(&pm_family_code, &pm_sub_family_code);
+ if (ret < 0)
+ return ret;
+
+ if (pm_sub_family_code == VERSALNET_SUB_FAMILY_CODE)
+ node_id = PM_DEV_ACPU_0_0;
+ else
+ node_id = PM_DEV_ACPU_0;
+
+ ret = register_event(&pdev->dev, PM_NOTIFY_CB, node_id, EVENT_SUBSYSTEM_RESTART,
+ false, subsystem_restart_event_callback);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n",
+ ret);
+ return ret;
+ }
+
+ zynqmp_pm_init_restart_work = devm_kzalloc(&pdev->dev,
+ sizeof(struct zynqmp_pm_work_struct),
+ GFP_KERNEL);
+ if (!zynqmp_pm_init_restart_work)
+ return -ENOMEM;
+
+ INIT_WORK(&zynqmp_pm_init_restart_work->callback_work,
+ zynqmp_pm_subsystem_restart_work_fn);
} else if (ret != -EACCES && ret != -ENODEV) {
dev_err(&pdev->dev, "Failed to Register with Xilinx Event manager %d\n", ret);
return ret;
@@ -264,15 +386,8 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
}
ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
- if (ret) {
- if (event_registered) {
- xlnx_unregister_event(PM_INIT_SUSPEND_CB, 0, 0, suspend_event_callback,
- NULL);
- event_registered = false;
- }
- dev_err(&pdev->dev, "unable to create sysfs interface\n");
+ if (ret)
return ret;
- }
return 0;
}
@@ -280,8 +395,6 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
static void zynqmp_pm_remove(struct platform_device *pdev)
{
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_suspend_mode.attr);
- if (event_registered)
- xlnx_unregister_event(PM_INIT_SUSPEND_CB, 0, 0, suspend_event_callback, NULL);
if (!rx_chan)
mbox_free_channel(rx_chan);
@@ -295,7 +408,7 @@ MODULE_DEVICE_TABLE(of, pm_of_match);
static struct platform_driver zynqmp_pm_platform_driver = {
.probe = zynqmp_pm_probe,
- .remove_new = zynqmp_pm_remove,
+ .remove = zynqmp_pm_remove,
.driver = {
.name = "zynqmp_power",
.of_match_table = pm_of_match,