18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/clk.h>
78c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
88c2ecf20Sopenharmony_ci#include <linux/of_address.h>
98c2ecf20Sopenharmony_ci#include <linux/of_platform.h>
108c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
118c2ecf20Sopenharmony_ci#include <linux/reset.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "ccu_common.h"
148c2ecf20Sopenharmony_ci#include "ccu_div.h"
158c2ecf20Sopenharmony_ci#include "ccu_gate.h"
168c2ecf20Sopenharmony_ci#include "ccu_reset.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "ccu-sun8i-de2.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(bus_mixer0_clk,	"bus-mixer0",	"bus-de",
218c2ecf20Sopenharmony_ci		      0x04, BIT(0), 0);
228c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(bus_mixer1_clk,	"bus-mixer1",	"bus-de",
238c2ecf20Sopenharmony_ci		      0x04, BIT(1), 0);
248c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(bus_wb_clk,	"bus-wb",	"bus-de",
258c2ecf20Sopenharmony_ci		      0x04, BIT(2), 0);
268c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(bus_rot_clk,	"bus-rot",	"bus-de",
278c2ecf20Sopenharmony_ci		      0x04, BIT(3), 0);
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(mixer0_clk,	"mixer0",	"mixer0-div",
308c2ecf20Sopenharmony_ci		      0x00, BIT(0), CLK_SET_RATE_PARENT);
318c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(mixer1_clk,	"mixer1",	"mixer1-div",
328c2ecf20Sopenharmony_ci		      0x00, BIT(1), CLK_SET_RATE_PARENT);
338c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(wb_clk,		"wb",		"wb-div",
348c2ecf20Sopenharmony_ci		      0x00, BIT(2), CLK_SET_RATE_PARENT);
358c2ecf20Sopenharmony_cistatic SUNXI_CCU_GATE(rot_clk,		"rot",		"rot-div",
368c2ecf20Sopenharmony_ci		      0x00, BIT(3), CLK_SET_RATE_PARENT);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
398c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
408c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
418c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
428c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(wb_div_clk, "wb-div", "de", 0x0c, 8, 4,
438c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
448c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(rot_div_clk, "rot-div", "de", 0x0c, 0x0c, 4,
458c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(mixer0_div_a83_clk, "mixer0-div", "pll-de", 0x0c, 0, 4,
488c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
498c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(mixer1_div_a83_clk, "mixer1-div", "pll-de", 0x0c, 4, 4,
508c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
518c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
528c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
538c2ecf20Sopenharmony_cistatic SUNXI_CCU_M(rot_div_a83_clk, "rot-div", "pll-de", 0x0c, 0x0c, 4,
548c2ecf20Sopenharmony_ci		   CLK_SET_RATE_PARENT);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic struct ccu_common *sun8i_a83t_de2_clks[] = {
578c2ecf20Sopenharmony_ci	&mixer0_clk.common,
588c2ecf20Sopenharmony_ci	&mixer1_clk.common,
598c2ecf20Sopenharmony_ci	&wb_clk.common,
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	&bus_mixer0_clk.common,
628c2ecf20Sopenharmony_ci	&bus_mixer1_clk.common,
638c2ecf20Sopenharmony_ci	&bus_wb_clk.common,
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	&mixer0_div_a83_clk.common,
668c2ecf20Sopenharmony_ci	&mixer1_div_a83_clk.common,
678c2ecf20Sopenharmony_ci	&wb_div_a83_clk.common,
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	&bus_rot_clk.common,
708c2ecf20Sopenharmony_ci	&rot_clk.common,
718c2ecf20Sopenharmony_ci	&rot_div_a83_clk.common,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic struct ccu_common *sun8i_h3_de2_clks[] = {
758c2ecf20Sopenharmony_ci	&mixer0_clk.common,
768c2ecf20Sopenharmony_ci	&mixer1_clk.common,
778c2ecf20Sopenharmony_ci	&wb_clk.common,
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	&bus_mixer0_clk.common,
808c2ecf20Sopenharmony_ci	&bus_mixer1_clk.common,
818c2ecf20Sopenharmony_ci	&bus_wb_clk.common,
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	&mixer0_div_clk.common,
848c2ecf20Sopenharmony_ci	&mixer1_div_clk.common,
858c2ecf20Sopenharmony_ci	&wb_div_clk.common,
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic struct ccu_common *sun8i_v3s_de2_clks[] = {
898c2ecf20Sopenharmony_ci	&mixer0_clk.common,
908c2ecf20Sopenharmony_ci	&wb_clk.common,
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	&bus_mixer0_clk.common,
938c2ecf20Sopenharmony_ci	&bus_wb_clk.common,
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	&mixer0_div_clk.common,
968c2ecf20Sopenharmony_ci	&wb_div_clk.common,
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic struct ccu_common *sun50i_a64_de2_clks[] = {
1008c2ecf20Sopenharmony_ci	&mixer0_clk.common,
1018c2ecf20Sopenharmony_ci	&mixer1_clk.common,
1028c2ecf20Sopenharmony_ci	&wb_clk.common,
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	&bus_mixer0_clk.common,
1058c2ecf20Sopenharmony_ci	&bus_mixer1_clk.common,
1068c2ecf20Sopenharmony_ci	&bus_wb_clk.common,
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	&mixer0_div_clk.common,
1098c2ecf20Sopenharmony_ci	&mixer1_div_clk.common,
1108c2ecf20Sopenharmony_ci	&wb_div_clk.common,
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	&bus_rot_clk.common,
1138c2ecf20Sopenharmony_ci	&rot_clk.common,
1148c2ecf20Sopenharmony_ci	&rot_div_clk.common,
1158c2ecf20Sopenharmony_ci};
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
1188c2ecf20Sopenharmony_ci	.hws	= {
1198c2ecf20Sopenharmony_ci		[CLK_MIXER0]		= &mixer0_clk.common.hw,
1208c2ecf20Sopenharmony_ci		[CLK_MIXER1]		= &mixer1_clk.common.hw,
1218c2ecf20Sopenharmony_ci		[CLK_WB]		= &wb_clk.common.hw,
1228c2ecf20Sopenharmony_ci		[CLK_ROT]		= &rot_clk.common.hw,
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
1258c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
1268c2ecf20Sopenharmony_ci		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
1278c2ecf20Sopenharmony_ci		[CLK_BUS_ROT]		= &bus_rot_clk.common.hw,
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci		[CLK_MIXER0_DIV]	= &mixer0_div_a83_clk.common.hw,
1308c2ecf20Sopenharmony_ci		[CLK_MIXER1_DIV]	= &mixer1_div_a83_clk.common.hw,
1318c2ecf20Sopenharmony_ci		[CLK_WB_DIV]		= &wb_div_a83_clk.common.hw,
1328c2ecf20Sopenharmony_ci		[CLK_ROT_DIV]		= &rot_div_a83_clk.common.hw,
1338c2ecf20Sopenharmony_ci	},
1348c2ecf20Sopenharmony_ci	.num	= CLK_NUMBER_WITH_ROT,
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic struct clk_hw_onecell_data sun8i_h3_de2_hw_clks = {
1388c2ecf20Sopenharmony_ci	.hws	= {
1398c2ecf20Sopenharmony_ci		[CLK_MIXER0]		= &mixer0_clk.common.hw,
1408c2ecf20Sopenharmony_ci		[CLK_MIXER1]		= &mixer1_clk.common.hw,
1418c2ecf20Sopenharmony_ci		[CLK_WB]		= &wb_clk.common.hw,
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
1448c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
1458c2ecf20Sopenharmony_ci		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci		[CLK_MIXER0_DIV]	= &mixer0_div_clk.common.hw,
1488c2ecf20Sopenharmony_ci		[CLK_MIXER1_DIV]	= &mixer1_div_clk.common.hw,
1498c2ecf20Sopenharmony_ci		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
1508c2ecf20Sopenharmony_ci	},
1518c2ecf20Sopenharmony_ci	.num	= CLK_NUMBER_WITHOUT_ROT,
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic struct clk_hw_onecell_data sun8i_v3s_de2_hw_clks = {
1558c2ecf20Sopenharmony_ci	.hws	= {
1568c2ecf20Sopenharmony_ci		[CLK_MIXER0]		= &mixer0_clk.common.hw,
1578c2ecf20Sopenharmony_ci		[CLK_WB]		= &wb_clk.common.hw,
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
1608c2ecf20Sopenharmony_ci		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci		[CLK_MIXER0_DIV]	= &mixer0_div_clk.common.hw,
1638c2ecf20Sopenharmony_ci		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
1648c2ecf20Sopenharmony_ci	},
1658c2ecf20Sopenharmony_ci	.num	= CLK_NUMBER_WITHOUT_ROT,
1668c2ecf20Sopenharmony_ci};
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = {
1698c2ecf20Sopenharmony_ci	.hws	= {
1708c2ecf20Sopenharmony_ci		[CLK_MIXER0]		= &mixer0_clk.common.hw,
1718c2ecf20Sopenharmony_ci		[CLK_MIXER1]		= &mixer1_clk.common.hw,
1728c2ecf20Sopenharmony_ci		[CLK_WB]		= &wb_clk.common.hw,
1738c2ecf20Sopenharmony_ci		[CLK_ROT]		= &rot_clk.common.hw,
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER0]	= &bus_mixer0_clk.common.hw,
1768c2ecf20Sopenharmony_ci		[CLK_BUS_MIXER1]	= &bus_mixer1_clk.common.hw,
1778c2ecf20Sopenharmony_ci		[CLK_BUS_WB]		= &bus_wb_clk.common.hw,
1788c2ecf20Sopenharmony_ci		[CLK_BUS_ROT]		= &bus_rot_clk.common.hw,
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci		[CLK_MIXER0_DIV]	= &mixer0_div_clk.common.hw,
1818c2ecf20Sopenharmony_ci		[CLK_MIXER1_DIV]	= &mixer1_div_clk.common.hw,
1828c2ecf20Sopenharmony_ci		[CLK_WB_DIV]		= &wb_div_clk.common.hw,
1838c2ecf20Sopenharmony_ci		[CLK_ROT_DIV]		= &rot_div_clk.common.hw,
1848c2ecf20Sopenharmony_ci	},
1858c2ecf20Sopenharmony_ci	.num	= CLK_NUMBER_WITH_ROT,
1868c2ecf20Sopenharmony_ci};
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cistatic struct ccu_reset_map sun8i_a83t_de2_resets[] = {
1898c2ecf20Sopenharmony_ci	[RST_MIXER0]	= { 0x08, BIT(0) },
1908c2ecf20Sopenharmony_ci	/*
1918c2ecf20Sopenharmony_ci	 * Mixer1 reset line is shared with wb, so only RST_WB is
1928c2ecf20Sopenharmony_ci	 * exported here.
1938c2ecf20Sopenharmony_ci	 */
1948c2ecf20Sopenharmony_ci	[RST_WB]	= { 0x08, BIT(2) },
1958c2ecf20Sopenharmony_ci	[RST_ROT]	= { 0x08, BIT(3) },
1968c2ecf20Sopenharmony_ci};
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic struct ccu_reset_map sun8i_h3_de2_resets[] = {
1998c2ecf20Sopenharmony_ci	[RST_MIXER0]	= { 0x08, BIT(0) },
2008c2ecf20Sopenharmony_ci	/*
2018c2ecf20Sopenharmony_ci	 * Mixer1 reset line is shared with wb, so only RST_WB is
2028c2ecf20Sopenharmony_ci	 * exported here.
2038c2ecf20Sopenharmony_ci	 * V3s doesn't have mixer1, so it also shares this struct.
2048c2ecf20Sopenharmony_ci	 */
2058c2ecf20Sopenharmony_ci	[RST_WB]	= { 0x08, BIT(2) },
2068c2ecf20Sopenharmony_ci};
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic struct ccu_reset_map sun50i_a64_de2_resets[] = {
2098c2ecf20Sopenharmony_ci	[RST_MIXER0]	= { 0x08, BIT(0) },
2108c2ecf20Sopenharmony_ci	[RST_MIXER1]	= { 0x08, BIT(1) },
2118c2ecf20Sopenharmony_ci	[RST_WB]	= { 0x08, BIT(2) },
2128c2ecf20Sopenharmony_ci	[RST_ROT]	= { 0x08, BIT(3) },
2138c2ecf20Sopenharmony_ci};
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic struct ccu_reset_map sun50i_h5_de2_resets[] = {
2168c2ecf20Sopenharmony_ci	[RST_MIXER0]	= { 0x08, BIT(0) },
2178c2ecf20Sopenharmony_ci	[RST_MIXER1]	= { 0x08, BIT(1) },
2188c2ecf20Sopenharmony_ci	[RST_WB]	= { 0x08, BIT(2) },
2198c2ecf20Sopenharmony_ci};
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
2228c2ecf20Sopenharmony_ci	.ccu_clks	= sun8i_a83t_de2_clks,
2238c2ecf20Sopenharmony_ci	.num_ccu_clks	= ARRAY_SIZE(sun8i_a83t_de2_clks),
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	.hw_clks	= &sun8i_a83t_de2_hw_clks,
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	.resets		= sun8i_a83t_de2_resets,
2288c2ecf20Sopenharmony_ci	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
2298c2ecf20Sopenharmony_ci};
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic const struct sunxi_ccu_desc sun8i_h3_de2_clk_desc = {
2328c2ecf20Sopenharmony_ci	.ccu_clks	= sun8i_h3_de2_clks,
2338c2ecf20Sopenharmony_ci	.num_ccu_clks	= ARRAY_SIZE(sun8i_h3_de2_clks),
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	.hw_clks	= &sun8i_h3_de2_hw_clks,
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	.resets		= sun8i_h3_de2_resets,
2388c2ecf20Sopenharmony_ci	.num_resets	= ARRAY_SIZE(sun8i_h3_de2_resets),
2398c2ecf20Sopenharmony_ci};
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic const struct sunxi_ccu_desc sun8i_r40_de2_clk_desc = {
2428c2ecf20Sopenharmony_ci	.ccu_clks	= sun50i_a64_de2_clks,
2438c2ecf20Sopenharmony_ci	.num_ccu_clks	= ARRAY_SIZE(sun50i_a64_de2_clks),
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	.hw_clks	= &sun50i_a64_de2_hw_clks,
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	.resets		= sun8i_a83t_de2_resets,
2488c2ecf20Sopenharmony_ci	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
2498c2ecf20Sopenharmony_ci};
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic const struct sunxi_ccu_desc sun8i_v3s_de2_clk_desc = {
2528c2ecf20Sopenharmony_ci	.ccu_clks	= sun8i_v3s_de2_clks,
2538c2ecf20Sopenharmony_ci	.num_ccu_clks	= ARRAY_SIZE(sun8i_v3s_de2_clks),
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	.hw_clks	= &sun8i_v3s_de2_hw_clks,
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	.resets		= sun8i_a83t_de2_resets,
2588c2ecf20Sopenharmony_ci	.num_resets	= ARRAY_SIZE(sun8i_a83t_de2_resets),
2598c2ecf20Sopenharmony_ci};
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistatic const struct sunxi_ccu_desc sun50i_a64_de2_clk_desc = {
2628c2ecf20Sopenharmony_ci	.ccu_clks	= sun50i_a64_de2_clks,
2638c2ecf20Sopenharmony_ci	.num_ccu_clks	= ARRAY_SIZE(sun50i_a64_de2_clks),
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	.hw_clks	= &sun50i_a64_de2_hw_clks,
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	.resets		= sun50i_a64_de2_resets,
2688c2ecf20Sopenharmony_ci	.num_resets	= ARRAY_SIZE(sun50i_a64_de2_resets),
2698c2ecf20Sopenharmony_ci};
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic const struct sunxi_ccu_desc sun50i_h5_de2_clk_desc = {
2728c2ecf20Sopenharmony_ci	.ccu_clks	= sun8i_h3_de2_clks,
2738c2ecf20Sopenharmony_ci	.num_ccu_clks	= ARRAY_SIZE(sun8i_h3_de2_clks),
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	.hw_clks	= &sun8i_h3_de2_hw_clks,
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	.resets		= sun50i_h5_de2_resets,
2788c2ecf20Sopenharmony_ci	.num_resets	= ARRAY_SIZE(sun50i_h5_de2_resets),
2798c2ecf20Sopenharmony_ci};
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_cistatic int sunxi_de2_clk_probe(struct platform_device *pdev)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct resource *res;
2848c2ecf20Sopenharmony_ci	struct clk *bus_clk, *mod_clk;
2858c2ecf20Sopenharmony_ci	struct reset_control *rstc;
2868c2ecf20Sopenharmony_ci	void __iomem *reg;
2878c2ecf20Sopenharmony_ci	const struct sunxi_ccu_desc *ccu_desc;
2888c2ecf20Sopenharmony_ci	int ret;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	ccu_desc = of_device_get_match_data(&pdev->dev);
2918c2ecf20Sopenharmony_ci	if (!ccu_desc)
2928c2ecf20Sopenharmony_ci		return -EINVAL;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2958c2ecf20Sopenharmony_ci	reg = devm_ioremap_resource(&pdev->dev, res);
2968c2ecf20Sopenharmony_ci	if (IS_ERR(reg))
2978c2ecf20Sopenharmony_ci		return PTR_ERR(reg);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	bus_clk = devm_clk_get(&pdev->dev, "bus");
3008c2ecf20Sopenharmony_ci	if (IS_ERR(bus_clk)) {
3018c2ecf20Sopenharmony_ci		ret = PTR_ERR(bus_clk);
3028c2ecf20Sopenharmony_ci		if (ret != -EPROBE_DEFER)
3038c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Couldn't get bus clk: %d\n", ret);
3048c2ecf20Sopenharmony_ci		return ret;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	mod_clk = devm_clk_get(&pdev->dev, "mod");
3088c2ecf20Sopenharmony_ci	if (IS_ERR(mod_clk)) {
3098c2ecf20Sopenharmony_ci		ret = PTR_ERR(mod_clk);
3108c2ecf20Sopenharmony_ci		if (ret != -EPROBE_DEFER)
3118c2ecf20Sopenharmony_ci			dev_err(&pdev->dev, "Couldn't get mod clk: %d\n", ret);
3128c2ecf20Sopenharmony_ci		return ret;
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
3168c2ecf20Sopenharmony_ci	if (IS_ERR(rstc)) {
3178c2ecf20Sopenharmony_ci		ret = PTR_ERR(rstc);
3188c2ecf20Sopenharmony_ci		if (ret != -EPROBE_DEFER)
3198c2ecf20Sopenharmony_ci			dev_err(&pdev->dev,
3208c2ecf20Sopenharmony_ci				"Couldn't get reset control: %d\n", ret);
3218c2ecf20Sopenharmony_ci		return ret;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	/* The clocks need to be enabled for us to access the registers */
3258c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(bus_clk);
3268c2ecf20Sopenharmony_ci	if (ret) {
3278c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);
3288c2ecf20Sopenharmony_ci		return ret;
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(mod_clk);
3328c2ecf20Sopenharmony_ci	if (ret) {
3338c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Couldn't enable mod clk: %d\n", ret);
3348c2ecf20Sopenharmony_ci		goto err_disable_bus_clk;
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	/* The reset control needs to be asserted for the controls to work */
3388c2ecf20Sopenharmony_ci	ret = reset_control_deassert(rstc);
3398c2ecf20Sopenharmony_ci	if (ret) {
3408c2ecf20Sopenharmony_ci		dev_err(&pdev->dev,
3418c2ecf20Sopenharmony_ci			"Couldn't deassert reset control: %d\n", ret);
3428c2ecf20Sopenharmony_ci		goto err_disable_mod_clk;
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, ccu_desc);
3468c2ecf20Sopenharmony_ci	if (ret)
3478c2ecf20Sopenharmony_ci		goto err_assert_reset;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	return 0;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_cierr_assert_reset:
3528c2ecf20Sopenharmony_ci	reset_control_assert(rstc);
3538c2ecf20Sopenharmony_cierr_disable_mod_clk:
3548c2ecf20Sopenharmony_ci	clk_disable_unprepare(mod_clk);
3558c2ecf20Sopenharmony_cierr_disable_bus_clk:
3568c2ecf20Sopenharmony_ci	clk_disable_unprepare(bus_clk);
3578c2ecf20Sopenharmony_ci	return ret;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic const struct of_device_id sunxi_de2_clk_ids[] = {
3618c2ecf20Sopenharmony_ci	{
3628c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun8i-a83t-de2-clk",
3638c2ecf20Sopenharmony_ci		.data = &sun8i_a83t_de2_clk_desc,
3648c2ecf20Sopenharmony_ci	},
3658c2ecf20Sopenharmony_ci	{
3668c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun8i-h3-de2-clk",
3678c2ecf20Sopenharmony_ci		.data = &sun8i_h3_de2_clk_desc,
3688c2ecf20Sopenharmony_ci	},
3698c2ecf20Sopenharmony_ci	{
3708c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun8i-r40-de2-clk",
3718c2ecf20Sopenharmony_ci		.data = &sun8i_r40_de2_clk_desc,
3728c2ecf20Sopenharmony_ci	},
3738c2ecf20Sopenharmony_ci	{
3748c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun8i-v3s-de2-clk",
3758c2ecf20Sopenharmony_ci		.data = &sun8i_v3s_de2_clk_desc,
3768c2ecf20Sopenharmony_ci	},
3778c2ecf20Sopenharmony_ci	{
3788c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun50i-a64-de2-clk",
3798c2ecf20Sopenharmony_ci		.data = &sun50i_a64_de2_clk_desc,
3808c2ecf20Sopenharmony_ci	},
3818c2ecf20Sopenharmony_ci	{
3828c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun50i-h5-de2-clk",
3838c2ecf20Sopenharmony_ci		.data = &sun50i_h5_de2_clk_desc,
3848c2ecf20Sopenharmony_ci	},
3858c2ecf20Sopenharmony_ci	{
3868c2ecf20Sopenharmony_ci		.compatible = "allwinner,sun50i-h6-de3-clk",
3878c2ecf20Sopenharmony_ci		.data = &sun50i_h5_de2_clk_desc,
3888c2ecf20Sopenharmony_ci	},
3898c2ecf20Sopenharmony_ci	{ }
3908c2ecf20Sopenharmony_ci};
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic struct platform_driver sunxi_de2_clk_driver = {
3938c2ecf20Sopenharmony_ci	.probe	= sunxi_de2_clk_probe,
3948c2ecf20Sopenharmony_ci	.driver	= {
3958c2ecf20Sopenharmony_ci		.name	= "sunxi-de2-clks",
3968c2ecf20Sopenharmony_ci		.of_match_table	= sunxi_de2_clk_ids,
3978c2ecf20Sopenharmony_ci	},
3988c2ecf20Sopenharmony_ci};
3998c2ecf20Sopenharmony_cibuiltin_platform_driver(sunxi_de2_clk_driver);
400