blob: 92b79a3a02c3e2c3ce857548801661cbe30cc0c5 [file] [log] [blame]
Lukasz Majewski4de44bb2019-06-24 15:50:45 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 DENX Software Engineering
4 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
5 */
6
Lukasz Majewski4de44bb2019-06-24 15:50:45 +02007#include <clk-uclass.h>
8#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06009#include <log.h>
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020010#include <asm/arch/clock.h>
11#include <asm/arch/imx-regs.h>
12#include <dt-bindings/clock/imx6qdl-clock.h>
13
14#include "clk.h"
15
Sean Anderson35c84642022-03-20 16:34:46 -040016static int imx6q_clk_request(struct clk *clk)
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020017{
Sean Anderson35c84642022-03-20 16:34:46 -040018 if (clk->id < IMX6QDL_CLK_DUMMY || clk->id >= IMX6QDL_CLK_END) {
19 printf("%s: Invalid clk ID #%lu\n", __func__, clk->id);
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020020 return -EINVAL;
21 }
22
23 return 0;
24}
25
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020026static struct clk_ops imx6q_clk_ops = {
Sean Anderson35c84642022-03-20 16:34:46 -040027 .request = imx6q_clk_request,
28 .set_rate = ccf_clk_set_rate,
29 .get_rate = ccf_clk_get_rate,
30 .enable = ccf_clk_enable,
31 .disable = ccf_clk_disable,
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020032};
33
34static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
Lukasz Majewski2f665412019-10-15 12:44:57 +020035static const char *const periph_sels[] = { "periph_pre", "periph_clk2", };
36static const char *const periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m",
37 "pll2_pfd0_352m", "pll2_198m", };
Adam Forda64506a2025-03-18 18:38:30 -050038static const char *const uart_sels[] = { "pll3_80m", "osc", };
Adam Ford5a7c1c12025-03-18 18:38:29 -050039static const char *const ecspi_sels[] = { "pll3_60m", "osc", };
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020040
41static int imx6q_clk_probe(struct udevice *dev)
42{
43 void *base;
44
45 /* Anatop clocks */
46 base = (void *)ANATOP_BASE_ADDR;
47
48 clk_dm(IMX6QDL_CLK_PLL2,
49 imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc",
50 base + 0x30, 0x1));
51 clk_dm(IMX6QDL_CLK_PLL3_USB_OTG,
52 imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc",
53 base + 0x10, 0x3));
54 clk_dm(IMX6QDL_CLK_PLL3_60M,
55 imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8));
56 clk_dm(IMX6QDL_CLK_PLL2_PFD0_352M,
57 imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0));
58 clk_dm(IMX6QDL_CLK_PLL2_PFD2_396M,
59 imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2));
Lukasz Majewski8252da02020-02-24 14:55:26 +010060 clk_dm(IMX6QDL_CLK_PLL6,
61 imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3));
62 clk_dm(IMX6QDL_CLK_PLL6_ENET,
63 imx_clk_gate("pll6_enet", "pll6", base + 0xe0, 13));
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020064
65 /* CCM clocks */
66 base = dev_read_addr_ptr(dev);
Sean Andersonb58106d2019-12-24 23:57:47 -050067 if (!base)
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020068 return -EINVAL;
69
70 clk_dm(IMX6QDL_CLK_USDHC1_SEL,
Marek Vasut33480a92025-03-23 16:58:34 +010071 imx_clk_mux(dev, "usdhc1_sel", base + 0x1c, 16, 1,
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020072 usdhc_sels, ARRAY_SIZE(usdhc_sels)));
73 clk_dm(IMX6QDL_CLK_USDHC2_SEL,
Marek Vasut33480a92025-03-23 16:58:34 +010074 imx_clk_mux(dev, "usdhc2_sel", base + 0x1c, 17, 1,
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020075 usdhc_sels, ARRAY_SIZE(usdhc_sels)));
76 clk_dm(IMX6QDL_CLK_USDHC3_SEL,
Marek Vasut33480a92025-03-23 16:58:34 +010077 imx_clk_mux(dev, "usdhc3_sel", base + 0x1c, 18, 1,
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020078 usdhc_sels, ARRAY_SIZE(usdhc_sels)));
79 clk_dm(IMX6QDL_CLK_USDHC4_SEL,
Marek Vasut33480a92025-03-23 16:58:34 +010080 imx_clk_mux(dev, "usdhc4_sel", base + 0x1c, 19, 1,
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020081 usdhc_sels, ARRAY_SIZE(usdhc_sels)));
82
Adam Forda64506a2025-03-18 18:38:30 -050083 if (of_machine_is_compatible("fsl,imx6qp")) {
84 clk_dm(IMX6QDL_CLK_UART_SEL,
Marek Vasut33480a92025-03-23 16:58:34 +010085 imx_clk_mux(dev, "uart_sel", base + 0x24, 6, 1, uart_sels,
Adam Forda64506a2025-03-18 18:38:30 -050086 ARRAY_SIZE(uart_sels)));
Adam Ford5a7c1c12025-03-18 18:38:29 -050087 clk_dm(IMX6QDL_CLK_ECSPI_SEL,
Marek Vasut33480a92025-03-23 16:58:34 +010088 imx_clk_mux(dev, "ecspi_sel", base + 0x38, 18, 1, ecspi_sels,
Adam Ford5a7c1c12025-03-18 18:38:29 -050089 ARRAY_SIZE(ecspi_sels)));
Adam Forda64506a2025-03-18 18:38:30 -050090 }
Adam Ford5a7c1c12025-03-18 18:38:29 -050091
Lukasz Majewski4de44bb2019-06-24 15:50:45 +020092 clk_dm(IMX6QDL_CLK_USDHC1_PODF,
93 imx_clk_divider("usdhc1_podf", "usdhc1_sel",
94 base + 0x24, 11, 3));
95 clk_dm(IMX6QDL_CLK_USDHC2_PODF,
96 imx_clk_divider("usdhc2_podf", "usdhc2_sel",
97 base + 0x24, 16, 3));
98 clk_dm(IMX6QDL_CLK_USDHC3_PODF,
99 imx_clk_divider("usdhc3_podf", "usdhc3_sel",
100 base + 0x24, 19, 3));
101 clk_dm(IMX6QDL_CLK_USDHC4_PODF,
102 imx_clk_divider("usdhc4_podf", "usdhc4_sel",
103 base + 0x24, 22, 3));
104
Adam Forda64506a2025-03-18 18:38:30 -0500105 if (of_machine_is_compatible("fsl,imx6qp")) {
106 clk_dm(IMX6QDL_CLK_UART_SERIAL_PODF,
107 imx_clk_divider("uart_serial_podf", "uart_sel", base + 0x24, 0, 6));
Adam Ford5a7c1c12025-03-18 18:38:29 -0500108 clk_dm(IMX6QDL_CLK_ECSPI_ROOT,
109 imx_clk_divider("ecspi_root", "ecspi_sel", base + 0x38, 19, 6));
Adam Forda64506a2025-03-18 18:38:30 -0500110 } else {
111 clk_dm(IMX6QDL_CLK_UART_SERIAL_PODF,
112 imx_clk_divider("uart_serial_podf", "pll3_80m", base + 0x24, 0, 6));
Adam Ford5a7c1c12025-03-18 18:38:29 -0500113 clk_dm(IMX6QDL_CLK_ECSPI_ROOT,
114 imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6));
Adam Forda64506a2025-03-18 18:38:30 -0500115 }
Lukasz Majewski4de44bb2019-06-24 15:50:45 +0200116
117 clk_dm(IMX6QDL_CLK_ECSPI1,
118 imx_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0));
119 clk_dm(IMX6QDL_CLK_ECSPI2,
120 imx_clk_gate2("ecspi2", "ecspi_root", base + 0x6c, 2));
121 clk_dm(IMX6QDL_CLK_ECSPI3,
122 imx_clk_gate2("ecspi3", "ecspi_root", base + 0x6c, 4));
123 clk_dm(IMX6QDL_CLK_ECSPI4,
124 imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6));
Adam Forda64506a2025-03-18 18:38:30 -0500125 clk_dm(IMX6QDL_CLK_UART_IPG,
126 imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24));
127 clk_dm(IMX6QDL_CLK_UART_SERIAL,
128 imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26));
Lukasz Majewski4de44bb2019-06-24 15:50:45 +0200129 clk_dm(IMX6QDL_CLK_USDHC1,
130 imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2));
131 clk_dm(IMX6QDL_CLK_USDHC2,
132 imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4));
133 clk_dm(IMX6QDL_CLK_USDHC3,
134 imx_clk_gate2("usdhc3", "usdhc3_podf", base + 0x80, 6));
135 clk_dm(IMX6QDL_CLK_USDHC4,
136 imx_clk_gate2("usdhc4", "usdhc4_podf", base + 0x80, 8));
137
Lukasz Majewski2f665412019-10-15 12:44:57 +0200138 clk_dm(IMX6QDL_CLK_PERIPH_PRE,
Marek Vasut33480a92025-03-23 16:58:34 +0100139 imx_clk_mux(dev, "periph_pre", base + 0x18, 18, 2, periph_pre_sels,
Lukasz Majewski2f665412019-10-15 12:44:57 +0200140 ARRAY_SIZE(periph_pre_sels)));
141 clk_dm(IMX6QDL_CLK_PERIPH,
Marek Vasut33480a92025-03-23 16:58:34 +0100142 imx_clk_busy_mux(dev, "periph", base + 0x14, 25, 1, base + 0x48,
Lukasz Majewski2f665412019-10-15 12:44:57 +0200143 5, periph_sels, ARRAY_SIZE(periph_sels)));
144 clk_dm(IMX6QDL_CLK_AHB,
145 imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3,
146 base + 0x48, 1));
147 clk_dm(IMX6QDL_CLK_IPG,
148 imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2));
149 clk_dm(IMX6QDL_CLK_IPG_PER,
150 imx_clk_divider("ipg_per", "ipg", base + 0x1c, 0, 6));
151 clk_dm(IMX6QDL_CLK_I2C1,
152 imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6));
153 clk_dm(IMX6QDL_CLK_I2C2,
154 imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8));
Emil Kronborg55f528f2024-07-12 14:19:10 +0000155 clk_dm(IMX6QDL_CLK_I2C3,
156 imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10));
Emil Kronborg907d1c42024-07-22 13:14:58 -0300157 clk_dm(IMX6QDL_CLK_PWM1,
158 imx_clk_gate2("pwm1", "ipg_per", base + 0x78, 16));
Lukasz Majewski2f665412019-10-15 12:44:57 +0200159
Lukasz Majewskicffad9c2020-02-24 14:55:24 +0100160 clk_dm(IMX6QDL_CLK_ENET, imx_clk_gate2("enet", "ipg", base + 0x6c, 10));
Lukasz Majewski8252da02020-02-24 14:55:26 +0100161 clk_dm(IMX6QDL_CLK_ENET_REF,
162 imx_clk_fixed_factor("enet_ref", "pll6_enet", 1, 1));
163
Lukasz Majewski4de44bb2019-06-24 15:50:45 +0200164 return 0;
165}
166
167static const struct udevice_id imx6q_clk_ids[] = {
168 { .compatible = "fsl,imx6q-ccm" },
169 { },
170};
171
172U_BOOT_DRIVER(imx6q_clk) = {
173 .name = "clk_imx6q",
174 .id = UCLASS_CLK,
175 .of_match = imx6q_clk_ids,
176 .ops = &imx6q_clk_ops,
177 .probe = imx6q_clk_probe,
178 .flags = DM_FLAG_PRE_RELOC,
179};