Skip to content

Commit 77d8f30

Browse files
Dong AishengShawn Guo
authored andcommitted
clk: imx: scu: add two cells binding support
This patch implements the new two cells binding for SCU clocks. The usage is as follows: clocks = <&uart0_clk IMX_SC_R_UART_0 IMX_SC_PM_CLK_PER> Due to each SCU clock is associated with a power domain, without power on the domain, the SCU clock can't work. So we create platform devices for each domain clock respectively and manually attach the required domain before register the clock devices, then we can register clocks in the clock platform driver accordingly. Note because we do not have power domain info in device tree and the SCU resource ID is the same for power domain and clock, so we use resource ID to find power domains. Later, we will also use this clock platform driver to support suspend/resume and runtime pm. Cc: Stephen Boyd <[email protected]> Cc: Shawn Guo <[email protected]> Cc: Sascha Hauer <[email protected]> Cc: Michael Turquette <[email protected]> Signed-off-by: Dong Aisheng <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Signed-off-by: Shawn Guo <[email protected]>
1 parent 3650b22 commit 77d8f30

File tree

3 files changed

+252
-67
lines changed

3 files changed

+252
-67
lines changed

drivers/clk/imx/clk-imx8qxp.c

Lines changed: 76 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
2222
struct device_node *ccm_node = pdev->dev.of_node;
2323
struct clk_hw_onecell_data *clk_data;
2424
struct clk_hw **clks;
25+
u32 clk_cells;
2526
int ret, i;
2627

27-
ret = imx_clk_scu_init();
28+
ret = imx_clk_scu_init(ccm_node);
2829
if (ret)
2930
return ret;
3031

@@ -33,6 +34,9 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
3334
if (!clk_data)
3435
return -ENOMEM;
3536

37+
if (of_property_read_u32(ccm_node, "#clock-cells", &clk_cells))
38+
return -EINVAL;
39+
3640
clk_data->num = IMX_SCU_CLK_END;
3741
clks = clk_data->hws;
3842

@@ -55,86 +59,98 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
5559
clks[IMX_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000);
5660

5761
/* ARM core */
58-
clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
62+
clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU, clk_cells);
5963

6064
/* LSIO SS */
61-
clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER);
62-
clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER);
63-
clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER);
64-
clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER);
65-
clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER);
66-
clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER);
67-
clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER);
68-
clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER);
69-
clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER);
70-
clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER);
71-
clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER);
72-
clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER);
73-
clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER);
74-
clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER);
75-
clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER);
65+
clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
66+
clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER, clk_cells);
67+
clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER, clk_cells);
68+
clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER, clk_cells);
69+
clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER, clk_cells);
70+
clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER, clk_cells);
71+
clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER, clk_cells);
72+
clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER, clk_cells);
73+
clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER, clk_cells);
74+
clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER, clk_cells);
75+
clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER, clk_cells);
76+
clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER, clk_cells);
77+
clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER, clk_cells);
78+
clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER, clk_cells);
79+
clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER, clk_cells);
7680

7781
/* ADMA SS */
78-
clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
79-
clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER);
80-
clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER);
81-
clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER);
82-
clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER);
83-
clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER);
84-
clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER);
85-
clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER);
86-
clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER);
87-
clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER);
88-
clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER);
89-
clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER);
90-
clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER);
91-
clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER);
92-
clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER);
93-
clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
94-
clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
95-
clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
82+
clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, clk_cells);
83+
clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER, clk_cells);
84+
clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER, clk_cells);
85+
clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER, clk_cells);
86+
clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER, clk_cells);
87+
clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER, clk_cells);
88+
clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER, clk_cells);
89+
clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER, clk_cells);
90+
clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER, clk_cells);
91+
clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER, clk_cells);
92+
clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER, clk_cells);
93+
clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER, clk_cells);
94+
clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER, clk_cells);
95+
clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER, clk_cells);
96+
clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER, clk_cells);
97+
clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER, clk_cells);
98+
clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
99+
clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER, clk_cells);
96100

