Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'icc-mtk' into icc-next

This series is a combination of binding changes, driver cleanups and new
driver code to enable the interconnect on the MediaTek MT8196 SoC.

* icc-mtk
dt-bindings: interconnect: mt8183-emi: Add support for MT8196 EMI
interconnect: mediatek: Add support for MediaTek MT8196 EMI ICC
interconnect: mediatek: Don't hijack parent device
interconnect: mediatek: Aggregate bandwidth with saturating add

Link: https://lore.kernel.org/r/20251124-mt8196-dvfsrc-v2-0-d9c1334db9f3@collabora.com
Signed-off-by: Georgi Djakov <djakov@kernel.org>

+446 -3
+1
Documentation/devicetree/bindings/interconnect/mediatek,mt8183-emi.yaml
··· 40 40 enum: 41 41 - mediatek,mt8183-emi 42 42 - mediatek,mt8195-emi 43 + - mediatek,mt8196-emi 43 44 44 45 '#interconnect-cells': 45 46 const: 1
+7
drivers/interconnect/mediatek/Kconfig
··· 27 27 help 28 28 This is a driver for the MediaTek bus interconnect on MT8195-based 29 29 platforms. 30 + 31 + config INTERCONNECT_MTK_MT8196 32 + tristate "MediaTek MT8196 interconnect driver" 33 + depends on INTERCONNECT_MTK_DVFSRC_EMI 34 + help 35 + This is a driver for the MediaTek bus interconnect on MT8196-based 36 + platforms.
+1
drivers/interconnect/mediatek/Makefile
··· 3 3 obj-$(CONFIG_INTERCONNECT_MTK_DVFSRC_EMI) += icc-emi.o 4 4 obj-$(CONFIG_INTERCONNECT_MTK_MT8183) += mt8183.o 5 5 obj-$(CONFIG_INTERCONNECT_MTK_MT8195) += mt8195.o 6 + obj-$(CONFIG_INTERCONNECT_MTK_MT8195) += mt8196.o
+6 -3
drivers/interconnect/mediatek/icc-emi.c
··· 12 12 #include <linux/module.h> 13 13 #include <linux/of.h> 14 14 #include <linux/of_platform.h> 15 + #include <linux/overflow.h> 15 16 #include <linux/platform_device.h> 16 17 #include <linux/soc/mediatek/dvfsrc.h> 17 18 ··· 23 22 { 24 23 struct mtk_icc_node *in = node->data; 25 24 26 - *agg_avg += avg_bw; 25 + if (check_add_overflow(*agg_avg, avg_bw, agg_avg)) 26 + *agg_avg = U32_MAX; 27 + 27 28 *agg_peak = max_t(u32, *agg_peak, peak_bw); 28 29 29 30 in->sum_avg = *agg_avg; ··· 43 40 if (unlikely(!src->provider)) 44 41 return -EINVAL; 45 42 46 - dev = src->provider->dev; 43 + dev = src->provider->dev->parent; 47 44 48 45 switch (node->ep) { 49 46 case 0: ··· 100 97 if (!data) 101 98 return -ENOMEM; 102 99 103 - provider->dev = pdev->dev.parent; 100 + provider->dev = dev; 104 101 provider->set = mtk_emi_icc_set; 105 102 provider->aggregate = mtk_emi_icc_aggregate; 106 103 provider->xlate = of_icc_xlate_onecell;
+383
drivers/interconnect/mediatek/mt8196.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2025 Collabora Ltd. 4 + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 5 + */ 6 + 7 + #include <linux/device.h> 8 + #include <linux/interconnect.h> 9 + #include <linux/interconnect-provider.h> 10 + #include <linux/mod_devicetable.h> 11 + #include <linux/module.h> 12 + #include <linux/platform_device.h> 13 + #include <dt-bindings/interconnect/mediatek,mt8196.h> 14 + 15 + #include "icc-emi.h" 16 + 17 + static struct mtk_icc_node ddr_emi = { 18 + .name = "ddr-emi", 19 + .id = SLAVE_DDR_EMI, 20 + .ep = 1, 21 + }; 22 + 23 + static struct mtk_icc_node mcusys = { 24 + .name = "mcusys", 25 + .id = MASTER_MCUSYS, 26 + .ep = 0, 27 + .num_links = 1, 28 + .links = { SLAVE_DDR_EMI } 29 + }; 30 + 31 + static struct mtk_icc_node mcu_port0 = { 32 + .name = "mcu-port0", 33 + .id = MASTER_MCU_0, 34 + .ep = 0, 35 + .num_links = 1, 36 + .links = { SLAVE_DDR_EMI } 37 + }; 38 + 39 + static struct mtk_icc_node mcu_port1 = { 40 + .name = "mcu-port1", 41 + .id = MASTER_MCU_1, 42 + .ep = 0, 43 + .num_links = 1, 44 + .links = { SLAVE_DDR_EMI } 45 + }; 46 + 47 + static struct mtk_icc_node mcu_port2 = { 48 + .name = "mcu-port2", 49 + .id = MASTER_MCU_2, 50 + .ep = 0, 51 + .num_links = 1, 52 + .links = { SLAVE_DDR_EMI } 53 + }; 54 + 55 + static struct mtk_icc_node mcu_port3 = { 56 + .name = "mcu-port3", 57 + .id = MASTER_MCU_3, 58 + .ep = 0, 59 + .num_links = 1, 60 + .links = { SLAVE_DDR_EMI } 61 + }; 62 + 63 + static struct mtk_icc_node mcu_port4 = { 64 + .name = "mcu-port4", 65 + .id = MASTER_MCU_4, 66 + .ep = 0, 67 + .num_links = 1, 68 + .links = { SLAVE_DDR_EMI } 69 + }; 70 + 71 + static struct mtk_icc_node gpu = { 72 + .name = "gpu", 73 + .id = MASTER_GPUSYS, 74 + .ep = 0, 75 + .num_links = 1, 76 + .links = { SLAVE_DDR_EMI } 77 + }; 78 + 79 + static struct mtk_icc_node mmsys = { 80 + .name = "mmsys", 81 + .id = MASTER_MMSYS, 82 + .ep = 0, 83 + .num_links = 1, 84 + .links = { SLAVE_DDR_EMI } 85 + }; 86 + 87 + static struct mtk_icc_node mm_vpu = { 88 + .name = "mm-vpu", 89 + .id = MASTER_MM_VPU, 90 + .ep = 0, 91 + .num_links = 1, 92 + .links = { MASTER_MMSYS } 93 + }; 94 + 95 + static struct mtk_icc_node mm_disp = { 96 + .name = "mm-disp", 97 + .id = MASTER_MM_DISP, 98 + .ep = 0, 99 + .num_links = 1, 100 + .links = { MASTER_MMSYS } 101 + }; 102 + 103 + static struct mtk_icc_node mm_vdec = { 104 + .name = "mm-vdec", 105 + .id = MASTER_MM_VDEC, 106 + .ep = 0, 107 + .num_links = 1, 108 + .links = { MASTER_MMSYS } 109 + }; 110 + 111 + static struct mtk_icc_node mm_venc = { 112 + .name = "mm-venc", 113 + .id = MASTER_MM_VENC, 114 + .ep = 0, 115 + .num_links = 1, 116 + .links = { MASTER_MMSYS } 117 + }; 118 + 119 + static struct mtk_icc_node mm_cam = { 120 + .name = "mm-cam", 121 + .id = MASTER_MM_CAM, 122 + .ep = 0, 123 + .num_links = 1, 124 + .links = { MASTER_MMSYS } 125 + }; 126 + 127 + static struct mtk_icc_node mm_img = { 128 + .name = "mm-img", 129 + .id = MASTER_MM_IMG, 130 + .ep = 0, 131 + .num_links = 1, 132 + .links = { MASTER_MMSYS } 133 + }; 134 + 135 + static struct mtk_icc_node mm_mdp = { 136 + .name = "mm-mdp", 137 + .id = MASTER_MM_MDP, 138 + .ep = 0, 139 + .num_links = 1, 140 + .links = { MASTER_MMSYS } 141 + }; 142 + 143 + static struct mtk_icc_node vpusys = { 144 + .name = "vpusys", 145 + .id = MASTER_VPUSYS, 146 + .ep = 0, 147 + .num_links = 1, 148 + .links = { SLAVE_DDR_EMI } 149 + }; 150 + 151 + static struct mtk_icc_node vpu_port0 = { 152 + .name = "vpu-port0", 153 + .id = MASTER_VPU_0, 154 + .ep = 0, 155 + .num_links = 1, 156 + .links = { MASTER_VPUSYS } 157 + }; 158 + 159 + static struct mtk_icc_node vpu_port1 = { 160 + .name = "vpu-port1", 161 + .id = MASTER_VPU_1, 162 + .ep = 0, 163 + .num_links = 1, 164 + .links = { MASTER_VPUSYS } 165 + }; 166 + 167 + static struct mtk_icc_node mdlasys = { 168 + .name = "mdlasys", 169 + .id = MASTER_MDLASYS, 170 + .ep = 0, 171 + .num_links = 1, 172 + .links = { SLAVE_DDR_EMI } 173 + }; 174 + 175 + static struct mtk_icc_node mdla_port0 = { 176 + .name = "mdla-port0", 177 + .id = MASTER_MDLA_0, 178 + .ep = 0, 179 + .num_links = 1, 180 + .links = { MASTER_MDLASYS } 181 + }; 182 + 183 + static struct mtk_icc_node ufs = { 184 + .name = "ufs", 185 + .id = MASTER_UFS, 186 + .ep = 0, 187 + .num_links = 1, 188 + .links = { SLAVE_DDR_EMI } 189 + }; 190 + 191 + static struct mtk_icc_node pcie = { 192 + .name = "pcie", 193 + .id = MASTER_PCIE, 194 + .ep = 0, 195 + .num_links = 1, 196 + .links = { SLAVE_DDR_EMI } 197 + }; 198 + 199 + static struct mtk_icc_node usb = { 200 + .name = "usb", 201 + .id = MASTER_USB, 202 + .ep = 0, 203 + .num_links = 1, 204 + .links = { SLAVE_DDR_EMI } 205 + }; 206 + 207 + static struct mtk_icc_node wifi = { 208 + .name = "wifi", 209 + .id = MASTER_WIFI, 210 + .ep = 0, 211 + .num_links = 1, 212 + .links = { SLAVE_DDR_EMI } 213 + }; 214 + 215 + static struct mtk_icc_node bt = { 216 + .name = "bt", 217 + .id = MASTER_BT, 218 + .ep = 0, 219 + .num_links = 1, 220 + .links = { SLAVE_DDR_EMI } 221 + }; 222 + 223 + static struct mtk_icc_node netsys = { 224 + .name = "netsys", 225 + .id = MASTER_NETSYS, 226 + .ep = 0, 227 + .num_links = 1, 228 + .links = { SLAVE_DDR_EMI } 229 + }; 230 + 231 + static struct mtk_icc_node dbgif = { 232 + .name = "dbgif", 233 + .id = MASTER_DBGIF, 234 + .ep = 0, 235 + .num_links = 1, 236 + .links = { SLAVE_DDR_EMI } 237 + }; 238 + 239 + static struct mtk_icc_node hrt_ddr_emi = { 240 + .name = "hrt-ddr-emi", 241 + .id = SLAVE_HRT_DDR_EMI, 242 + .ep = 2, 243 + }; 244 + 245 + static struct mtk_icc_node hrt_mmsys = { 246 + .name = "hrt-mmsys", 247 + .id = MASTER_HRT_MMSYS, 248 + .ep = 0, 249 + .num_links = 1, 250 + .links = { SLAVE_HRT_DDR_EMI } 251 + }; 252 + 253 + static struct mtk_icc_node hrt_mm_disp = { 254 + .name = "hrt-mm-disp", 255 + .id = MASTER_HRT_MM_DISP, 256 + .ep = 0, 257 + .num_links = 1, 258 + .links = { MASTER_HRT_MMSYS } 259 + }; 260 + 261 + static struct mtk_icc_node hrt_mm_vdec = { 262 + .name = "hrt-mm-vdec", 263 + .id = MASTER_HRT_MM_VDEC, 264 + .ep = 0, 265 + .num_links = 1, 266 + .links = { MASTER_HRT_MMSYS } 267 + }; 268 + 269 + static struct mtk_icc_node hrt_mm_venc = { 270 + .name = "hrt-mm-venc", 271 + .id = MASTER_HRT_MM_VENC, 272 + .ep = 0, 273 + .num_links = 1, 274 + .links = { MASTER_HRT_MMSYS } 275 + }; 276 + 277 + static struct mtk_icc_node hrt_mm_cam = { 278 + .name = "hrt-mm-cam", 279 + .id = MASTER_HRT_MM_CAM, 280 + .ep = 0, 281 + .num_links = 1, 282 + .links = { MASTER_HRT_MMSYS } 283 + }; 284 + 285 + static struct mtk_icc_node hrt_mm_img = { 286 + .name = "hrt-mm-img", 287 + .id = MASTER_HRT_MM_IMG, 288 + .ep = 0, 289 + .num_links = 1, 290 + .links = { MASTER_HRT_MMSYS } 291 + }; 292 + 293 + static struct mtk_icc_node hrt_mm_mdp = { 294 + .name = "hrt-mm-mdp", 295 + .id = MASTER_HRT_MM_MDP, 296 + .ep = 0, 297 + .num_links = 1, 298 + .links = { MASTER_HRT_MMSYS } 299 + }; 300 + 301 + static struct mtk_icc_node hrt_adsp = { 302 + .name = "hrt-adsp", 303 + .id = MASTER_HRT_ADSP, 304 + .ep = 0, 305 + .num_links = 1, 306 + .links = { SLAVE_HRT_DDR_EMI } 307 + }; 308 + 309 + static struct mtk_icc_node hrt_dbgif = { 310 + .name = "hrt-dbgif", 311 + .id = MASTER_HRT_DBGIF, 312 + .ep = 0, 313 + .num_links = 1, 314 + .links = { SLAVE_HRT_DDR_EMI } 315 + }; 316 + 317 + static struct mtk_icc_node *mt8196_emi_icc_nodes[] = { 318 + [SLAVE_DDR_EMI] = &ddr_emi, 319 + [MASTER_MCUSYS] = &mcusys, 320 + [MASTER_MCU_0] = &mcu_port0, 321 + [MASTER_MCU_1] = &mcu_port1, 322 + [MASTER_MCU_2] = &mcu_port2, 323 + [MASTER_MCU_3] = &mcu_port3, 324 + [MASTER_MCU_4] = &mcu_port4, 325 + [MASTER_GPUSYS] = &gpu, 326 + [MASTER_MMSYS] = &mmsys, 327 + [MASTER_MM_VPU] = &mm_vpu, 328 + [MASTER_MM_DISP] = &mm_disp, 329 + [MASTER_MM_VDEC] = &mm_vdec, 330 + [MASTER_MM_VENC] = &mm_venc, 331 + [MASTER_MM_CAM] = &mm_cam, 332 + [MASTER_MM_IMG] = &mm_img, 333 + [MASTER_MM_MDP] = &mm_mdp, 334 + [MASTER_VPUSYS] = &vpusys, 335 + [MASTER_VPU_0] = &vpu_port0, 336 + [MASTER_VPU_1] = &vpu_port1, 337 + [MASTER_MDLASYS] = &mdlasys, 338 + [MASTER_MDLA_0] = &mdla_port0, 339 + [MASTER_UFS] = &ufs, 340 + [MASTER_PCIE] = &pcie, 341 + [MASTER_USB] = &usb, 342 + [MASTER_WIFI] = &wifi, 343 + [MASTER_BT] = &bt, 344 + [MASTER_NETSYS] = &netsys, 345 + [MASTER_DBGIF] = &dbgif, 346 + [SLAVE_HRT_DDR_EMI] = &hrt_ddr_emi, 347 + [MASTER_HRT_MMSYS] = &hrt_mmsys, 348 + [MASTER_HRT_MM_DISP] = &hrt_mm_disp, 349 + [MASTER_HRT_MM_VDEC] = &hrt_mm_vdec, 350 + [MASTER_HRT_MM_VENC] = &hrt_mm_venc, 351 + [MASTER_HRT_MM_CAM] = &hrt_mm_cam, 352 + [MASTER_HRT_MM_IMG] = &hrt_mm_img, 353 + [MASTER_HRT_MM_MDP] = &hrt_mm_mdp, 354 + [MASTER_HRT_ADSP] = &hrt_adsp, 355 + [MASTER_HRT_DBGIF] = &hrt_dbgif 356 + }; 357 + 358 + static struct mtk_icc_desc mt8196_emi_icc = { 359 + .nodes = mt8196_emi_icc_nodes, 360 + .num_nodes = ARRAY_SIZE(mt8196_emi_icc_nodes), 361 + }; 362 + 363 + static const struct of_device_id mtk_mt8196_emi_icc_of_match[] = { 364 + { .compatible = "mediatek,mt8196-emi", .data = &mt8196_emi_icc }, 365 + { /* sentinel */ }, 366 + }; 367 + MODULE_DEVICE_TABLE(of, mtk_mt8196_emi_icc_of_match); 368 + 369 + static struct platform_driver mtk_emi_icc_mt8196_driver = { 370 + .driver = { 371 + .name = "emi-icc-mt8196", 372 + .of_match_table = mtk_mt8196_emi_icc_of_match, 373 + .sync_state = icc_sync_state, 374 + }, 375 + .probe = mtk_emi_icc_probe, 376 + .remove = mtk_emi_icc_remove, 377 + 378 + }; 379 + module_platform_driver(mtk_emi_icc_mt8196_driver); 380 + 381 + MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>"); 382 + MODULE_DESCRIPTION("MediaTek MT8196 EMI ICC driver"); 383 + MODULE_LICENSE("GPL");
+48
include/dt-bindings/interconnect/mediatek,mt8196.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Copyright (c) 2025 Collabora Ltd. 4 + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> 5 + */ 6 + 7 + #ifndef __DT_BINDINGS_INTERCONNECT_MEDIATEK_MT8196_H 8 + #define __DT_BINDINGS_INTERCONNECT_MEDIATEK_MT8196_H 9 + 10 + #define SLAVE_DDR_EMI 0 11 + #define MASTER_MCUSYS 1 12 + #define MASTER_MCU_0 2 13 + #define MASTER_MCU_1 3 14 + #define MASTER_MCU_2 4 15 + #define MASTER_MCU_3 5 16 + #define MASTER_MCU_4 6 17 + #define MASTER_GPUSYS 7 18 + #define MASTER_MMSYS 8 19 + #define MASTER_MM_VPU 9 20 + #define MASTER_MM_DISP 10 21 + #define MASTER_MM_VDEC 11 22 + #define MASTER_MM_VENC 12 23 + #define MASTER_MM_CAM 13 24 + #define MASTER_MM_IMG 14 25 + #define MASTER_MM_MDP 15 26 + #define MASTER_VPUSYS 16 27 + #define MASTER_VPU_0 17 28 + #define MASTER_VPU_1 18 29 + #define MASTER_MDLASYS 19 30 + #define MASTER_MDLA_0 20 31 + #define MASTER_UFS 21 32 + #define MASTER_PCIE 22 33 + #define MASTER_USB 23 34 + #define MASTER_WIFI 24 35 + #define MASTER_BT 25 36 + #define MASTER_NETSYS 26 37 + #define MASTER_DBGIF 27 38 + #define SLAVE_HRT_DDR_EMI 28 39 + #define MASTER_HRT_MMSYS 29 40 + #define MASTER_HRT_MM_DISP 30 41 + #define MASTER_HRT_MM_VDEC 31 42 + #define MASTER_HRT_MM_VENC 32 43 + #define MASTER_HRT_MM_CAM 33 44 + #define MASTER_HRT_MM_IMG 34 45 + #define MASTER_HRT_MM_MDP 35 46 + #define MASTER_HRT_ADSP 36 47 + #define MASTER_HRT_DBGIF 37 48 + #endif