1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved. 4 * Copyright (c) 2025, Luca Weiss <luca.weiss@fairphone.com> 5 */ 6 7 #include <linux/clk-provider.h> 8 #include <linux/mod_devicetable.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/regmap.h> 12 13 #include <dt-bindings/clock/qcom,milos-gpucc.h> 14 15 #include "clk-alpha-pll.h" 16 #include "clk-branch.h" 17 #include "clk-pll.h" 18 #include "clk-rcg.h" 19 #include "clk-regmap.h" 20 #include "clk-regmap-divider.h" 21 #include "clk-regmap-mux.h" 22 #include "common.h" 23 #include "gdsc.h" 24 #include "reset.h" 25 26 /* Need to match the order of clocks in DT binding */ 27 enum { 28 DT_BI_TCXO, 29 DT_GPLL0_OUT_MAIN, 30 DT_GPLL0_OUT_MAIN_DIV, 31 }; 32 33 enum { 34 P_BI_TCXO, 35 P_GPLL0_OUT_MAIN, 36 P_GPLL0_OUT_MAIN_DIV, 37 P_GPU_CC_PLL0_OUT_EVEN, 38 P_GPU_CC_PLL0_OUT_MAIN, 39 P_GPU_CC_PLL0_OUT_ODD, 40 }; 41 42 static const struct pll_vco lucid_ole_vco[] = { 43 { 249600000, 2300000000, 0 }, 44 }; 45 46 /* 700.0 MHz Configuration */ 47 static const struct alpha_pll_config gpu_cc_pll0_config = { 48 .l = 0x24, 49 .alpha = 0x7555, 50 .config_ctl_val = 0x20485699, 51 .config_ctl_hi_val = 0x00182261, 52 .config_ctl_hi1_val = 0x82aa299c, 53 .test_ctl_val = 0x00000000, 54 .test_ctl_hi_val = 0x00000003, 55 .test_ctl_hi1_val = 0x00009000, 56 .test_ctl_hi2_val = 0x00000034, 57 .user_ctl_val = 0x00000400, 58 .user_ctl_hi_val = 0x00000005, 59 }; 60 61 static struct clk_alpha_pll gpu_cc_pll0 = { 62 .offset = 0x0, 63 .config = &gpu_cc_pll0_config, 64 .vco_table = lucid_ole_vco, 65 .num_vco = ARRAY_SIZE(lucid_ole_vco), 66 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], 67 .clkr = { 68 .hw.init = &(const struct clk_init_data) { 69 .name = "gpu_cc_pll0", 70 .parent_data = &(const struct clk_parent_data) { 71 .index = DT_BI_TCXO, 72 }, 73 .num_parents = 1, 74 .ops = &clk_alpha_pll_lucid_evo_ops, 75 }, 76 }, 77 }; 78 79 static const struct clk_div_table post_div_table_gpu_cc_pll0_out_even[] = { 80 { 0x1, 2 }, 81 { } 82 }; 83 84 static struct clk_alpha_pll_postdiv gpu_cc_pll0_out_even = { 85 .offset = 0x0, 86 .post_div_shift = 10, 87 .post_div_table = post_div_table_gpu_cc_pll0_out_even, 88 .num_post_div = ARRAY_SIZE(post_div_table_gpu_cc_pll0_out_even), 89 .width = 4, 90 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE], 91 .clkr.hw.init = &(const struct clk_init_data) { 92 .name = "gpu_cc_pll0_out_even", 93 .parent_hws = (const struct clk_hw*[]) { 94 &gpu_cc_pll0.clkr.hw, 95 }, 96 .num_parents = 1, 97 .flags = CLK_SET_RATE_PARENT, 98 .ops = &clk_alpha_pll_postdiv_lucid_ole_ops, 99 }, 100 }; 101 102 static const struct parent_map gpu_cc_parent_map_0[] = { 103 { P_BI_TCXO, 0 }, 104 { P_GPLL0_OUT_MAIN, 5 }, 105 { P_GPLL0_OUT_MAIN_DIV, 6 }, 106 }; 107 108 static const struct clk_parent_data gpu_cc_parent_data_0[] = { 109 { .index = DT_BI_TCXO }, 110 { .index = DT_GPLL0_OUT_MAIN }, 111 { .index = DT_GPLL0_OUT_MAIN_DIV }, 112 }; 113 114 static const struct parent_map gpu_cc_parent_map_1[] = { 115 { P_BI_TCXO, 0 }, 116 { P_GPU_CC_PLL0_OUT_MAIN, 1 }, 117 { P_GPU_CC_PLL0_OUT_EVEN, 2 }, 118 { P_GPU_CC_PLL0_OUT_ODD, 3 }, 119 { P_GPLL0_OUT_MAIN, 5 }, 120 { P_GPLL0_OUT_MAIN_DIV, 6 }, 121 }; 122 123 static const struct clk_parent_data gpu_cc_parent_data_1[] = { 124 { .index = DT_BI_TCXO }, 125 { .hw = &gpu_cc_pll0.clkr.hw }, 126 { .hw = &gpu_cc_pll0_out_even.clkr.hw }, 127 { .hw = &gpu_cc_pll0.clkr.hw }, 128 { .index = DT_GPLL0_OUT_MAIN }, 129 { .index = DT_GPLL0_OUT_MAIN_DIV }, 130 }; 131 132 static const struct freq_tbl ftbl_gpu_cc_ff_clk_src[] = { 133 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), 134 { } 135 }; 136 137 static struct clk_rcg2 gpu_cc_ff_clk_src = { 138 .cmd_rcgr = 0x9474, 139 .mnd_width = 0, 140 .hid_width = 5, 141 .parent_map = gpu_cc_parent_map_0, 142 .freq_tbl = ftbl_gpu_cc_ff_clk_src, 143 .clkr.hw.init = &(const struct clk_init_data) { 144 .name = "gpu_cc_ff_clk_src", 145 .parent_data = gpu_cc_parent_data_0, 146 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), 147 .flags = CLK_SET_RATE_PARENT, 148 .ops = &clk_rcg2_shared_ops, 149 }, 150 }; 151 152 static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { 153 F(19200000, P_BI_TCXO, 1, 0, 0), 154 F(350000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), 155 F(650000000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), 156 F(687500000, P_GPU_CC_PLL0_OUT_EVEN, 1, 0, 0), 157 { } 158 }; 159 160 static struct clk_rcg2 gpu_cc_gmu_clk_src = { 161 .cmd_rcgr = 0x9318, 162 .mnd_width = 0, 163 .hid_width = 5, 164 .parent_map = gpu_cc_parent_map_1, 165 .freq_tbl = ftbl_gpu_cc_gmu_clk_src, 166 .clkr.hw.init = &(const struct clk_init_data) { 167 .name = "gpu_cc_gmu_clk_src", 168 .parent_data = gpu_cc_parent_data_1, 169 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 170 .flags = CLK_SET_RATE_PARENT, 171 .ops = &clk_rcg2_shared_ops, 172 }, 173 }; 174 175 static const struct freq_tbl ftbl_gpu_cc_hub_clk_src[] = { 176 F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), 177 F(300000000, P_GPLL0_OUT_MAIN, 2, 0, 0), 178 F(400000000, P_GPLL0_OUT_MAIN, 1.5, 0, 0), 179 { } 180 }; 181 182 static struct clk_rcg2 gpu_cc_hub_clk_src = { 183 .cmd_rcgr = 0x93ec, 184 .mnd_width = 0, 185 .hid_width = 5, 186 .parent_map = gpu_cc_parent_map_1, 187 .freq_tbl = ftbl_gpu_cc_hub_clk_src, 188 .clkr.hw.init = &(const struct clk_init_data) { 189 .name = "gpu_cc_hub_clk_src", 190 .parent_data = gpu_cc_parent_data_1, 191 .num_parents = ARRAY_SIZE(gpu_cc_parent_data_1), 192 .flags = CLK_SET_RATE_PARENT, 193 .ops = &clk_rcg2_shared_ops, 194 }, 195 }; 196 197 static struct clk_regmap_div gpu_cc_hub_div_clk_src = { 198 .reg = 0x942c, 199 .shift = 0, 200 .width = 4, 201 .clkr.hw.init = &(const struct clk_init_data) { 202 .name = "gpu_cc_hub_div_clk_src", 203 .parent_hws = (const struct clk_hw*[]) { 204 &gpu_cc_hub_clk_src.clkr.hw, 205 }, 206 .num_parents = 1, 207 .flags = CLK_SET_RATE_PARENT, 208 .ops = &clk_regmap_div_ro_ops, 209 }, 210 }; 211 212 static struct clk_branch gpu_cc_ahb_clk = { 213 .halt_reg = 0x90bc, 214 .halt_check = BRANCH_HALT_DELAY, 215 .clkr = { 216 .enable_reg = 0x90bc, 217 .enable_mask = BIT(0), 218 .hw.init = &(const struct clk_init_data) { 219 .name = "gpu_cc_ahb_clk", 220 .parent_hws = (const struct clk_hw*[]) { 221 &gpu_cc_hub_div_clk_src.clkr.hw, 222 }, 223 .num_parents = 1, 224 .flags = CLK_SET_RATE_PARENT, 225 .ops = &clk_branch2_ops, 226 }, 227 }, 228 }; 229 230 static struct clk_branch gpu_cc_cx_accu_shift_clk = { 231 .halt_reg = 0x910c, 232 .halt_check = BRANCH_HALT_VOTED, 233 .clkr = { 234 .enable_reg = 0x910c, 235 .enable_mask = BIT(0), 236 .hw.init = &(const struct clk_init_data) { 237 .name = "gpu_cc_cx_accu_shift_clk", 238 .ops = &clk_branch2_ops, 239 }, 240 }, 241 }; 242 243 static struct clk_branch gpu_cc_cx_ff_clk = { 244 .halt_reg = 0x90ec, 245 .halt_check = BRANCH_HALT, 246 .clkr = { 247 .enable_reg = 0x90ec, 248 .enable_mask = BIT(0), 249 .hw.init = &(const struct clk_init_data) { 250 .name = "gpu_cc_cx_ff_clk", 251 .parent_hws = (const struct clk_hw*[]) { 252 &gpu_cc_ff_clk_src.clkr.hw, 253 }, 254 .num_parents = 1, 255 .flags = CLK_SET_RATE_PARENT, 256 .ops = &clk_branch2_ops, 257 }, 258 }, 259 }; 260 261 static struct clk_branch gpu_cc_cx_gmu_clk = { 262 .halt_reg = 0x90d4, 263 .halt_check = BRANCH_HALT_VOTED, 264 .clkr = { 265 .enable_reg = 0x90d4, 266 .enable_mask = BIT(0), 267 .hw.init = &(const struct clk_init_data) { 268 .name = "gpu_cc_cx_gmu_clk", 269 .parent_hws = (const struct clk_hw*[]) { 270 &gpu_cc_gmu_clk_src.clkr.hw, 271 }, 272 .num_parents = 1, 273 .flags = CLK_SET_RATE_PARENT, 274 .ops = &clk_branch2_aon_ops, 275 }, 276 }, 277 }; 278 279 static struct clk_branch gpu_cc_cxo_clk = { 280 .halt_reg = 0x90e4, 281 .halt_check = BRANCH_HALT, 282 .clkr = { 283 .enable_reg = 0x90e4, 284 .enable_mask = BIT(0), 285 .hw.init = &(const struct clk_init_data) { 286 .name = "gpu_cc_cxo_clk", 287 .ops = &clk_branch2_ops, 288 }, 289 }, 290 }; 291 292 static struct clk_branch gpu_cc_dpm_clk = { 293 .halt_reg = 0x9110, 294 .halt_check = BRANCH_HALT, 295 .clkr = { 296 .enable_reg = 0x9110, 297 .enable_mask = BIT(0), 298 .hw.init = &(const struct clk_init_data) { 299 .name = "gpu_cc_dpm_clk", 300 .ops = &clk_branch2_ops, 301 }, 302 }, 303 }; 304 305 static struct clk_branch gpu_cc_freq_measure_clk = { 306 .halt_reg = 0x900c, 307 .halt_check = BRANCH_HALT, 308 .clkr = { 309 .enable_reg = 0x900c, 310 .enable_mask = BIT(0), 311 .hw.init = &(const struct clk_init_data) { 312 .name = "gpu_cc_freq_measure_clk", 313 .ops = &clk_branch2_ops, 314 }, 315 }, 316 }; 317 318 static struct clk_branch gpu_cc_gx_accu_shift_clk = { 319 .halt_reg = 0x9070, 320 .halt_check = BRANCH_HALT_VOTED, 321 .clkr = { 322 .enable_reg = 0x9070, 323 .enable_mask = BIT(0), 324 .hw.init = &(const struct clk_init_data) { 325 .name = "gpu_cc_gx_accu_shift_clk", 326 .ops = &clk_branch2_ops, 327 }, 328 }, 329 }; 330 331 static struct clk_branch gpu_cc_gx_acd_ahb_ff_clk = { 332 .halt_reg = 0x9068, 333 .halt_check = BRANCH_HALT, 334 .clkr = { 335 .enable_reg = 0x9068, 336 .enable_mask = BIT(0), 337 .hw.init = &(const struct clk_init_data) { 338 .name = "gpu_cc_gx_acd_ahb_ff_clk", 339 .parent_hws = (const struct clk_hw*[]) { 340 &gpu_cc_ff_clk_src.clkr.hw, 341 }, 342 .num_parents = 1, 343 .flags = CLK_SET_RATE_PARENT, 344 .ops = &clk_branch2_ops, 345 }, 346 }, 347 }; 348 349 static struct clk_branch gpu_cc_gx_gmu_clk = { 350 .halt_reg = 0x9060, 351 .halt_check = BRANCH_HALT, 352 .clkr = { 353 .enable_reg = 0x9060, 354 .enable_mask = BIT(0), 355 .hw.init = &(const struct clk_init_data) { 356 .name = "gpu_cc_gx_gmu_clk", 357 .parent_hws = (const struct clk_hw*[]) { 358 &gpu_cc_gmu_clk_src.clkr.hw, 359 }, 360 .num_parents = 1, 361 .flags = CLK_SET_RATE_PARENT, 362 .ops = &clk_branch2_ops, 363 }, 364 }, 365 }; 366 367 static struct clk_branch gpu_cc_gx_rcg_ahb_ff_clk = { 368 .halt_reg = 0x906c, 369 .halt_check = BRANCH_HALT_VOTED, 370 .clkr = { 371 .enable_reg = 0x906c, 372 .enable_mask = BIT(0), 373 .hw.init = &(const struct clk_init_data) { 374 .name = "gpu_cc_gx_rcg_ahb_ff_clk", 375 .parent_hws = (const struct clk_hw*[]) { 376 &gpu_cc_ff_clk_src.clkr.hw, 377 }, 378 .num_parents = 1, 379 .flags = CLK_SET_RATE_PARENT, 380 .ops = &clk_branch2_ops, 381 }, 382 }, 383 }; 384 385 static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { 386 .halt_reg = 0x7000, 387 .halt_check = BRANCH_HALT_VOTED, 388 .clkr = { 389 .enable_reg = 0x7000, 390 .enable_mask = BIT(0), 391 .hw.init = &(const struct clk_init_data) { 392 .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", 393 .ops = &clk_branch2_ops, 394 }, 395 }, 396 }; 397 398 static struct clk_branch gpu_cc_hub_aon_clk = { 399 .halt_reg = 0x93e8, 400 .halt_check = BRANCH_HALT_VOTED, 401 .clkr = { 402 .enable_reg = 0x93e8, 403 .enable_mask = BIT(0), 404 .hw.init = &(const struct clk_init_data) { 405 .name = "gpu_cc_hub_aon_clk", 406 .parent_hws = (const struct clk_hw*[]) { 407 &gpu_cc_hub_clk_src.clkr.hw, 408 }, 409 .num_parents = 1, 410 .flags = CLK_SET_RATE_PARENT, 411 .ops = &clk_branch2_aon_ops, 412 }, 413 }, 414 }; 415 416 static struct clk_branch gpu_cc_hub_cx_int_clk = { 417 .halt_reg = 0x90e8, 418 .halt_check = BRANCH_HALT_VOTED, 419 .clkr = { 420 .enable_reg = 0x90e8, 421 .enable_mask = BIT(0), 422 .hw.init = &(const struct clk_init_data) { 423 .name = "gpu_cc_hub_cx_int_clk", 424 .parent_hws = (const struct clk_hw*[]) { 425 &gpu_cc_hub_clk_src.clkr.hw, 426 }, 427 .num_parents = 1, 428 .flags = CLK_SET_RATE_PARENT, 429 .ops = &clk_branch2_aon_ops, 430 }, 431 }, 432 }; 433 434 static struct clk_branch gpu_cc_memnoc_gfx_clk = { 435 .halt_reg = 0x90f4, 436 .halt_check = BRANCH_HALT_VOTED, 437 .clkr = { 438 .enable_reg = 0x90f4, 439 .enable_mask = BIT(0), 440 .hw.init = &(const struct clk_init_data) { 441 .name = "gpu_cc_memnoc_gfx_clk", 442 .ops = &clk_branch2_ops, 443 }, 444 }, 445 }; 446 447 static struct gdsc gpu_cc_cx_gdsc = { 448 .gdscr = 0x9080, 449 .gds_hw_ctrl = 0x9094, 450 .en_rest_wait_val = 0x2, 451 .en_few_wait_val = 0x2, 452 .clk_dis_wait_val = 0x8, 453 .pd = { 454 .name = "gpu_cc_cx_gdsc", 455 }, 456 .pwrsts = PWRSTS_OFF_ON, 457 .flags = RETAIN_FF_ENABLE | VOTABLE, 458 }; 459 460 static struct clk_regmap *gpu_cc_milos_clocks[] = { 461 [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, 462 [GPU_CC_CX_ACCU_SHIFT_CLK] = &gpu_cc_cx_accu_shift_clk.clkr, 463 [GPU_CC_CX_FF_CLK] = &gpu_cc_cx_ff_clk.clkr, 464 [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, 465 [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, 466 [GPU_CC_DPM_CLK] = &gpu_cc_dpm_clk.clkr, 467 [GPU_CC_FF_CLK_SRC] = &gpu_cc_ff_clk_src.clkr, 468 [GPU_CC_FREQ_MEASURE_CLK] = &gpu_cc_freq_measure_clk.clkr, 469 [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, 470 [GPU_CC_GX_ACCU_SHIFT_CLK] = &gpu_cc_gx_accu_shift_clk.clkr, 471 [GPU_CC_GX_ACD_AHB_FF_CLK] = &gpu_cc_gx_acd_ahb_ff_clk.clkr, 472 [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, 473 [GPU_CC_GX_RCG_AHB_FF_CLK] = &gpu_cc_gx_rcg_ahb_ff_clk.clkr, 474 [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, 475 [GPU_CC_HUB_AON_CLK] = &gpu_cc_hub_aon_clk.clkr, 476 [GPU_CC_HUB_CLK_SRC] = &gpu_cc_hub_clk_src.clkr, 477 [GPU_CC_HUB_CX_INT_CLK] = &gpu_cc_hub_cx_int_clk.clkr, 478 [GPU_CC_HUB_DIV_CLK_SRC] = &gpu_cc_hub_div_clk_src.clkr, 479 [GPU_CC_MEMNOC_GFX_CLK] = &gpu_cc_memnoc_gfx_clk.clkr, 480 [GPU_CC_PLL0] = &gpu_cc_pll0.clkr, 481 [GPU_CC_PLL0_OUT_EVEN] = &gpu_cc_pll0_out_even.clkr, 482 }; 483 484 static struct gdsc *gpu_cc_milos_gdscs[] = { 485 [GPU_CC_CX_GDSC] = &gpu_cc_cx_gdsc, 486 }; 487 488 static const struct qcom_reset_map gpu_cc_milos_resets[] = { 489 [GPU_CC_CB_BCR] = { 0x93a0 }, 490 [GPU_CC_CX_BCR] = { 0x907c }, 491 [GPU_CC_FAST_HUB_BCR] = { 0x93e4 }, 492 [GPU_CC_FF_BCR] = { 0x9470 }, 493 [GPU_CC_GMU_BCR] = { 0x9314 }, 494 [GPU_CC_GX_BCR] = { 0x905c }, 495 [GPU_CC_RBCPR_BCR] = { 0x91e0 }, 496 [GPU_CC_XO_BCR] = { 0x9000 }, 497 }; 498 499 static struct clk_alpha_pll *gpu_cc_milos_plls[] = { 500 &gpu_cc_pll0, 501 }; 502 503 static u32 gpu_cc_milos_critical_cbcrs[] = { 504 0x93a4, /* GPU_CC_CB_CLK */ 505 0x9008, /* GPU_CC_CXO_AON_CLK */ 506 0x9010, /* GPU_CC_DEMET_CLK */ 507 0x9064, /* GPU_CC_GX_AHB_FF_CLK */ 508 0x93a8, /* GPU_CC_RSCC_HUB_AON_CLK */ 509 0x9004, /* GPU_CC_RSCC_XO_AON_CLK */ 510 0x90cc, /* GPU_CC_SLEEP_CLK */ 511 }; 512 513 static const struct regmap_config gpu_cc_milos_regmap_config = { 514 .reg_bits = 32, 515 .reg_stride = 4, 516 .val_bits = 32, 517 .max_register = 0x95e8, 518 .fast_io = true, 519 }; 520 521 static struct qcom_cc_driver_data gpu_cc_milos_driver_data = { 522 .alpha_plls = gpu_cc_milos_plls, 523 .num_alpha_plls = ARRAY_SIZE(gpu_cc_milos_plls), 524 .clk_cbcrs = gpu_cc_milos_critical_cbcrs, 525 .num_clk_cbcrs = ARRAY_SIZE(gpu_cc_milos_critical_cbcrs), 526 }; 527 528 static const struct qcom_cc_desc gpu_cc_milos_desc = { 529 .config = &gpu_cc_milos_regmap_config, 530 .clks = gpu_cc_milos_clocks, 531 .num_clks = ARRAY_SIZE(gpu_cc_milos_clocks), 532 .resets = gpu_cc_milos_resets, 533 .num_resets = ARRAY_SIZE(gpu_cc_milos_resets), 534 .gdscs = gpu_cc_milos_gdscs, 535 .num_gdscs = ARRAY_SIZE(gpu_cc_milos_gdscs), 536 .use_rpm = true, 537 .driver_data = &gpu_cc_milos_driver_data, 538 }; 539 540 static const struct of_device_id gpu_cc_milos_match_table[] = { 541 { .compatible = "qcom,milos-gpucc" }, 542 { } 543 }; 544 MODULE_DEVICE_TABLE(of, gpu_cc_milos_match_table); 545 546 static int gpu_cc_milos_probe(struct platform_device *pdev) 547 { 548 return qcom_cc_probe(pdev, &gpu_cc_milos_desc); 549 } 550 551 static struct platform_driver gpu_cc_milos_driver = { 552 .probe = gpu_cc_milos_probe, 553 .driver = { 554 .name = "gpu_cc-milos", 555 .of_match_table = gpu_cc_milos_match_table, 556 }, 557 }; 558 559 module_platform_driver(gpu_cc_milos_driver); 560 561 MODULE_DESCRIPTION("QTI GPU_CC Milos Driver"); 562 MODULE_LICENSE("GPL"); 563