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

clk: imx: Fix reparenting of UARTs not associated with stdout

Most if not all i.MX SoC's call a function which enables all UARTS.
This is a problem for users who need to re-parent the clock source,
because any attempt to change the parent results in an busy error
due to the fact that the clocks have been enabled already.

clk: failed to reparent uart1 to sys_pll1_80m: -16

Instead of pre-initializing all UARTS, scan the device tree to see
which UART clocks are associated to stdout, and only enable those
UART clocks if it's needed early. This will move initialization of
the remaining clocks until after the parenting of the clocks.

When the clocks are shutdown, this mechanism will also disable any
clocks that were pre-initialized.

Fixes: 9461f7b33d11c ("clk: fix CLK_SET_RATE_GATE with clock rate protection")
Suggested-by: Aisheng Dong <aisheng.dong@nxp.com>
Signed-off-by: Adam Ford <aford173@gmail.com>
Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
Tested-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
Signed-off-by: Abel Vesa <abel.vesa@nxp.com>

authored by

Adam Ford and committed by
Abel Vesa
379c9a24 a38fd874

+54 -252
+1 -11
drivers/clk/imx/clk-imx25.c
··· 73 73 74 74 static struct clk *clk[clk_max]; 75 75 76 - static struct clk ** const uart_clks[] __initconst = { 77 - &clk[uart_ipg_per], 78 - &clk[uart1_ipg], 79 - &clk[uart2_ipg], 80 - &clk[uart3_ipg], 81 - &clk[uart4_ipg], 82 - &clk[uart5_ipg], 83 - NULL 84 - }; 85 - 86 76 static int __init __mx25_clocks_init(void __iomem *ccm_base) 87 77 { 88 78 BUG_ON(!ccm_base); ··· 218 228 */ 219 229 clk_set_parent(clk[cko_sel], clk[ipg]); 220 230 221 - imx_register_uart_clocks(uart_clks); 231 + imx_register_uart_clocks(6); 222 232 223 233 return 0; 224 234 }
+1 -12
drivers/clk/imx/clk-imx27.c
··· 49 49 static struct clk *clk[IMX27_CLK_MAX]; 50 50 static struct clk_onecell_data clk_data; 51 51 52 - static struct clk ** const uart_clks[] __initconst = { 53 - &clk[IMX27_CLK_PER1_GATE], 54 - &clk[IMX27_CLK_UART1_IPG_GATE], 55 - &clk[IMX27_CLK_UART2_IPG_GATE], 56 - &clk[IMX27_CLK_UART3_IPG_GATE], 57 - &clk[IMX27_CLK_UART4_IPG_GATE], 58 - &clk[IMX27_CLK_UART5_IPG_GATE], 59 - &clk[IMX27_CLK_UART6_IPG_GATE], 60 - NULL 61 - }; 62 - 63 52 static void __init _mx27_clocks_init(unsigned long fref) 64 53 { 65 54 BUG_ON(!ccm); ··· 165 176 166 177 clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]); 167 178 168 - imx_register_uart_clocks(uart_clks); 179 + imx_register_uart_clocks(7); 169 180 170 181 imx_print_silicon_rev("i.MX27", mx27_revision()); 171 182 }
+1 -9
drivers/clk/imx/clk-imx35.c
··· 82 82 83 83 static struct clk *clk[clk_max]; 84 84 85 - static struct clk ** const uart_clks[] __initconst = { 86 - &clk[ipg], 87 - &clk[uart1_gate], 88 - &clk[uart2_gate], 89 - &clk[uart3_gate], 90 - NULL 91 - }; 92 - 93 85 static void __init _mx35_clocks_init(void) 94 86 { 95 87 void __iomem *base; ··· 235 243 */ 236 244 clk_prepare_enable(clk[scc_gate]); 237 245 238 - imx_register_uart_clocks(uart_clks); 246 + imx_register_uart_clocks(4); 239 247 240 248 imx_print_silicon_rev("i.MX35", mx35_revision()); 241 249 }
+3 -27
drivers/clk/imx/clk-imx5.c
··· 128 128 static struct clk *clk[IMX5_CLK_END]; 129 129 static struct clk_onecell_data clk_data; 130 130 131 - static struct clk ** const uart_clks_mx51[] __initconst = { 132 - &clk[IMX5_CLK_UART1_IPG_GATE], 133 - &clk[IMX5_CLK_UART1_PER_GATE], 134 - &clk[IMX5_CLK_UART2_IPG_GATE], 135 - &clk[IMX5_CLK_UART2_PER_GATE], 136 - &clk[IMX5_CLK_UART3_IPG_GATE], 137 - &clk[IMX5_CLK_UART3_PER_GATE], 138 - NULL 139 - }; 140 - 141 - static struct clk ** const uart_clks_mx50_mx53[] __initconst = { 142 - &clk[IMX5_CLK_UART1_IPG_GATE], 143 - &clk[IMX5_CLK_UART1_PER_GATE], 144 - &clk[IMX5_CLK_UART2_IPG_GATE], 145 - &clk[IMX5_CLK_UART2_PER_GATE], 146 - &clk[IMX5_CLK_UART3_IPG_GATE], 147 - &clk[IMX5_CLK_UART3_PER_GATE], 148 - &clk[IMX5_CLK_UART4_IPG_GATE], 149 - &clk[IMX5_CLK_UART4_PER_GATE], 150 - &clk[IMX5_CLK_UART5_IPG_GATE], 151 - &clk[IMX5_CLK_UART5_PER_GATE], 152 - NULL 153 - }; 154 - 155 131 static void __init mx5_clocks_common_init(void __iomem *ccm_base) 156 132 { 157 133 clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0); ··· 358 382 r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000); 359 383 clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r); 360 384 361 - imx_register_uart_clocks(uart_clks_mx50_mx53); 385 + imx_register_uart_clocks(5); 362 386 } 363 387 CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init); 364 388 ··· 464 488 val |= 1 << 23; 465 489 writel(val, MXC_CCM_CLPCR); 466 490 467 - imx_register_uart_clocks(uart_clks_mx51); 491 + imx_register_uart_clocks(3); 468 492 } 469 493 CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init); 470 494 ··· 609 633 r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000); 610 634 clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r); 611 635 612 - imx_register_uart_clocks(uart_clks_mx50_mx53); 636 + imx_register_uart_clocks(5); 613 637 } 614 638 CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
+1 -15
drivers/clk/imx/clk-imx6q.c
··· 140 140 return of_machine_is_compatible("fsl,imx6dl"); 141 141 } 142 142 143 - static const int uart_clk_ids[] __initconst = { 144 - IMX6QDL_CLK_UART_IPG, 145 - IMX6QDL_CLK_UART_SERIAL, 146 - }; 147 - 148 - static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata; 149 - 150 143 static int ldb_di_sel_by_clock_id(int clock_id) 151 144 { 152 145 switch (clock_id) { ··· 433 440 struct device_node *np; 434 441 void __iomem *anatop_base, *base; 435 442 int ret; 436 - int i; 437 443 438 444 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 439 445 IMX6QDL_CLK_END), GFP_KERNEL); ··· 974 982 hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk); 975 983 } 976 984 977 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 978 - int index = uart_clk_ids[i]; 979 - 980 - uart_clks[i] = &hws[index]->clk; 981 - } 982 - 983 - imx_register_uart_clocks(uart_clks); 985 + imx_register_uart_clocks(1); 984 986 } 985 987 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
+1 -15
drivers/clk/imx/clk-imx6sl.c
··· 179 179 imx6sl_enable_pll_arm(false); 180 180 } 181 181 182 - static const int uart_clk_ids[] __initconst = { 183 - IMX6SL_CLK_UART, 184 - IMX6SL_CLK_UART_SERIAL, 185 - }; 186 - 187 - static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata; 188 - 189 182 static void __init imx6sl_clocks_init(struct device_node *ccm_node) 190 183 { 191 184 struct device_node *np; 192 185 void __iomem *base; 193 186 int ret; 194 - int i; 195 187 196 188 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 197 189 IMX6SL_CLK_END), GFP_KERNEL); ··· 440 448 clk_set_parent(hws[IMX6SL_CLK_LCDIF_AXI_SEL]->clk, 441 449 hws[IMX6SL_CLK_PLL2_PFD2]->clk); 442 450 443 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 444 - int index = uart_clk_ids[i]; 445 - 446 - uart_clks[i] = &hws[index]->clk; 447 - } 448 - 449 - imx_register_uart_clocks(uart_clks); 451 + imx_register_uart_clocks(2); 450 452 } 451 453 CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
+1 -23
drivers/clk/imx/clk-imx6sll.c
··· 76 76 static u32 share_count_ssi2; 77 77 static u32 share_count_ssi3; 78 78 79 - static const int uart_clk_ids[] __initconst = { 80 - IMX6SLL_CLK_UART1_IPG, 81 - IMX6SLL_CLK_UART1_SERIAL, 82 - IMX6SLL_CLK_UART2_IPG, 83 - IMX6SLL_CLK_UART2_SERIAL, 84 - IMX6SLL_CLK_UART3_IPG, 85 - IMX6SLL_CLK_UART3_SERIAL, 86 - IMX6SLL_CLK_UART4_IPG, 87 - IMX6SLL_CLK_UART4_SERIAL, 88 - IMX6SLL_CLK_UART5_IPG, 89 - IMX6SLL_CLK_UART5_SERIAL, 90 - }; 91 - 92 - static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata; 93 - 94 79 static void __init imx6sll_clocks_init(struct device_node *ccm_node) 95 80 { 96 81 struct device_node *np; 97 82 void __iomem *base; 98 - int i; 99 83 100 84 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 101 85 IMX6SLL_CLK_END), GFP_KERNEL); ··· 340 356 341 357 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); 342 358 343 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 344 - int index = uart_clk_ids[i]; 345 - 346 - uart_clks[i] = &hws[index]->clk; 347 - } 348 - 349 - imx_register_uart_clocks(uart_clks); 359 + imx_register_uart_clocks(5); 350 360 351 361 /* Lower the AHB clock rate before changing the clock source. */ 352 362 clk_set_rate(hws[IMX6SLL_CLK_AHB]->clk, 99000000);
+1 -15
drivers/clk/imx/clk-imx6sx.c
··· 117 117 static u32 share_count_sai1; 118 118 static u32 share_count_sai2; 119 119 120 - static const int uart_clk_ids[] __initconst = { 121 - IMX6SX_CLK_UART_IPG, 122 - IMX6SX_CLK_UART_SERIAL, 123 - }; 124 - 125 - static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata; 126 - 127 120 static void __init imx6sx_clocks_init(struct device_node *ccm_node) 128 121 { 129 122 struct device_node *np; 130 123 void __iomem *base; 131 - int i; 132 124 133 125 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 134 126 IMX6SX_CLK_CLK_END), GFP_KERNEL); ··· 548 556 clk_set_parent(hws[IMX6SX_CLK_QSPI1_SEL]->clk, hws[IMX6SX_CLK_PLL2_BUS]->clk); 549 557 clk_set_parent(hws[IMX6SX_CLK_QSPI2_SEL]->clk, hws[IMX6SX_CLK_PLL2_BUS]->clk); 550 558 551 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 552 - int index = uart_clk_ids[i]; 553 - 554 - uart_clks[i] = &hws[index]->clk; 555 - } 556 - 557 - imx_register_uart_clocks(uart_clks); 559 + imx_register_uart_clocks(2); 558 560 } 559 561 CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
+1 -21
drivers/clk/imx/clk-imx7d.c
··· 377 377 static struct clk_hw **hws; 378 378 static struct clk_hw_onecell_data *clk_hw_data; 379 379 380 - static const int uart_clk_ids[] __initconst = { 381 - IMX7D_UART1_ROOT_CLK, 382 - IMX7D_UART2_ROOT_CLK, 383 - IMX7D_UART3_ROOT_CLK, 384 - IMX7D_UART4_ROOT_CLK, 385 - IMX7D_UART5_ROOT_CLK, 386 - IMX7D_UART6_ROOT_CLK, 387 - IMX7D_UART7_ROOT_CLK, 388 - }; 389 - 390 - static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1] __initdata; 391 - 392 380 static void __init imx7d_clocks_init(struct device_node *ccm_node) 393 381 { 394 382 struct device_node *np; 395 383 void __iomem *base; 396 - int i; 397 384 398 385 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 399 386 IMX7D_CLK_END), GFP_KERNEL); ··· 884 897 hws[IMX7D_USB1_MAIN_480M_CLK] = imx_clk_hw_fixed_factor("pll_usb1_main_clk", "osc", 20, 1); 885 898 hws[IMX7D_USB_MAIN_480M_CLK] = imx_clk_hw_fixed_factor("pll_usb_main_clk", "osc", 20, 1); 886 899 887 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 888 - int index = uart_clk_ids[i]; 889 - 890 - uart_clks[i] = &hws[index]->clk; 891 - } 892 - 893 - 894 - imx_register_uart_clocks(uart_clks); 900 + imx_register_uart_clocks(7); 895 901 896 902 } 897 903 CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init);
+2 -29
drivers/clk/imx/clk-imx7ulp.c
··· 43 43 { /* sentinel */ }, 44 44 }; 45 45 46 - static const int pcc2_uart_clk_ids[] __initconst = { 47 - IMX7ULP_CLK_LPUART4, 48 - IMX7ULP_CLK_LPUART5, 49 - }; 50 - 51 - static const int pcc3_uart_clk_ids[] __initconst = { 52 - IMX7ULP_CLK_LPUART6, 53 - IMX7ULP_CLK_LPUART7, 54 - }; 55 - 56 - static struct clk **pcc2_uart_clks[ARRAY_SIZE(pcc2_uart_clk_ids) + 1] __initdata; 57 - static struct clk **pcc3_uart_clks[ARRAY_SIZE(pcc3_uart_clk_ids) + 1] __initdata; 58 - 59 46 static void __init imx7ulp_clk_scg1_init(struct device_node *np) 60 47 { 61 48 struct clk_hw_onecell_data *clk_data; ··· 137 150 struct clk_hw_onecell_data *clk_data; 138 151 struct clk_hw **hws; 139 152 void __iomem *base; 140 - int i; 141 153 142 154 clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_PCC2_END), 143 155 GFP_KERNEL); ··· 176 190 177 191 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); 178 192 179 - for (i = 0; i < ARRAY_SIZE(pcc2_uart_clk_ids); i++) { 180 - int index = pcc2_uart_clk_ids[i]; 181 - 182 - pcc2_uart_clks[i] = &hws[index]->clk; 183 - } 184 - 185 - imx_register_uart_clocks(pcc2_uart_clks); 193 + imx_register_uart_clocks(2); 186 194 } 187 195 CLK_OF_DECLARE(imx7ulp_clk_pcc2, "fsl,imx7ulp-pcc2", imx7ulp_clk_pcc2_init); 188 196 ··· 185 205 struct clk_hw_onecell_data *clk_data; 186 206 struct clk_hw **hws; 187 207 void __iomem *base; 188 - int i; 189 208 190 209 clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_PCC3_END), 191 210 GFP_KERNEL); ··· 223 244 224 245 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); 225 246 226 - for (i = 0; i < ARRAY_SIZE(pcc3_uart_clk_ids); i++) { 227 - int index = pcc3_uart_clk_ids[i]; 228 - 229 - pcc3_uart_clks[i] = &hws[index]->clk; 230 - } 231 - 232 - imx_register_uart_clocks(pcc3_uart_clks); 247 + imx_register_uart_clocks(7); 233 248 } 234 249 CLK_OF_DECLARE(imx7ulp_clk_pcc3, "fsl,imx7ulp-pcc3", imx7ulp_clk_pcc3_init); 235 250
+2 -16
drivers/clk/imx/clk-imx8mm.c
··· 296 296 static struct clk_hw_onecell_data *clk_hw_data; 297 297 static struct clk_hw **hws; 298 298 299 - static const int uart_clk_ids[] = { 300 - IMX8MM_CLK_UART1_ROOT, 301 - IMX8MM_CLK_UART2_ROOT, 302 - IMX8MM_CLK_UART3_ROOT, 303 - IMX8MM_CLK_UART4_ROOT, 304 - }; 305 - static struct clk **uart_hws[ARRAY_SIZE(uart_clk_ids) + 1]; 306 - 307 299 static int imx8mm_clocks_probe(struct platform_device *pdev) 308 300 { 309 301 struct device *dev = &pdev->dev; 310 302 struct device_node *np = dev->of_node; 311 303 void __iomem *base; 312 - int ret, i; 304 + int ret; 313 305 314 306 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 315 307 IMX8MM_CLK_END), GFP_KERNEL); ··· 626 634 goto unregister_hws; 627 635 } 628 636 629 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 630 - int index = uart_clk_ids[i]; 631 - 632 - uart_hws[i] = &hws[index]->clk; 633 - } 634 - 635 - imx_register_uart_clocks(uart_hws); 637 + imx_register_uart_clocks(4); 636 638 637 639 return 0; 638 640
+2 -16
drivers/clk/imx/clk-imx8mn.c
··· 289 289 static struct clk_hw_onecell_data *clk_hw_data; 290 290 static struct clk_hw **hws; 291 291 292 - static const int uart_clk_ids[] = { 293 - IMX8MN_CLK_UART1_ROOT, 294 - IMX8MN_CLK_UART2_ROOT, 295 - IMX8MN_CLK_UART3_ROOT, 296 - IMX8MN_CLK_UART4_ROOT, 297 - }; 298 - static struct clk **uart_hws[ARRAY_SIZE(uart_clk_ids) + 1]; 299 - 300 292 static int imx8mn_clocks_probe(struct platform_device *pdev) 301 293 { 302 294 struct device *dev = &pdev->dev; 303 295 struct device_node *np = dev->of_node; 304 296 void __iomem *base; 305 - int ret, i; 297 + int ret; 306 298 307 299 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 308 300 IMX8MN_CLK_END), GFP_KERNEL); ··· 577 585 goto unregister_hws; 578 586 } 579 587 580 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 581 - int index = uart_clk_ids[i]; 582 - 583 - uart_hws[i] = &hws[index]->clk; 584 - } 585 - 586 - imx_register_uart_clocks(uart_hws); 588 + imx_register_uart_clocks(4); 587 589 588 590 return 0; 589 591
+1 -16
drivers/clk/imx/clk-imx8mp.c
··· 414 414 static struct clk_hw **hws; 415 415 static struct clk_hw_onecell_data *clk_hw_data; 416 416 417 - static const int uart_clk_ids[] = { 418 - IMX8MP_CLK_UART1_ROOT, 419 - IMX8MP_CLK_UART2_ROOT, 420 - IMX8MP_CLK_UART3_ROOT, 421 - IMX8MP_CLK_UART4_ROOT, 422 - }; 423 - static struct clk **uart_clks[ARRAY_SIZE(uart_clk_ids) + 1]; 424 - 425 417 static int imx8mp_clocks_probe(struct platform_device *pdev) 426 418 { 427 419 struct device *dev = &pdev->dev; 428 420 struct device_node *np; 429 421 void __iomem *anatop_base, *ccm_base; 430 - int i; 431 422 432 423 np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop"); 433 424 anatop_base = of_iomap(np, 0); ··· 728 737 729 738 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); 730 739 731 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 732 - int index = uart_clk_ids[i]; 733 - 734 - uart_clks[i] = &hws[index]->clk; 735 - } 736 - 737 - imx_register_uart_clocks(uart_clks); 740 + imx_register_uart_clocks(4); 738 741 739 742 return 0; 740 743 }
+2 -16
drivers/clk/imx/clk-imx8mq.c
··· 281 281 static struct clk_hw_onecell_data *clk_hw_data; 282 282 static struct clk_hw **hws; 283 283 284 - static const int uart_clk_ids[] = { 285 - IMX8MQ_CLK_UART1_ROOT, 286 - IMX8MQ_CLK_UART2_ROOT, 287 - IMX8MQ_CLK_UART3_ROOT, 288 - IMX8MQ_CLK_UART4_ROOT, 289 - }; 290 - static struct clk **uart_hws[ARRAY_SIZE(uart_clk_ids) + 1]; 291 - 292 284 static int imx8mq_clocks_probe(struct platform_device *pdev) 293 285 { 294 286 struct device *dev = &pdev->dev; 295 287 struct device_node *np = dev->of_node; 296 288 void __iomem *base; 297 - int err, i; 289 + int err; 298 290 299 291 clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, 300 292 IMX8MQ_CLK_END), GFP_KERNEL); ··· 621 629 goto unregister_hws; 622 630 } 623 631 624 - for (i = 0; i < ARRAY_SIZE(uart_clk_ids); i++) { 625 - int index = uart_clk_ids[i]; 626 - 627 - uart_hws[i] = &hws[index]->clk; 628 - } 629 - 630 - imx_register_uart_clocks(uart_hws); 632 + imx_register_uart_clocks(4); 631 633 632 634 return 0; 633 635
+32 -9
drivers/clk/imx/clk.c
··· 147 147 } 148 148 149 149 #ifndef MODULE 150 - static int imx_keep_uart_clocks; 151 - static struct clk ** const *imx_uart_clocks; 150 + 151 + static bool imx_keep_uart_clocks; 152 + static int imx_enabled_uart_clocks; 153 + static struct clk **imx_uart_clocks; 152 154 153 155 static int __init imx_keep_uart_clocks_param(char *str) 154 156 { ··· 163 161 __setup_param("earlyprintk", imx_keep_uart_earlyprintk, 164 162 imx_keep_uart_clocks_param, 0); 165 163 166 - void imx_register_uart_clocks(struct clk ** const clks[]) 164 + void imx_register_uart_clocks(unsigned int clk_count) 167 165 { 166 + imx_enabled_uart_clocks = 0; 167 + 168 + /* i.MX boards use device trees now. For build tests without CONFIG_OF, do nothing */ 169 + #ifdef CONFIG_OF 168 170 if (imx_keep_uart_clocks) { 169 171 int i; 170 172 171 - imx_uart_clocks = clks; 172 - for (i = 0; imx_uart_clocks[i]; i++) 173 - clk_prepare_enable(*imx_uart_clocks[i]); 173 + imx_uart_clocks = kcalloc(clk_count, sizeof(struct clk *), GFP_KERNEL); 174 + 175 + if (!of_stdout) 176 + return; 177 + 178 + for (i = 0; i < clk_count; i++) { 179 + imx_uart_clocks[imx_enabled_uart_clocks] = of_clk_get(of_stdout, i); 180 + 181 + /* Stop if there are no more of_stdout references */ 182 + if (IS_ERR(imx_uart_clocks[imx_enabled_uart_clocks])) 183 + return; 184 + 185 + /* Only enable the clock if it's not NULL */ 186 + if (imx_uart_clocks[imx_enabled_uart_clocks]) 187 + clk_prepare_enable(imx_uart_clocks[imx_enabled_uart_clocks++]); 188 + } 174 189 } 190 + #endif 175 191 } 176 192 177 193 static int __init imx_clk_disable_uart(void) 178 194 { 179 - if (imx_keep_uart_clocks && imx_uart_clocks) { 195 + if (imx_keep_uart_clocks && imx_enabled_uart_clocks) { 180 196 int i; 181 197 182 - for (i = 0; imx_uart_clocks[i]; i++) 183 - clk_disable_unprepare(*imx_uart_clocks[i]); 198 + for (i = 0; i < imx_enabled_uart_clocks; i++) { 199 + clk_disable_unprepare(imx_uart_clocks[i]); 200 + clk_put(imx_uart_clocks[i]); 201 + } 202 + kfree(imx_uart_clocks); 184 203 } 185 204 186 205 return 0;
+2 -2
drivers/clk/imx/clk.h
··· 11 11 void imx_check_clocks(struct clk *clks[], unsigned int count); 12 12 void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count); 13 13 #ifndef MODULE 14 - void imx_register_uart_clocks(struct clk ** const clks[]); 14 + void imx_register_uart_clocks(unsigned int clk_count); 15 15 #else 16 - static inline void imx_register_uart_clocks(struct clk ** const clks[]) 16 + static inline void imx_register_uart_clocks(unsigned int clk_count) 17 17 { 18 18 } 19 19 #endif