19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2763c5bd0SIcenowy Zheng /* 3763c5bd0SIcenowy Zheng * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io> 4763c5bd0SIcenowy Zheng */ 5763c5bd0SIcenowy Zheng 6763c5bd0SIcenowy Zheng #include <linux/clk.h> 7763c5bd0SIcenowy Zheng #include <linux/clk-provider.h> 8763c5bd0SIcenowy Zheng #include <linux/of_address.h> 9763c5bd0SIcenowy Zheng #include <linux/of_platform.h> 10763c5bd0SIcenowy Zheng #include <linux/platform_device.h> 11763c5bd0SIcenowy Zheng #include <linux/reset.h> 12763c5bd0SIcenowy Zheng 13763c5bd0SIcenowy Zheng #include "ccu_common.h" 14763c5bd0SIcenowy Zheng #include "ccu_div.h" 15763c5bd0SIcenowy Zheng #include "ccu_gate.h" 16763c5bd0SIcenowy Zheng #include "ccu_reset.h" 17763c5bd0SIcenowy Zheng 18763c5bd0SIcenowy Zheng #include "ccu-sun8i-de2.h" 19763c5bd0SIcenowy Zheng 20763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(bus_mixer0_clk, "bus-mixer0", "bus-de", 21763c5bd0SIcenowy Zheng 0x04, BIT(0), 0); 22763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(bus_mixer1_clk, "bus-mixer1", "bus-de", 23763c5bd0SIcenowy Zheng 0x04, BIT(1), 0); 24763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(bus_wb_clk, "bus-wb", "bus-de", 25763c5bd0SIcenowy Zheng 0x04, BIT(2), 0); 2656808da9SJernej Skrabec static SUNXI_CCU_GATE(bus_rot_clk, "bus-rot", "bus-de", 2756808da9SJernej Skrabec 0x04, BIT(3), 0); 28763c5bd0SIcenowy Zheng 29763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(mixer0_clk, "mixer0", "mixer0-div", 30763c5bd0SIcenowy Zheng 0x00, BIT(0), CLK_SET_RATE_PARENT); 31763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(mixer1_clk, "mixer1", "mixer1-div", 32763c5bd0SIcenowy Zheng 0x00, BIT(1), CLK_SET_RATE_PARENT); 33763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div", 34763c5bd0SIcenowy Zheng 0x00, BIT(2), CLK_SET_RATE_PARENT); 3556808da9SJernej Skrabec static SUNXI_CCU_GATE(rot_clk, "rot", "rot-div", 3656808da9SJernej Skrabec 0x00, BIT(3), CLK_SET_RATE_PARENT); 37763c5bd0SIcenowy Zheng 38763c5bd0SIcenowy Zheng static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4, 39763c5bd0SIcenowy Zheng CLK_SET_RATE_PARENT); 4019368d99SIcenowy Zheng static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4, 4119368d99SIcenowy Zheng CLK_SET_RATE_PARENT); 42763c5bd0SIcenowy Zheng static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4, 43763c5bd0SIcenowy Zheng CLK_SET_RATE_PARENT); 4456808da9SJernej Skrabec static SUNXI_CCU_M(rot_div_clk, "rot-div", "de", 0x0c, 0x0c, 4, 4556808da9SJernej Skrabec CLK_SET_RATE_PARENT); 46763c5bd0SIcenowy Zheng 47553c7d5bSMaxime Ripard static SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4, 48553c7d5bSMaxime Ripard CLK_SET_RATE_PARENT); 49553c7d5bSMaxime Ripard static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4, 50553c7d5bSMaxime Ripard CLK_SET_RATE_PARENT); 51553c7d5bSMaxime Ripard static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4, 52553c7d5bSMaxime Ripard CLK_SET_RATE_PARENT); 53b0bfba90SJernej Skrabec static SUNXI_CCU_M(rot_div_a83_clk, "rot-div", "pll-de", 0x0c, 0x0c, 4, 54b0bfba90SJernej Skrabec CLK_SET_RATE_PARENT); 55553c7d5bSMaxime Ripard 56763c5bd0SIcenowy Zheng static struct ccu_common *sun8i_a83t_de2_clks[] = { 57763c5bd0SIcenowy Zheng &mixer0_clk.common, 58763c5bd0SIcenowy Zheng &mixer1_clk.common, 59763c5bd0SIcenowy Zheng &wb_clk.common, 60763c5bd0SIcenowy Zheng 61763c5bd0SIcenowy Zheng &bus_mixer0_clk.common, 62763c5bd0SIcenowy Zheng &bus_mixer1_clk.common, 63763c5bd0SIcenowy Zheng &bus_wb_clk.common, 64763c5bd0SIcenowy Zheng 65553c7d5bSMaxime Ripard &mixer0_div_a83_clk.common, 66553c7d5bSMaxime Ripard &mixer1_div_a83_clk.common, 67553c7d5bSMaxime Ripard &wb_div_a83_clk.common, 68b0bfba90SJernej Skrabec 69b0bfba90SJernej Skrabec &bus_rot_clk.common, 70b0bfba90SJernej Skrabec &rot_clk.common, 71b0bfba90SJernej Skrabec &rot_div_a83_clk.common, 72763c5bd0SIcenowy Zheng }; 73763c5bd0SIcenowy Zheng 7419368d99SIcenowy Zheng static struct ccu_common *sun8i_h3_de2_clks[] = { 7519368d99SIcenowy Zheng &mixer0_clk.common, 7619368d99SIcenowy Zheng &mixer1_clk.common, 7719368d99SIcenowy Zheng &wb_clk.common, 7819368d99SIcenowy Zheng 7919368d99SIcenowy Zheng &bus_mixer0_clk.common, 8019368d99SIcenowy Zheng &bus_mixer1_clk.common, 8119368d99SIcenowy Zheng &bus_wb_clk.common, 8219368d99SIcenowy Zheng 8319368d99SIcenowy Zheng &mixer0_div_clk.common, 8419368d99SIcenowy Zheng &mixer1_div_clk.common, 8519368d99SIcenowy Zheng &wb_div_clk.common, 8619368d99SIcenowy Zheng }; 8719368d99SIcenowy Zheng 88763c5bd0SIcenowy Zheng static struct ccu_common *sun8i_v3s_de2_clks[] = { 89763c5bd0SIcenowy Zheng &mixer0_clk.common, 90763c5bd0SIcenowy Zheng &wb_clk.common, 91763c5bd0SIcenowy Zheng 92763c5bd0SIcenowy Zheng &bus_mixer0_clk.common, 93763c5bd0SIcenowy Zheng &bus_wb_clk.common, 94763c5bd0SIcenowy Zheng 95763c5bd0SIcenowy Zheng &mixer0_div_clk.common, 96763c5bd0SIcenowy Zheng &wb_div_clk.common, 97763c5bd0SIcenowy Zheng }; 98763c5bd0SIcenowy Zheng 99b4bbce66SJernej Skrabec static struct ccu_common *sun50i_a64_de2_clks[] = { 100b4bbce66SJernej Skrabec &mixer0_clk.common, 101b4bbce66SJernej Skrabec &mixer1_clk.common, 102b4bbce66SJernej Skrabec &wb_clk.common, 103b4bbce66SJernej Skrabec 104b4bbce66SJernej Skrabec &bus_mixer0_clk.common, 105b4bbce66SJernej Skrabec &bus_mixer1_clk.common, 106b4bbce66SJernej Skrabec &bus_wb_clk.common, 107b4bbce66SJernej Skrabec 108b4bbce66SJernej Skrabec &mixer0_div_clk.common, 109b4bbce66SJernej Skrabec &mixer1_div_clk.common, 110b4bbce66SJernej Skrabec &wb_div_clk.common, 111b4bbce66SJernej Skrabec 112b4bbce66SJernej Skrabec &bus_rot_clk.common, 113b4bbce66SJernej Skrabec &rot_clk.common, 114b4bbce66SJernej Skrabec &rot_div_clk.common, 115b4bbce66SJernej Skrabec }; 116b4bbce66SJernej Skrabec 117763c5bd0SIcenowy Zheng static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = { 118763c5bd0SIcenowy Zheng .hws = { 119763c5bd0SIcenowy Zheng [CLK_MIXER0] = &mixer0_clk.common.hw, 120763c5bd0SIcenowy Zheng [CLK_MIXER1] = &mixer1_clk.common.hw, 121763c5bd0SIcenowy Zheng [CLK_WB] = &wb_clk.common.hw, 122b0bfba90SJernej Skrabec [CLK_ROT] = &rot_clk.common.hw, 123763c5bd0SIcenowy Zheng 124763c5bd0SIcenowy Zheng [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 125763c5bd0SIcenowy Zheng [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, 126763c5bd0SIcenowy Zheng [CLK_BUS_WB] = &bus_wb_clk.common.hw, 127b0bfba90SJernej Skrabec [CLK_BUS_ROT] = &bus_rot_clk.common.hw, 128763c5bd0SIcenowy Zheng 129553c7d5bSMaxime Ripard [CLK_MIXER0_DIV] = &mixer0_div_a83_clk.common.hw, 130553c7d5bSMaxime Ripard [CLK_MIXER1_DIV] = &mixer1_div_a83_clk.common.hw, 131553c7d5bSMaxime Ripard [CLK_WB_DIV] = &wb_div_a83_clk.common.hw, 132b0bfba90SJernej Skrabec [CLK_ROT_DIV] = &rot_div_a83_clk.common.hw, 133763c5bd0SIcenowy Zheng }, 134b0bfba90SJernej Skrabec .num = CLK_NUMBER_WITH_ROT, 135763c5bd0SIcenowy Zheng }; 136763c5bd0SIcenowy Zheng 13719368d99SIcenowy Zheng static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = { 13819368d99SIcenowy Zheng .hws = { 13919368d99SIcenowy Zheng [CLK_MIXER0] = &mixer0_clk.common.hw, 14019368d99SIcenowy Zheng [CLK_MIXER1] = &mixer1_clk.common.hw, 14119368d99SIcenowy Zheng [CLK_WB] = &wb_clk.common.hw, 14219368d99SIcenowy Zheng 14319368d99SIcenowy Zheng [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 14419368d99SIcenowy Zheng [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, 14519368d99SIcenowy Zheng [CLK_BUS_WB] = &bus_wb_clk.common.hw, 14619368d99SIcenowy Zheng 14719368d99SIcenowy Zheng [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, 14819368d99SIcenowy Zheng [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, 14919368d99SIcenowy Zheng [CLK_WB_DIV] = &wb_div_clk.common.hw, 15019368d99SIcenowy Zheng }, 15156808da9SJernej Skrabec .num = CLK_NUMBER_WITHOUT_ROT, 15219368d99SIcenowy Zheng }; 15319368d99SIcenowy Zheng 154763c5bd0SIcenowy Zheng static struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = { 155763c5bd0SIcenowy Zheng .hws = { 156763c5bd0SIcenowy Zheng [CLK_MIXER0] = &mixer0_clk.common.hw, 157763c5bd0SIcenowy Zheng [CLK_WB] = &wb_clk.common.hw, 158763c5bd0SIcenowy Zheng 159763c5bd0SIcenowy Zheng [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 160763c5bd0SIcenowy Zheng [CLK_BUS_WB] = &bus_wb_clk.common.hw, 161763c5bd0SIcenowy Zheng 162763c5bd0SIcenowy Zheng [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, 163763c5bd0SIcenowy Zheng [CLK_WB_DIV] = &wb_div_clk.common.hw, 164763c5bd0SIcenowy Zheng }, 16556808da9SJernej Skrabec .num = CLK_NUMBER_WITHOUT_ROT, 16656808da9SJernej Skrabec }; 16756808da9SJernej Skrabec 168b4bbce66SJernej Skrabec static struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = { 169b4bbce66SJernej Skrabec .hws = { 170b4bbce66SJernej Skrabec [CLK_MIXER0] = &mixer0_clk.common.hw, 171b4bbce66SJernej Skrabec [CLK_MIXER1] = &mixer1_clk.common.hw, 172b4bbce66SJernej Skrabec [CLK_WB] = &wb_clk.common.hw, 173b4bbce66SJernej Skrabec [CLK_ROT] = &rot_clk.common.hw, 174b4bbce66SJernej Skrabec 175b4bbce66SJernej Skrabec [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 176b4bbce66SJernej Skrabec [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, 177b4bbce66SJernej Skrabec [CLK_BUS_WB] = &bus_wb_clk.common.hw, 178b4bbce66SJernej Skrabec [CLK_BUS_ROT] = &bus_rot_clk.common.hw, 179b4bbce66SJernej Skrabec 180b4bbce66SJernej Skrabec [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, 181b4bbce66SJernej Skrabec [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, 182b4bbce66SJernej Skrabec [CLK_WB_DIV] = &wb_div_clk.common.hw, 183b4bbce66SJernej Skrabec [CLK_ROT_DIV] = &rot_div_clk.common.hw, 184b4bbce66SJernej Skrabec }, 185b4bbce66SJernej Skrabec .num = CLK_NUMBER_WITH_ROT, 186b4bbce66SJernej Skrabec }; 187b4bbce66SJernej Skrabec 188763c5bd0SIcenowy Zheng static struct ccu_reset_map sun8i_a83t_de2_resets[] = { 189763c5bd0SIcenowy Zheng [RST_MIXER0] = { 0x08, BIT(0) }, 190763c5bd0SIcenowy Zheng /* 1918f9b11a3SJernej Skrabec * Mixer1 reset line is shared with wb, so only RST_WB is 1928f9b11a3SJernej Skrabec * exported here. 1938f9b11a3SJernej Skrabec */ 1948f9b11a3SJernej Skrabec [RST_WB] = { 0x08, BIT(2) }, 195b0bfba90SJernej Skrabec [RST_ROT] = { 0x08, BIT(3) }, 1968f9b11a3SJernej Skrabec }; 1978f9b11a3SJernej Skrabec 1988f9b11a3SJernej Skrabec static struct ccu_reset_map sun8i_h3_de2_resets[] = { 1998f9b11a3SJernej Skrabec [RST_MIXER0] = { 0x08, BIT(0) }, 2008f9b11a3SJernej Skrabec /* 2018f9b11a3SJernej Skrabec * Mixer1 reset line is shared with wb, so only RST_WB is 2028f9b11a3SJernej Skrabec * exported here. 2038f9b11a3SJernej Skrabec * V3s doesn't have mixer1, so it also shares this struct. 204763c5bd0SIcenowy Zheng */ 205763c5bd0SIcenowy Zheng [RST_WB] = { 0x08, BIT(2) }, 206763c5bd0SIcenowy Zheng }; 207763c5bd0SIcenowy Zheng 208763c5bd0SIcenowy Zheng static struct ccu_reset_map sun50i_a64_de2_resets[] = { 209763c5bd0SIcenowy Zheng [RST_MIXER0] = { 0x08, BIT(0) }, 210763c5bd0SIcenowy Zheng [RST_MIXER1] = { 0x08, BIT(1) }, 211763c5bd0SIcenowy Zheng [RST_WB] = { 0x08, BIT(2) }, 212b4bbce66SJernej Skrabec [RST_ROT] = { 0x08, BIT(3) }, 213763c5bd0SIcenowy Zheng }; 214763c5bd0SIcenowy Zheng 2152b48dcb7SJernej Skrabec static struct ccu_reset_map sun50i_h5_de2_resets[] = { 2162b48dcb7SJernej Skrabec [RST_MIXER0] = { 0x08, BIT(0) }, 2172b48dcb7SJernej Skrabec [RST_MIXER1] = { 0x08, BIT(1) }, 2182b48dcb7SJernej Skrabec [RST_WB] = { 0x08, BIT(2) }, 2192b48dcb7SJernej Skrabec }; 2202b48dcb7SJernej Skrabec 221763c5bd0SIcenowy Zheng static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = { 222763c5bd0SIcenowy Zheng .ccu_clks = sun8i_a83t_de2_clks, 223763c5bd0SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_a83t_de2_clks), 224763c5bd0SIcenowy Zheng 225763c5bd0SIcenowy Zheng .hw_clks = &sun8i_a83t_de2_hw_clks, 226763c5bd0SIcenowy Zheng 227763c5bd0SIcenowy Zheng .resets = sun8i_a83t_de2_resets, 228763c5bd0SIcenowy Zheng .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), 229763c5bd0SIcenowy Zheng }; 230763c5bd0SIcenowy Zheng 23119368d99SIcenowy Zheng static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = { 23219368d99SIcenowy Zheng .ccu_clks = sun8i_h3_de2_clks, 23319368d99SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks), 23419368d99SIcenowy Zheng 23519368d99SIcenowy Zheng .hw_clks = &sun8i_h3_de2_hw_clks, 23619368d99SIcenowy Zheng 2378f9b11a3SJernej Skrabec .resets = sun8i_h3_de2_resets, 2388f9b11a3SJernej Skrabec .num_resets = ARRAY_SIZE(sun8i_h3_de2_resets), 23919368d99SIcenowy Zheng }; 24019368d99SIcenowy Zheng 241*11d0c436SJernej Skrabec static const struct sunxi_ccu_desc sun8i_r40_de2_clk_desc = { 242*11d0c436SJernej Skrabec .ccu_clks = sun50i_a64_de2_clks, 243*11d0c436SJernej Skrabec .num_ccu_clks = ARRAY_SIZE(sun50i_a64_de2_clks), 244*11d0c436SJernej Skrabec 245*11d0c436SJernej Skrabec .hw_clks = &sun50i_a64_de2_hw_clks, 246*11d0c436SJernej Skrabec 247*11d0c436SJernej Skrabec .resets = sun8i_a83t_de2_resets, 248*11d0c436SJernej Skrabec .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), 249*11d0c436SJernej Skrabec }; 250*11d0c436SJernej Skrabec 251763c5bd0SIcenowy Zheng static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { 252b4bbce66SJernej Skrabec .ccu_clks = sun50i_a64_de2_clks, 253b4bbce66SJernej Skrabec .num_ccu_clks = ARRAY_SIZE(sun50i_a64_de2_clks), 254763c5bd0SIcenowy Zheng 255b4bbce66SJernej Skrabec .hw_clks = &sun50i_a64_de2_hw_clks, 256763c5bd0SIcenowy Zheng 257763c5bd0SIcenowy Zheng .resets = sun50i_a64_de2_resets, 258763c5bd0SIcenowy Zheng .num_resets = ARRAY_SIZE(sun50i_a64_de2_resets), 259763c5bd0SIcenowy Zheng }; 260763c5bd0SIcenowy Zheng 2612b48dcb7SJernej Skrabec static const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = { 2622b48dcb7SJernej Skrabec .ccu_clks = sun8i_h3_de2_clks, 2632b48dcb7SJernej Skrabec .num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks), 2642b48dcb7SJernej Skrabec 2652b48dcb7SJernej Skrabec .hw_clks = &sun8i_h3_de2_hw_clks, 2662b48dcb7SJernej Skrabec 2672b48dcb7SJernej Skrabec .resets = sun50i_h5_de2_resets, 2682b48dcb7SJernej Skrabec .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets), 2692b48dcb7SJernej Skrabec }; 2702b48dcb7SJernej Skrabec 271763c5bd0SIcenowy Zheng static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = { 272763c5bd0SIcenowy Zheng .ccu_clks = sun8i_v3s_de2_clks, 273763c5bd0SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_v3s_de2_clks), 274763c5bd0SIcenowy Zheng 275763c5bd0SIcenowy Zheng .hw_clks = &sun8i_v3s_de2_hw_clks, 276763c5bd0SIcenowy Zheng 2778f9b11a3SJernej Skrabec .resets = sun8i_h3_de2_resets, 2788f9b11a3SJernej Skrabec .num_resets = ARRAY_SIZE(sun8i_h3_de2_resets), 279763c5bd0SIcenowy Zheng }; 280763c5bd0SIcenowy Zheng 281763c5bd0SIcenowy Zheng static int sunxi_de2_clk_probe(struct platform_device *pdev) 282763c5bd0SIcenowy Zheng { 283763c5bd0SIcenowy Zheng struct resource *res; 284763c5bd0SIcenowy Zheng struct clk *bus_clk, *mod_clk; 285763c5bd0SIcenowy Zheng struct reset_control *rstc; 286763c5bd0SIcenowy Zheng void __iomem *reg; 287763c5bd0SIcenowy Zheng const struct sunxi_ccu_desc *ccu_desc; 288763c5bd0SIcenowy Zheng int ret; 289763c5bd0SIcenowy Zheng 290763c5bd0SIcenowy Zheng ccu_desc = of_device_get_match_data(&pdev->dev); 291763c5bd0SIcenowy Zheng if (!ccu_desc) 292763c5bd0SIcenowy Zheng return -EINVAL; 293763c5bd0SIcenowy Zheng 294763c5bd0SIcenowy Zheng res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 295763c5bd0SIcenowy Zheng reg = devm_ioremap_resource(&pdev->dev, res); 296763c5bd0SIcenowy Zheng if (IS_ERR(reg)) 297763c5bd0SIcenowy Zheng return PTR_ERR(reg); 298763c5bd0SIcenowy Zheng 299763c5bd0SIcenowy Zheng bus_clk = devm_clk_get(&pdev->dev, "bus"); 300763c5bd0SIcenowy Zheng if (IS_ERR(bus_clk)) { 301763c5bd0SIcenowy Zheng ret = PTR_ERR(bus_clk); 302763c5bd0SIcenowy Zheng if (ret != -EPROBE_DEFER) 303763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret); 304763c5bd0SIcenowy Zheng return ret; 305763c5bd0SIcenowy Zheng } 306763c5bd0SIcenowy Zheng 307763c5bd0SIcenowy Zheng mod_clk = devm_clk_get(&pdev->dev, "mod"); 308763c5bd0SIcenowy Zheng if (IS_ERR(mod_clk)) { 309763c5bd0SIcenowy Zheng ret = PTR_ERR(mod_clk); 310763c5bd0SIcenowy Zheng if (ret != -EPROBE_DEFER) 311763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't get mod clk: %d\n", ret); 312763c5bd0SIcenowy Zheng return ret; 313763c5bd0SIcenowy Zheng } 314763c5bd0SIcenowy Zheng 315763c5bd0SIcenowy Zheng rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 316763c5bd0SIcenowy Zheng if (IS_ERR(rstc)) { 3171f6d640cSWei Yongjun ret = PTR_ERR(rstc); 318763c5bd0SIcenowy Zheng if (ret != -EPROBE_DEFER) 319763c5bd0SIcenowy Zheng dev_err(&pdev->dev, 320763c5bd0SIcenowy Zheng "Couldn't get reset control: %d\n", ret); 321763c5bd0SIcenowy Zheng return ret; 322763c5bd0SIcenowy Zheng } 323763c5bd0SIcenowy Zheng 324763c5bd0SIcenowy Zheng /* The clocks need to be enabled for us to access the registers */ 325763c5bd0SIcenowy Zheng ret = clk_prepare_enable(bus_clk); 326763c5bd0SIcenowy Zheng if (ret) { 327763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret); 328763c5bd0SIcenowy Zheng return ret; 329763c5bd0SIcenowy Zheng } 330763c5bd0SIcenowy Zheng 331763c5bd0SIcenowy Zheng ret = clk_prepare_enable(mod_clk); 332763c5bd0SIcenowy Zheng if (ret) { 333763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't enable mod clk: %d\n", ret); 334763c5bd0SIcenowy Zheng goto err_disable_bus_clk; 335763c5bd0SIcenowy Zheng } 336763c5bd0SIcenowy Zheng 337763c5bd0SIcenowy Zheng /* The reset control needs to be asserted for the controls to work */ 338763c5bd0SIcenowy Zheng ret = reset_control_deassert(rstc); 339763c5bd0SIcenowy Zheng if (ret) { 340763c5bd0SIcenowy Zheng dev_err(&pdev->dev, 341763c5bd0SIcenowy Zheng "Couldn't deassert reset control: %d\n", ret); 342763c5bd0SIcenowy Zheng goto err_disable_mod_clk; 343763c5bd0SIcenowy Zheng } 344763c5bd0SIcenowy Zheng 345763c5bd0SIcenowy Zheng ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc); 346763c5bd0SIcenowy Zheng if (ret) 347763c5bd0SIcenowy Zheng goto err_assert_reset; 348763c5bd0SIcenowy Zheng 349763c5bd0SIcenowy Zheng return 0; 350763c5bd0SIcenowy Zheng 351763c5bd0SIcenowy Zheng err_assert_reset: 352763c5bd0SIcenowy Zheng reset_control_assert(rstc); 353763c5bd0SIcenowy Zheng err_disable_mod_clk: 354763c5bd0SIcenowy Zheng clk_disable_unprepare(mod_clk); 355763c5bd0SIcenowy Zheng err_disable_bus_clk: 356763c5bd0SIcenowy Zheng clk_disable_unprepare(bus_clk); 357763c5bd0SIcenowy Zheng return ret; 358763c5bd0SIcenowy Zheng } 359763c5bd0SIcenowy Zheng 360763c5bd0SIcenowy Zheng static const struct of_device_id sunxi_de2_clk_ids[] = { 361763c5bd0SIcenowy Zheng { 362763c5bd0SIcenowy Zheng .compatible = "allwinner,sun8i-a83t-de2-clk", 363763c5bd0SIcenowy Zheng .data = &sun8i_a83t_de2_clk_desc, 364763c5bd0SIcenowy Zheng }, 365763c5bd0SIcenowy Zheng { 36619368d99SIcenowy Zheng .compatible = "allwinner,sun8i-h3-de2-clk", 36719368d99SIcenowy Zheng .data = &sun8i_h3_de2_clk_desc, 36819368d99SIcenowy Zheng }, 36919368d99SIcenowy Zheng { 370*11d0c436SJernej Skrabec .compatible = "allwinner,sun8i-r40-de2-clk", 371*11d0c436SJernej Skrabec .data = &sun8i_r40_de2_clk_desc, 372*11d0c436SJernej Skrabec }, 373*11d0c436SJernej Skrabec { 374763c5bd0SIcenowy Zheng .compatible = "allwinner,sun8i-v3s-de2-clk", 375763c5bd0SIcenowy Zheng .data = &sun8i_v3s_de2_clk_desc, 376763c5bd0SIcenowy Zheng }, 377763c5bd0SIcenowy Zheng { 37801951563SIcenowy Zheng .compatible = "allwinner,sun50i-a64-de2-clk", 37901951563SIcenowy Zheng .data = &sun50i_a64_de2_clk_desc, 38001951563SIcenowy Zheng }, 38101951563SIcenowy Zheng { 382763c5bd0SIcenowy Zheng .compatible = "allwinner,sun50i-h5-de2-clk", 3832b48dcb7SJernej Skrabec .data = &sun50i_h5_de2_clk_desc, 384763c5bd0SIcenowy Zheng }, 38556808da9SJernej Skrabec { 38656808da9SJernej Skrabec .compatible = "allwinner,sun50i-h6-de3-clk", 38775250eb7SJernej Skrabec .data = &sun50i_h5_de2_clk_desc, 38856808da9SJernej Skrabec }, 389763c5bd0SIcenowy Zheng { } 390763c5bd0SIcenowy Zheng }; 391763c5bd0SIcenowy Zheng 392763c5bd0SIcenowy Zheng static struct platform_driver sunxi_de2_clk_driver = { 393763c5bd0SIcenowy Zheng .probe = sunxi_de2_clk_probe, 394763c5bd0SIcenowy Zheng .driver = { 395763c5bd0SIcenowy Zheng .name = "sunxi-de2-clks", 396763c5bd0SIcenowy Zheng .of_match_table = sunxi_de2_clk_ids, 397763c5bd0SIcenowy Zheng }, 398763c5bd0SIcenowy Zheng }; 399763c5bd0SIcenowy Zheng builtin_platform_driver(sunxi_de2_clk_driver); 400