97101
/* Connectivity */
98-
clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER);
99-
clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER);
100-
clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER);
101-
clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER);
102-
clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
103-
clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
104-
clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
105-
clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
106-
clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
107-
clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
108-
clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
109-
clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);
110-
clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS);
111-
clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC);
102+
clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER, clk_cells);
103+
clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER, clk_cells);
104+
clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER, clk_cells);
105+
clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER, clk_cells);
106+
clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS, clk_cells);
107+
clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0, clk_cells);
108+
clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER, clk_cells);
109+
clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS, clk_cells);
110+
clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0, clk_cells);
111+
clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS, clk_cells);
112+
clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER, clk_cells);
113+
clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER, clk_cells);
114+
clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS, clk_cells);
115+
clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells);
112116

113117
/* Display controller SS */
114-
clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0);
115-
clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1);
118+
clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells);
119+
clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells);
116120

117121
/* MIPI-LVDS SS */
118-
clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2);
119-
clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2);
122+
clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells);
123+
clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells);
120124

121125
/* MIPI CSI SS */
122-
clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
123-
clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
124-
clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
125-
clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
126+
clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells);
127+
clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, clk_cells);
128+
clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, clk_cells);
129+
clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells);
126130

127131
/* GPU SS */
128-
clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER);
129-
clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC);
132+
clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER, clk_cells);
133+
clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC, clk_cells);
130134

131135
for (i = 0; i < clk_data->num; i++) {
132136
if (IS_ERR(clks[i]))
133137
pr_warn("i.MX clk %u: register failed with %ld\n",
134138
i, PTR_ERR(clks[i]));
135139
}
136140

137-
return of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
141+
if (clk_cells == 2) {
142+
ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks);
143+
if (ret)
144+
imx_clk_scu_unregister();
145+
} else {
146+
/*
147+
* legacy binding code path doesn't unregister here because
148+
* it will be removed later.
149+
*/
150+
ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
151+
}
152+
153+
return ret;
138154
}
139155

140156
static const struct of_device_id imx8qxp_match[] = {

drivers/clk/imx/clk-scu.c

Lines changed: 154 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <linux/arm-smccc.h>
99
#include <linux/clk-provider.h>
1010
#include <linux/err.h>
11+
#include <linux/of_platform.h>
12+
#include <linux/platform_device.h>
13+
#include <linux/pm_domain.h>
1114
#include <linux/slab.h>
1215

1316
#include "clk-scu.h"
@@ -16,6 +19,20 @@
1619
#define IMX_SIP_SET_CPUFREQ 0x00
1720

1821
static struct imx_sc_ipc *ccm_ipc_handle;
22+
struct device_node *pd_np;
23+
24+
struct imx_scu_clk_node {
25+
const char *name;
26+
u32 rsrc;
27+
u8 clk_type;
28+
const char * const *parents;
29+
int num_parents;
30+
31+
struct clk_hw *hw;
32+
struct list_head node;
33+
};
34+
35+
struct list_head imx_scu_clks[IMX_SC_R_LAST];
1936

2037
/*
2138
* struct clk_scu - Description of one SCU clock
@@ -128,9 +145,35 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
128145
return container_of(hw, struct clk_scu, hw);
129146
}
130147

131-
int imx_clk_scu_init(void)
148+
int imx_clk_scu_init(struct device_node *np)
132149
{
133-
return imx_scu_get_handle(&ccm_ipc_handle);
150+
struct platform_device *pd_dev;
151+
u32 clk_cells;
152+
int ret, i;
153+
154+
ret = imx_scu_get_handle(&ccm_ipc_handle);
155+
if (ret)
156+
return ret;
157+
158+
of_property_read_u32(np, "#clock-cells", &clk_cells);
159+
160+
if (clk_cells == 2) {
161+
for (i = 0; i < IMX_SC_R_LAST; i++)
162+
INIT_LIST_HEAD(&imx_scu_clks[i]);
163+
/*
164+
* Note: SCU clock driver depends on SCU power domain to be ready
165+
* first. As there're no power domains under scu clock node in dts,
166+
* we can't use PROBE_DEFER automatically.
167+
*/
168+
pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd");
169+
pd_dev = of_find_device_by_node(pd_np);
170+
if (!pd_dev || !device_is_bound(&pd_dev->dev)) {
171+
of_node_put(pd_np);
172+
return -EPROBE_DEFER;
173+
}
174+
}
175+
176+
return 0;
134177
}
135178

