1763c5bd0SIcenowy Zheng /* 2763c5bd0SIcenowy Zheng * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io> 3763c5bd0SIcenowy Zheng * 4763c5bd0SIcenowy Zheng * This software is licensed under the terms of the GNU General Public 5763c5bd0SIcenowy Zheng * License version 2, as published by the Free Software Foundation, and 6763c5bd0SIcenowy Zheng * may be copied, distributed, and modified under those terms. 7763c5bd0SIcenowy Zheng * 8763c5bd0SIcenowy Zheng * This program is distributed in the hope that it will be useful, 9763c5bd0SIcenowy Zheng * but WITHOUT ANY WARRANTY; without even the implied warranty of 10763c5bd0SIcenowy Zheng * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11763c5bd0SIcenowy Zheng * GNU General Public License for more details. 12763c5bd0SIcenowy Zheng */ 13763c5bd0SIcenowy Zheng 14763c5bd0SIcenowy Zheng #include <linux/clk.h> 15763c5bd0SIcenowy Zheng #include <linux/clk-provider.h> 16763c5bd0SIcenowy Zheng #include <linux/of_address.h> 17763c5bd0SIcenowy Zheng #include <linux/of_platform.h> 18763c5bd0SIcenowy Zheng #include <linux/platform_device.h> 19763c5bd0SIcenowy Zheng #include <linux/reset.h> 20763c5bd0SIcenowy Zheng 21763c5bd0SIcenowy Zheng #include "ccu_common.h" 22763c5bd0SIcenowy Zheng #include "ccu_div.h" 23763c5bd0SIcenowy Zheng #include "ccu_gate.h" 24763c5bd0SIcenowy Zheng #include "ccu_reset.h" 25763c5bd0SIcenowy Zheng 26763c5bd0SIcenowy Zheng #include "ccu-sun8i-de2.h" 27763c5bd0SIcenowy Zheng 28763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(bus_mixer0_clk, "bus-mixer0", "bus-de", 29763c5bd0SIcenowy Zheng 0x04, BIT(0), 0); 30763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(bus_mixer1_clk, "bus-mixer1", "bus-de", 31763c5bd0SIcenowy Zheng 0x04, BIT(1), 0); 32763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(bus_wb_clk, "bus-wb", "bus-de", 33763c5bd0SIcenowy Zheng 0x04, BIT(2), 0); 34*56808da9SJernej Skrabec static SUNXI_CCU_GATE(bus_rot_clk, "bus-rot", "bus-de", 35*56808da9SJernej Skrabec 0x04, BIT(3), 0); 36763c5bd0SIcenowy Zheng 37763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(mixer0_clk, "mixer0", "mixer0-div", 38763c5bd0SIcenowy Zheng 0x00, BIT(0), CLK_SET_RATE_PARENT); 39763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(mixer1_clk, "mixer1", "mixer1-div", 40763c5bd0SIcenowy Zheng 0x00, BIT(1), CLK_SET_RATE_PARENT); 41763c5bd0SIcenowy Zheng static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div", 42763c5bd0SIcenowy Zheng 0x00, BIT(2), CLK_SET_RATE_PARENT); 43*56808da9SJernej Skrabec static SUNXI_CCU_GATE(rot_clk, "rot", "rot-div", 44*56808da9SJernej Skrabec 0x00, BIT(3), CLK_SET_RATE_PARENT); 45763c5bd0SIcenowy Zheng 46763c5bd0SIcenowy Zheng static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4, 47763c5bd0SIcenowy Zheng CLK_SET_RATE_PARENT); 4819368d99SIcenowy Zheng static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4, 4919368d99SIcenowy Zheng CLK_SET_RATE_PARENT); 50763c5bd0SIcenowy Zheng static SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4, 51763c5bd0SIcenowy Zheng CLK_SET_RATE_PARENT); 52*56808da9SJernej Skrabec static SUNXI_CCU_M(rot_div_clk, "rot-div", "de", 0x0c, 0x0c, 4, 53*56808da9SJernej Skrabec CLK_SET_RATE_PARENT); 54763c5bd0SIcenowy Zheng 55553c7d5bSMaxime Ripard static SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4, 56553c7d5bSMaxime Ripard CLK_SET_RATE_PARENT); 57553c7d5bSMaxime Ripard static SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4, 58553c7d5bSMaxime Ripard CLK_SET_RATE_PARENT); 59553c7d5bSMaxime Ripard static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4, 60553c7d5bSMaxime Ripard CLK_SET_RATE_PARENT); 61553c7d5bSMaxime Ripard 62*56808da9SJernej Skrabec static struct ccu_common *sun50i_h6_de3_clks[] = { 63*56808da9SJernej Skrabec &mixer0_clk.common, 64*56808da9SJernej Skrabec &mixer1_clk.common, 65*56808da9SJernej Skrabec &wb_clk.common, 66*56808da9SJernej Skrabec 67*56808da9SJernej Skrabec &bus_mixer0_clk.common, 68*56808da9SJernej Skrabec &bus_mixer1_clk.common, 69*56808da9SJernej Skrabec &bus_wb_clk.common, 70*56808da9SJernej Skrabec 71*56808da9SJernej Skrabec &mixer0_div_clk.common, 72*56808da9SJernej Skrabec &mixer1_div_clk.common, 73*56808da9SJernej Skrabec &wb_div_clk.common, 74*56808da9SJernej Skrabec 75*56808da9SJernej Skrabec &bus_rot_clk.common, 76*56808da9SJernej Skrabec &rot_clk.common, 77*56808da9SJernej Skrabec &rot_div_clk.common, 78*56808da9SJernej Skrabec }; 79*56808da9SJernej Skrabec 80763c5bd0SIcenowy Zheng static struct ccu_common *sun8i_a83t_de2_clks[] = { 81763c5bd0SIcenowy Zheng &mixer0_clk.common, 82763c5bd0SIcenowy Zheng &mixer1_clk.common, 83763c5bd0SIcenowy Zheng &wb_clk.common, 84763c5bd0SIcenowy Zheng 85763c5bd0SIcenowy Zheng &bus_mixer0_clk.common, 86763c5bd0SIcenowy Zheng &bus_mixer1_clk.common, 87763c5bd0SIcenowy Zheng &bus_wb_clk.common, 88763c5bd0SIcenowy Zheng 89553c7d5bSMaxime Ripard &mixer0_div_a83_clk.common, 90553c7d5bSMaxime Ripard &mixer1_div_a83_clk.common, 91553c7d5bSMaxime Ripard &wb_div_a83_clk.common, 92763c5bd0SIcenowy Zheng }; 93763c5bd0SIcenowy Zheng 9419368d99SIcenowy Zheng static struct ccu_common *sun8i_h3_de2_clks[] = { 9519368d99SIcenowy Zheng &mixer0_clk.common, 9619368d99SIcenowy Zheng &mixer1_clk.common, 9719368d99SIcenowy Zheng &wb_clk.common, 9819368d99SIcenowy Zheng 9919368d99SIcenowy Zheng &bus_mixer0_clk.common, 10019368d99SIcenowy Zheng &bus_mixer1_clk.common, 10119368d99SIcenowy Zheng &bus_wb_clk.common, 10219368d99SIcenowy Zheng 10319368d99SIcenowy Zheng &mixer0_div_clk.common, 10419368d99SIcenowy Zheng &mixer1_div_clk.common, 10519368d99SIcenowy Zheng &wb_div_clk.common, 10619368d99SIcenowy Zheng }; 10719368d99SIcenowy Zheng 108763c5bd0SIcenowy Zheng static struct ccu_common *sun8i_v3s_de2_clks[] = { 109763c5bd0SIcenowy Zheng &mixer0_clk.common, 110763c5bd0SIcenowy Zheng &wb_clk.common, 111763c5bd0SIcenowy Zheng 112763c5bd0SIcenowy Zheng &bus_mixer0_clk.common, 113763c5bd0SIcenowy Zheng &bus_wb_clk.common, 114763c5bd0SIcenowy Zheng 115763c5bd0SIcenowy Zheng &mixer0_div_clk.common, 116763c5bd0SIcenowy Zheng &wb_div_clk.common, 117763c5bd0SIcenowy Zheng }; 118763c5bd0SIcenowy Zheng 119763c5bd0SIcenowy Zheng static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = { 120763c5bd0SIcenowy Zheng .hws = { 121763c5bd0SIcenowy Zheng [CLK_MIXER0] = &mixer0_clk.common.hw, 122763c5bd0SIcenowy Zheng [CLK_MIXER1] = &mixer1_clk.common.hw, 123763c5bd0SIcenowy Zheng [CLK_WB] = &wb_clk.common.hw, 124763c5bd0SIcenowy Zheng 125763c5bd0SIcenowy Zheng [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 126763c5bd0SIcenowy Zheng [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, 127763c5bd0SIcenowy Zheng [CLK_BUS_WB] = &bus_wb_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, 132763c5bd0SIcenowy Zheng }, 133*56808da9SJernej Skrabec .num = CLK_NUMBER_WITHOUT_ROT, 134763c5bd0SIcenowy Zheng }; 135763c5bd0SIcenowy Zheng 13619368d99SIcenowy Zheng static struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = { 13719368d99SIcenowy Zheng .hws = { 13819368d99SIcenowy Zheng [CLK_MIXER0] = &mixer0_clk.common.hw, 13919368d99SIcenowy Zheng [CLK_MIXER1] = &mixer1_clk.common.hw, 14019368d99SIcenowy Zheng [CLK_WB] = &wb_clk.common.hw, 14119368d99SIcenowy Zheng 14219368d99SIcenowy Zheng [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 14319368d99SIcenowy Zheng [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, 14419368d99SIcenowy Zheng [CLK_BUS_WB] = &bus_wb_clk.common.hw, 14519368d99SIcenowy Zheng 14619368d99SIcenowy Zheng [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, 14719368d99SIcenowy Zheng [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, 14819368d99SIcenowy Zheng [CLK_WB_DIV] = &wb_div_clk.common.hw, 14919368d99SIcenowy Zheng }, 150*56808da9SJernej Skrabec .num = CLK_NUMBER_WITHOUT_ROT, 15119368d99SIcenowy Zheng }; 15219368d99SIcenowy Zheng 153763c5bd0SIcenowy Zheng static struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = { 154763c5bd0SIcenowy Zheng .hws = { 155763c5bd0SIcenowy Zheng [CLK_MIXER0] = &mixer0_clk.common.hw, 156763c5bd0SIcenowy Zheng [CLK_WB] = &wb_clk.common.hw, 157763c5bd0SIcenowy Zheng 158763c5bd0SIcenowy Zheng [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 159763c5bd0SIcenowy Zheng [CLK_BUS_WB] = &bus_wb_clk.common.hw, 160763c5bd0SIcenowy Zheng 161763c5bd0SIcenowy Zheng [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, 162763c5bd0SIcenowy Zheng [CLK_WB_DIV] = &wb_div_clk.common.hw, 163763c5bd0SIcenowy Zheng }, 164*56808da9SJernej Skrabec .num = CLK_NUMBER_WITHOUT_ROT, 165*56808da9SJernej Skrabec }; 166*56808da9SJernej Skrabec 167*56808da9SJernej Skrabec static struct clk_hw_onecell_data sun50i_h6_de3_hw_clks = { 168*56808da9SJernej Skrabec .hws = { 169*56808da9SJernej Skrabec [CLK_MIXER0] = &mixer0_clk.common.hw, 170*56808da9SJernej Skrabec [CLK_MIXER1] = &mixer1_clk.common.hw, 171*56808da9SJernej Skrabec [CLK_WB] = &wb_clk.common.hw, 172*56808da9SJernej Skrabec [CLK_ROT] = &rot_clk.common.hw, 173*56808da9SJernej Skrabec 174*56808da9SJernej Skrabec [CLK_BUS_MIXER0] = &bus_mixer0_clk.common.hw, 175*56808da9SJernej Skrabec [CLK_BUS_MIXER1] = &bus_mixer1_clk.common.hw, 176*56808da9SJernej Skrabec [CLK_BUS_WB] = &bus_wb_clk.common.hw, 177*56808da9SJernej Skrabec [CLK_BUS_ROT] = &bus_rot_clk.common.hw, 178*56808da9SJernej Skrabec 179*56808da9SJernej Skrabec [CLK_MIXER0_DIV] = &mixer0_div_clk.common.hw, 180*56808da9SJernej Skrabec [CLK_MIXER1_DIV] = &mixer1_div_clk.common.hw, 181*56808da9SJernej Skrabec [CLK_WB_DIV] = &wb_div_clk.common.hw, 182*56808da9SJernej Skrabec [CLK_ROT_DIV] = &rot_div_clk.common.hw, 183*56808da9SJernej Skrabec }, 184*56808da9SJernej Skrabec .num = CLK_NUMBER_WITH_ROT, 185763c5bd0SIcenowy Zheng }; 186763c5bd0SIcenowy Zheng 187763c5bd0SIcenowy Zheng static struct ccu_reset_map sun8i_a83t_de2_resets[] = { 188763c5bd0SIcenowy Zheng [RST_MIXER0] = { 0x08, BIT(0) }, 189763c5bd0SIcenowy Zheng /* 190763c5bd0SIcenowy Zheng * For A83T, H3 and R40, mixer1 reset line is shared with wb, so 191763c5bd0SIcenowy Zheng * only RST_WB is exported here. 192763c5bd0SIcenowy Zheng * For V3s there's just no mixer1, so it also shares this struct. 193763c5bd0SIcenowy Zheng */ 194763c5bd0SIcenowy Zheng [RST_WB] = { 0x08, BIT(2) }, 195763c5bd0SIcenowy Zheng }; 196763c5bd0SIcenowy Zheng 197763c5bd0SIcenowy Zheng static struct ccu_reset_map sun50i_a64_de2_resets[] = { 198763c5bd0SIcenowy Zheng [RST_MIXER0] = { 0x08, BIT(0) }, 199763c5bd0SIcenowy Zheng [RST_MIXER1] = { 0x08, BIT(1) }, 200763c5bd0SIcenowy Zheng [RST_WB] = { 0x08, BIT(2) }, 201763c5bd0SIcenowy Zheng }; 202763c5bd0SIcenowy Zheng 203*56808da9SJernej Skrabec static struct ccu_reset_map sun50i_h6_de3_resets[] = { 204*56808da9SJernej Skrabec [RST_MIXER0] = { 0x08, BIT(0) }, 205*56808da9SJernej Skrabec [RST_MIXER1] = { 0x08, BIT(1) }, 206*56808da9SJernej Skrabec [RST_WB] = { 0x08, BIT(2) }, 207*56808da9SJernej Skrabec [RST_ROT] = { 0x08, BIT(3) }, 208*56808da9SJernej Skrabec }; 209*56808da9SJernej Skrabec 210763c5bd0SIcenowy Zheng static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = { 211763c5bd0SIcenowy Zheng .ccu_clks = sun8i_a83t_de2_clks, 212763c5bd0SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_a83t_de2_clks), 213763c5bd0SIcenowy Zheng 214763c5bd0SIcenowy Zheng .hw_clks = &sun8i_a83t_de2_hw_clks, 215763c5bd0SIcenowy Zheng 216763c5bd0SIcenowy Zheng .resets = sun8i_a83t_de2_resets, 217763c5bd0SIcenowy Zheng .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), 218763c5bd0SIcenowy Zheng }; 219763c5bd0SIcenowy Zheng 22019368d99SIcenowy Zheng static const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = { 22119368d99SIcenowy Zheng .ccu_clks = sun8i_h3_de2_clks, 22219368d99SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks), 22319368d99SIcenowy Zheng 22419368d99SIcenowy Zheng .hw_clks = &sun8i_h3_de2_hw_clks, 22519368d99SIcenowy Zheng 22619368d99SIcenowy Zheng .resets = sun8i_a83t_de2_resets, 22719368d99SIcenowy Zheng .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), 22819368d99SIcenowy Zheng }; 22919368d99SIcenowy Zheng 230763c5bd0SIcenowy Zheng static const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = { 231cf4881c1SIcenowy Zheng .ccu_clks = sun8i_h3_de2_clks, 232cf4881c1SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_h3_de2_clks), 233763c5bd0SIcenowy Zheng 234cf4881c1SIcenowy Zheng .hw_clks = &sun8i_h3_de2_hw_clks, 235763c5bd0SIcenowy Zheng 236763c5bd0SIcenowy Zheng .resets = sun50i_a64_de2_resets, 237763c5bd0SIcenowy Zheng .num_resets = ARRAY_SIZE(sun50i_a64_de2_resets), 238763c5bd0SIcenowy Zheng }; 239763c5bd0SIcenowy Zheng 240*56808da9SJernej Skrabec static const struct sunxi_ccu_desc sun50i_h6_de3_clk_desc = { 241*56808da9SJernej Skrabec .ccu_clks = sun50i_h6_de3_clks, 242*56808da9SJernej Skrabec .num_ccu_clks = ARRAY_SIZE(sun50i_h6_de3_clks), 243*56808da9SJernej Skrabec 244*56808da9SJernej Skrabec .hw_clks = &sun50i_h6_de3_hw_clks, 245*56808da9SJernej Skrabec 246*56808da9SJernej Skrabec .resets = sun50i_h6_de3_resets, 247*56808da9SJernej Skrabec .num_resets = ARRAY_SIZE(sun50i_h6_de3_resets), 248*56808da9SJernej Skrabec }; 249*56808da9SJernej Skrabec 250763c5bd0SIcenowy Zheng static const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = { 251763c5bd0SIcenowy Zheng .ccu_clks = sun8i_v3s_de2_clks, 252763c5bd0SIcenowy Zheng .num_ccu_clks = ARRAY_SIZE(sun8i_v3s_de2_clks), 253763c5bd0SIcenowy Zheng 254763c5bd0SIcenowy Zheng .hw_clks = &sun8i_v3s_de2_hw_clks, 255763c5bd0SIcenowy Zheng 256763c5bd0SIcenowy Zheng .resets = sun8i_a83t_de2_resets, 257763c5bd0SIcenowy Zheng .num_resets = ARRAY_SIZE(sun8i_a83t_de2_resets), 258763c5bd0SIcenowy Zheng }; 259763c5bd0SIcenowy Zheng 260763c5bd0SIcenowy Zheng static int sunxi_de2_clk_probe(struct platform_device *pdev) 261763c5bd0SIcenowy Zheng { 262763c5bd0SIcenowy Zheng struct resource *res; 263763c5bd0SIcenowy Zheng struct clk *bus_clk, *mod_clk; 264763c5bd0SIcenowy Zheng struct reset_control *rstc; 265763c5bd0SIcenowy Zheng void __iomem *reg; 266763c5bd0SIcenowy Zheng const struct sunxi_ccu_desc *ccu_desc; 267763c5bd0SIcenowy Zheng int ret; 268763c5bd0SIcenowy Zheng 269763c5bd0SIcenowy Zheng ccu_desc = of_device_get_match_data(&pdev->dev); 270763c5bd0SIcenowy Zheng if (!ccu_desc) 271763c5bd0SIcenowy Zheng return -EINVAL; 272763c5bd0SIcenowy Zheng 273763c5bd0SIcenowy Zheng res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 274763c5bd0SIcenowy Zheng reg = devm_ioremap_resource(&pdev->dev, res); 275763c5bd0SIcenowy Zheng if (IS_ERR(reg)) 276763c5bd0SIcenowy Zheng return PTR_ERR(reg); 277763c5bd0SIcenowy Zheng 278763c5bd0SIcenowy Zheng bus_clk = devm_clk_get(&pdev->dev, "bus"); 279763c5bd0SIcenowy Zheng if (IS_ERR(bus_clk)) { 280763c5bd0SIcenowy Zheng ret = PTR_ERR(bus_clk); 281763c5bd0SIcenowy Zheng if (ret != -EPROBE_DEFER) 282763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret); 283763c5bd0SIcenowy Zheng return ret; 284763c5bd0SIcenowy Zheng } 285763c5bd0SIcenowy Zheng 286763c5bd0SIcenowy Zheng mod_clk = devm_clk_get(&pdev->dev, "mod"); 287763c5bd0SIcenowy Zheng if (IS_ERR(mod_clk)) { 288763c5bd0SIcenowy Zheng ret = PTR_ERR(mod_clk); 289763c5bd0SIcenowy Zheng if (ret != -EPROBE_DEFER) 290763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't get mod clk: %d\n", ret); 291763c5bd0SIcenowy Zheng return ret; 292763c5bd0SIcenowy Zheng } 293763c5bd0SIcenowy Zheng 294763c5bd0SIcenowy Zheng rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); 295763c5bd0SIcenowy Zheng if (IS_ERR(rstc)) { 2961f6d640cSWei Yongjun ret = PTR_ERR(rstc); 297763c5bd0SIcenowy Zheng if (ret != -EPROBE_DEFER) 298763c5bd0SIcenowy Zheng dev_err(&pdev->dev, 299763c5bd0SIcenowy Zheng "Couldn't get reset control: %d\n", ret); 300763c5bd0SIcenowy Zheng return ret; 301763c5bd0SIcenowy Zheng } 302763c5bd0SIcenowy Zheng 303763c5bd0SIcenowy Zheng /* The clocks need to be enabled for us to access the registers */ 304763c5bd0SIcenowy Zheng ret = clk_prepare_enable(bus_clk); 305763c5bd0SIcenowy Zheng if (ret) { 306763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret); 307763c5bd0SIcenowy Zheng return ret; 308763c5bd0SIcenowy Zheng } 309763c5bd0SIcenowy Zheng 310763c5bd0SIcenowy Zheng ret = clk_prepare_enable(mod_clk); 311763c5bd0SIcenowy Zheng if (ret) { 312763c5bd0SIcenowy Zheng dev_err(&pdev->dev, "Couldn't enable mod clk: %d\n", ret); 313763c5bd0SIcenowy Zheng goto err_disable_bus_clk; 314763c5bd0SIcenowy Zheng } 315763c5bd0SIcenowy Zheng 316763c5bd0SIcenowy Zheng /* The reset control needs to be asserted for the controls to work */ 317763c5bd0SIcenowy Zheng ret = reset_control_deassert(rstc); 318763c5bd0SIcenowy Zheng if (ret) { 319763c5bd0SIcenowy Zheng dev_err(&pdev->dev, 320763c5bd0SIcenowy Zheng "Couldn't deassert reset control: %d\n", ret); 321763c5bd0SIcenowy Zheng goto err_disable_mod_clk; 322763c5bd0SIcenowy Zheng } 323763c5bd0SIcenowy Zheng 324763c5bd0SIcenowy Zheng ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc); 325763c5bd0SIcenowy Zheng if (ret) 326763c5bd0SIcenowy Zheng goto err_assert_reset; 327763c5bd0SIcenowy Zheng 328763c5bd0SIcenowy Zheng return 0; 329763c5bd0SIcenowy Zheng 330763c5bd0SIcenowy Zheng err_assert_reset: 331763c5bd0SIcenowy Zheng reset_control_assert(rstc); 332763c5bd0SIcenowy Zheng err_disable_mod_clk: 333763c5bd0SIcenowy Zheng clk_disable_unprepare(mod_clk); 334763c5bd0SIcenowy Zheng err_disable_bus_clk: 335763c5bd0SIcenowy Zheng clk_disable_unprepare(bus_clk); 336763c5bd0SIcenowy Zheng return ret; 337763c5bd0SIcenowy Zheng } 338763c5bd0SIcenowy Zheng 339763c5bd0SIcenowy Zheng static const struct of_device_id sunxi_de2_clk_ids[] = { 340763c5bd0SIcenowy Zheng { 341763c5bd0SIcenowy Zheng .compatible = "allwinner,sun8i-a83t-de2-clk", 342763c5bd0SIcenowy Zheng .data = &sun8i_a83t_de2_clk_desc, 343763c5bd0SIcenowy Zheng }, 344763c5bd0SIcenowy Zheng { 34519368d99SIcenowy Zheng .compatible = "allwinner,sun8i-h3-de2-clk", 34619368d99SIcenowy Zheng .data = &sun8i_h3_de2_clk_desc, 34719368d99SIcenowy Zheng }, 34819368d99SIcenowy Zheng { 349763c5bd0SIcenowy Zheng .compatible = "allwinner,sun8i-v3s-de2-clk", 350763c5bd0SIcenowy Zheng .data = &sun8i_v3s_de2_clk_desc, 351763c5bd0SIcenowy Zheng }, 352763c5bd0SIcenowy Zheng { 35301951563SIcenowy Zheng .compatible = "allwinner,sun50i-a64-de2-clk", 35401951563SIcenowy Zheng .data = &sun50i_a64_de2_clk_desc, 35501951563SIcenowy Zheng }, 35601951563SIcenowy Zheng { 357763c5bd0SIcenowy Zheng .compatible = "allwinner,sun50i-h5-de2-clk", 358763c5bd0SIcenowy Zheng .data = &sun50i_a64_de2_clk_desc, 359763c5bd0SIcenowy Zheng }, 360*56808da9SJernej Skrabec { 361*56808da9SJernej Skrabec .compatible = "allwinner,sun50i-h6-de3-clk", 362*56808da9SJernej Skrabec .data = &sun50i_h6_de3_clk_desc, 363*56808da9SJernej Skrabec }, 364763c5bd0SIcenowy Zheng { } 365763c5bd0SIcenowy Zheng }; 366763c5bd0SIcenowy Zheng 367763c5bd0SIcenowy Zheng static struct platform_driver sunxi_de2_clk_driver = { 368763c5bd0SIcenowy Zheng .probe = sunxi_de2_clk_probe, 369763c5bd0SIcenowy Zheng .driver = { 370763c5bd0SIcenowy Zheng .name = "sunxi-de2-clks", 371763c5bd0SIcenowy Zheng .of_match_table = sunxi_de2_clk_ids, 372763c5bd0SIcenowy Zheng }, 373763c5bd0SIcenowy Zheng }; 374763c5bd0SIcenowy Zheng builtin_platform_driver(sunxi_de2_clk_driver); 375