136179
/*
@@ -387,3 +430,112 @@ struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
387430

388431
return hw;
389432
}
433+
434+
struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec,
435+
void *data)
436+
{
437+
unsigned int rsrc = clkspec->args[0];
438+
unsigned int idx = clkspec->args[1];
439+
struct list_head *scu_clks = data;
440+
struct imx_scu_clk_node *clk;
441+
442+
list_for_each_entry(clk, &scu_clks[rsrc], node) {
443+
if (clk->clk_type == idx)
444+
return clk->hw;
445+
}
446+
447+
return ERR_PTR(-ENODEV);
448+
}
449+
450+
static int imx_clk_scu_probe(struct platform_device *pdev)
451+
{
452+
struct device *dev = &pdev->dev;
453+
struct imx_scu_clk_node *clk = dev_get_platdata(dev);
454+
struct clk_hw *hw;
455+
456+
hw = __imx_clk_scu(clk->name, clk->parents, clk->num_parents,
457+
clk->rsrc, clk->clk_type);
458+
if (IS_ERR(hw))
459+
return PTR_ERR(hw);
460+
461+
clk->hw = hw;
462+
list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]);
463+
464+
dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc,
465+
clk->clk_type);
466+
467+
return 0;
468+
}
469+
470+
static struct platform_driver imx_clk_scu_driver = {
471+
.driver = {
472+
.name = "imx-scu-clk",
473+
.suppress_bind_attrs = true,
474+
},
475+
.probe = imx_clk_scu_probe,
476+
};
477+
builtin_platform_driver(imx_clk_scu_driver);
478+
479+
static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
480+
{
481+
struct of_phandle_args genpdspec = {
482+
.np = pd_np,
483+
.args_count = 1,
484+
.args[0] = rsrc_id,
485+
};
486+
487+
return of_genpd_add_device(&genpdspec, dev);
488+
}
489+
490+
struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
491+
const char * const *parents,
492+
int num_parents, u32 rsrc_id, u8 clk_type)
493+
{
494+
struct imx_scu_clk_node clk = {
495+
.name = name,
496+
.rsrc = rsrc_id,
497+
.clk_type = clk_type,
498+
.parents = parents,
499+
.num_parents = num_parents,
500+
};
501+
struct platform_device *pdev;
502+
int ret;
503+
504+
pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
505+
if (!pdev) {
506+
pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
507+
name, rsrc_id, clk_type);
508+
return ERR_PTR(-ENOMEM);
509+
}
510+
511+
ret = platform_device_add_data(pdev, &clk, sizeof(clk));
512+
if (ret) {
513+
platform_device_put(pdev);
514+
return ERR_PTR(ret);
515+
}
516+
517+
pdev->driver_override = "imx-scu-clk";
518+
519+
ret = imx_clk_scu_attach_pd(&pdev->dev, rsrc_id);
520+
if (ret)
521+
pr_warn("%s: failed to attached the power domain %d\n",
522+
name, ret);
523+
524+
platform_device_add(pdev);
525+
526+
/* For API backwards compatiblilty, simply return NULL for success */
527+
return NULL;
528+
}
529+
530+
void imx_clk_scu_unregister(void)
531+
{
532+
struct imx_scu_clk_node *clk;
533+
int i;
534+
535+
for (i = 0; i < IMX_SC_R_LAST; i++) {
536+
list_for_each_entry(clk, &imx_scu_clks[i], node) {
537+
clk_hw_unregister(clk->hw);
538+
kfree(clk);
539+
}
540+
}
541+
}

0 commit comments

Comments
 (0)