xref: /openbmc/linux/drivers/clk/clk-versaclock3.c (revision acfdcaeed6e6b954f5b99210b8f05cbc18200945)
16e9aff55SBiju Das // SPDX-License-Identifier: GPL-2.0+
26e9aff55SBiju Das /*
36e9aff55SBiju Das  * Driver for Renesas Versaclock 3
46e9aff55SBiju Das  *
56e9aff55SBiju Das  * Copyright (C) 2023 Renesas Electronics Corp.
66e9aff55SBiju Das  */
76e9aff55SBiju Das 
86e9aff55SBiju Das #include <linux/clk-provider.h>
96e9aff55SBiju Das #include <linux/i2c.h>
106e9aff55SBiju Das #include <linux/limits.h>
116e9aff55SBiju Das #include <linux/module.h>
126e9aff55SBiju Das #include <linux/regmap.h>
136e9aff55SBiju Das 
146e9aff55SBiju Das #define NUM_CONFIG_REGISTERS		37
156e9aff55SBiju Das 
166e9aff55SBiju Das #define VC3_GENERAL_CTR			0x0
176e9aff55SBiju Das #define VC3_GENERAL_CTR_DIV1_SRC_SEL	BIT(3)
186e9aff55SBiju Das #define VC3_GENERAL_CTR_PLL3_REFIN_SEL	BIT(2)
196e9aff55SBiju Das 
206e9aff55SBiju Das #define VC3_PLL3_M_DIVIDER		0x3
216e9aff55SBiju Das #define VC3_PLL3_M_DIV1			BIT(7)
226e9aff55SBiju Das #define VC3_PLL3_M_DIV2			BIT(6)
236e9aff55SBiju Das #define VC3_PLL3_M_DIV(n)		((n) & GENMASK(5, 0))
246e9aff55SBiju Das 
256e9aff55SBiju Das #define VC3_PLL3_N_DIVIDER		0x4
266e9aff55SBiju Das #define VC3_PLL3_LOOP_FILTER_N_DIV_MSB	0x5
276e9aff55SBiju Das 
286e9aff55SBiju Das #define VC3_PLL3_CHARGE_PUMP_CTRL	0x6
296e9aff55SBiju Das #define VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL	BIT(7)
306e9aff55SBiju Das 
316e9aff55SBiju Das #define VC3_PLL1_CTRL_OUTDIV5		0x7
326e9aff55SBiju Das #define VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER		BIT(7)
336e9aff55SBiju Das 
346e9aff55SBiju Das #define VC3_PLL1_M_DIVIDER		0x8
356e9aff55SBiju Das #define VC3_PLL1_M_DIV1			BIT(7)
366e9aff55SBiju Das #define VC3_PLL1_M_DIV2			BIT(6)
376e9aff55SBiju Das #define VC3_PLL1_M_DIV(n)		((n) & GENMASK(5, 0))
386e9aff55SBiju Das 
396e9aff55SBiju Das #define VC3_PLL1_VCO_N_DIVIDER		0x9
406e9aff55SBiju Das #define VC3_PLL1_LOOP_FILTER_N_DIV_MSB	0x0a
416e9aff55SBiju Das 
426e9aff55SBiju Das #define VC3_OUT_DIV1_DIV2_CTRL		0xf
436e9aff55SBiju Das 
446e9aff55SBiju Das #define VC3_PLL2_FB_INT_DIV_MSB		0x10
456e9aff55SBiju Das #define VC3_PLL2_FB_INT_DIV_LSB		0x11
466e9aff55SBiju Das #define VC3_PLL2_FB_FRC_DIV_MSB		0x12
476e9aff55SBiju Das #define VC3_PLL2_FB_FRC_DIV_LSB		0x13
486e9aff55SBiju Das 
496e9aff55SBiju Das #define VC3_PLL2_M_DIVIDER		0x1a
506e9aff55SBiju Das #define VC3_PLL2_MDIV_DOUBLER		BIT(7)
516e9aff55SBiju Das #define VC3_PLL2_M_DIV1			BIT(6)
526e9aff55SBiju Das #define VC3_PLL2_M_DIV2			BIT(5)
536e9aff55SBiju Das #define VC3_PLL2_M_DIV(n)		((n) & GENMASK(4, 0))
546e9aff55SBiju Das 
556e9aff55SBiju Das #define VC3_OUT_DIV3_DIV4_CTRL		0x1b
566e9aff55SBiju Das 
576e9aff55SBiju Das #define VC3_PLL_OP_CTRL			0x1c
586e9aff55SBiju Das #define VC3_PLL_OP_CTRL_PLL2_REFIN_SEL	6
596e9aff55SBiju Das 
606e9aff55SBiju Das #define VC3_OUTPUT_CTR			0x1d
616e9aff55SBiju Das #define VC3_OUTPUT_CTR_DIV4_SRC_SEL	BIT(3)
626e9aff55SBiju Das 
636e9aff55SBiju Das #define VC3_SE2_CTRL_REG0		0x1f
646e9aff55SBiju Das #define VC3_SE2_CTRL_REG0_SE2_CLK_SEL	BIT(6)
656e9aff55SBiju Das 
666e9aff55SBiju Das #define VC3_SE3_DIFF1_CTRL_REG		0x21
676e9aff55SBiju Das #define VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL	BIT(6)
686e9aff55SBiju Das 
696e9aff55SBiju Das #define VC3_DIFF1_CTRL_REG		0x22
706e9aff55SBiju Das #define VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL	BIT(7)
716e9aff55SBiju Das 
726e9aff55SBiju Das #define VC3_DIFF2_CTRL_REG		0x23
736e9aff55SBiju Das #define VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL	BIT(7)
746e9aff55SBiju Das 
756e9aff55SBiju Das #define VC3_SE1_DIV4_CTRL		0x24
766e9aff55SBiju Das #define VC3_SE1_DIV4_CTRL_SE1_CLK_SEL	BIT(3)
776e9aff55SBiju Das 
786e9aff55SBiju Das #define VC3_PLL1_VCO_MIN		300000000UL
796e9aff55SBiju Das #define VC3_PLL1_VCO_MAX		600000000UL
806e9aff55SBiju Das 
816e9aff55SBiju Das #define VC3_PLL2_VCO_MIN		400000000UL
826e9aff55SBiju Das #define VC3_PLL2_VCO_MAX		1200000000UL
836e9aff55SBiju Das 
846e9aff55SBiju Das #define VC3_PLL3_VCO_MIN		300000000UL
856e9aff55SBiju Das #define VC3_PLL3_VCO_MAX		800000000UL
866e9aff55SBiju Das 
876e9aff55SBiju Das #define VC3_2_POW_16			(U16_MAX + 1)
886e9aff55SBiju Das #define VC3_DIV_MASK(width)		((1 << (width)) - 1)
896e9aff55SBiju Das 
906e9aff55SBiju Das enum vc3_pfd_mux {
916e9aff55SBiju Das 	VC3_PFD2_MUX,
926e9aff55SBiju Das 	VC3_PFD3_MUX,
936e9aff55SBiju Das };
946e9aff55SBiju Das 
956e9aff55SBiju Das enum vc3_pfd {
966e9aff55SBiju Das 	VC3_PFD1,
976e9aff55SBiju Das 	VC3_PFD2,
986e9aff55SBiju Das 	VC3_PFD3,
996e9aff55SBiju Das };
1006e9aff55SBiju Das 
1016e9aff55SBiju Das enum vc3_pll {
1026e9aff55SBiju Das 	VC3_PLL1,
1036e9aff55SBiju Das 	VC3_PLL2,
1046e9aff55SBiju Das 	VC3_PLL3,
1056e9aff55SBiju Das };
1066e9aff55SBiju Das 
1076e9aff55SBiju Das enum vc3_div_mux {
1086e9aff55SBiju Das 	VC3_DIV1_MUX,
1096e9aff55SBiju Das 	VC3_DIV3_MUX,
1106e9aff55SBiju Das 	VC3_DIV4_MUX,
1116e9aff55SBiju Das };
1126e9aff55SBiju Das 
1136e9aff55SBiju Das enum vc3_div {
1146e9aff55SBiju Das 	VC3_DIV1,
1156e9aff55SBiju Das 	VC3_DIV2,
1166e9aff55SBiju Das 	VC3_DIV3,
1176e9aff55SBiju Das 	VC3_DIV4,
1186e9aff55SBiju Das 	VC3_DIV5,
1196e9aff55SBiju Das };
1206e9aff55SBiju Das 
1216e9aff55SBiju Das enum vc3_clk {
1226e9aff55SBiju Das 	VC3_REF,
1236dcf03bcSBiju Das 	VC3_SE1,
1246dcf03bcSBiju Das 	VC3_SE2,
1256dcf03bcSBiju Das 	VC3_SE3,
1266dcf03bcSBiju Das 	VC3_DIFF1,
1276dcf03bcSBiju Das 	VC3_DIFF2,
1286e9aff55SBiju Das };
1296e9aff55SBiju Das 
130*eec11486SBiju Das enum vc3_clk_mux {
131*eec11486SBiju Das 	VC3_SE1_MUX = VC3_SE1 - 1,
132*eec11486SBiju Das 	VC3_SE2_MUX = VC3_SE2 - 1,
133*eec11486SBiju Das 	VC3_SE3_MUX = VC3_SE3 - 1,
134*eec11486SBiju Das 	VC3_DIFF1_MUX = VC3_DIFF1 - 1,
135*eec11486SBiju Das 	VC3_DIFF2_MUX = VC3_DIFF2 - 1,
136*eec11486SBiju Das };
137*eec11486SBiju Das 
1386e9aff55SBiju Das struct vc3_clk_data {
1396e9aff55SBiju Das 	u8 offs;
1406e9aff55SBiju Das 	u8 bitmsk;
1416e9aff55SBiju Das };
1426e9aff55SBiju Das 
1436e9aff55SBiju Das struct vc3_pfd_data {
1446e9aff55SBiju Das 	u8 num;
1456e9aff55SBiju Das 	u8 offs;
1466e9aff55SBiju Das 	u8 mdiv1_bitmsk;
1476e9aff55SBiju Das 	u8 mdiv2_bitmsk;
1486e9aff55SBiju Das };
1496e9aff55SBiju Das 
1506e9aff55SBiju Das struct vc3_pll_data {
1516e9aff55SBiju Das 	u8 num;
1526e9aff55SBiju Das 	u8 int_div_msb_offs;
1536e9aff55SBiju Das 	u8 int_div_lsb_offs;
1546e9aff55SBiju Das 	unsigned long vco_min;
1556e9aff55SBiju Das 	unsigned long vco_max;
1566e9aff55SBiju Das };
1576e9aff55SBiju Das 
1586e9aff55SBiju Das struct vc3_div_data {
1596e9aff55SBiju Das 	u8 offs;
1606e9aff55SBiju Das 	const struct clk_div_table *table;
1616e9aff55SBiju Das 	u8 shift;
1626e9aff55SBiju Das 	u8 width;
1636e9aff55SBiju Das 	u8 flags;
1646e9aff55SBiju Das };
1656e9aff55SBiju Das 
1666e9aff55SBiju Das struct vc3_hw_data {
1676e9aff55SBiju Das 	struct clk_hw hw;
1686e9aff55SBiju Das 	struct regmap *regmap;
1696e9aff55SBiju Das 	const void *data;
1706e9aff55SBiju Das 
1716e9aff55SBiju Das 	u32 div_int;
1726e9aff55SBiju Das 	u32 div_frc;
1736e9aff55SBiju Das };
1746e9aff55SBiju Das 
1756e9aff55SBiju Das static const struct clk_div_table div1_divs[] = {
1766e9aff55SBiju Das 	{ .val = 0, .div = 1, }, { .val = 1, .div = 4, },
1776e9aff55SBiju Das 	{ .val = 2, .div = 5, }, { .val = 3, .div = 6, },
1786e9aff55SBiju Das 	{ .val = 4, .div = 2, }, { .val = 5, .div = 8, },
1796e9aff55SBiju Das 	{ .val = 6, .div = 10, }, { .val = 7, .div = 12, },
1806e9aff55SBiju Das 	{ .val = 8, .div = 4, }, { .val = 9, .div = 16, },
1816e9aff55SBiju Das 	{ .val = 10, .div = 20, }, { .val = 11, .div = 24, },
1826e9aff55SBiju Das 	{ .val = 12, .div = 8, }, { .val = 13, .div = 32, },
1836e9aff55SBiju Das 	{ .val = 14, .div = 40, }, { .val = 15, .div = 48, },
1846e9aff55SBiju Das 	{}
1856e9aff55SBiju Das };
1866e9aff55SBiju Das 
1876e9aff55SBiju Das static const struct clk_div_table div245_divs[] = {
1886e9aff55SBiju Das 	{ .val = 0, .div = 1, }, { .val = 1, .div = 3, },
1896e9aff55SBiju Das 	{ .val = 2, .div = 5, }, { .val = 3, .div = 10, },
1906e9aff55SBiju Das 	{ .val = 4, .div = 2, }, { .val = 5, .div = 6, },
1916e9aff55SBiju Das 	{ .val = 6, .div = 10, }, { .val = 7, .div = 20, },
1926e9aff55SBiju Das 	{ .val = 8, .div = 4, }, { .val = 9, .div = 12, },
1936e9aff55SBiju Das 	{ .val = 10, .div = 20, }, { .val = 11, .div = 40, },
1946e9aff55SBiju Das 	{ .val = 12, .div = 5, }, { .val = 13, .div = 15, },
1956e9aff55SBiju Das 	{ .val = 14, .div = 25, }, { .val = 15, .div = 50, },
1966e9aff55SBiju Das 	{}
1976e9aff55SBiju Das };
1986e9aff55SBiju Das 
1996e9aff55SBiju Das static const struct clk_div_table div3_divs[] = {
2006e9aff55SBiju Das 	{ .val = 0, .div = 1, }, { .val = 1, .div = 3, },
2016e9aff55SBiju Das 	{ .val = 2, .div = 5, }, { .val = 3, .div = 10, },
2026e9aff55SBiju Das 	{ .val = 4, .div = 2, }, { .val = 5, .div = 6, },
2036e9aff55SBiju Das 	{ .val = 6, .div = 10, }, { .val = 7, .div = 20, },
2046e9aff55SBiju Das 	{ .val = 8, .div = 4, }, { .val = 9, .div = 12, },
2056e9aff55SBiju Das 	{ .val = 10, .div = 20, }, { .val = 11, .div = 40, },
2066e9aff55SBiju Das 	{ .val = 12, .div = 8, }, { .val = 13, .div = 24, },
2076e9aff55SBiju Das 	{ .val = 14, .div = 40, }, { .val = 15, .div = 80, },
2086e9aff55SBiju Das 	{}
2096e9aff55SBiju Das };
2106e9aff55SBiju Das 
2116e9aff55SBiju Das static struct clk_hw *clk_out[6];
2126e9aff55SBiju Das 
vc3_pfd_mux_get_parent(struct clk_hw * hw)2136e9aff55SBiju Das static unsigned char vc3_pfd_mux_get_parent(struct clk_hw *hw)
2146e9aff55SBiju Das {
2156e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
2166e9aff55SBiju Das 	const struct vc3_clk_data *pfd_mux = vc3->data;
2176e9aff55SBiju Das 	u32 src;
2186e9aff55SBiju Das 
2196e9aff55SBiju Das 	regmap_read(vc3->regmap, pfd_mux->offs, &src);
2206e9aff55SBiju Das 
2216e9aff55SBiju Das 	return !!(src & pfd_mux->bitmsk);
2226e9aff55SBiju Das }
2236e9aff55SBiju Das 
vc3_pfd_mux_set_parent(struct clk_hw * hw,u8 index)2246e9aff55SBiju Das static int vc3_pfd_mux_set_parent(struct clk_hw *hw, u8 index)
2256e9aff55SBiju Das {
2266e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
2276e9aff55SBiju Das 	const struct vc3_clk_data *pfd_mux = vc3->data;
2286e9aff55SBiju Das 
2296e9aff55SBiju Das 	regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk,
2306e9aff55SBiju Das 			   index ? pfd_mux->bitmsk : 0);
2316e9aff55SBiju Das 	return 0;
2326e9aff55SBiju Das }
2336e9aff55SBiju Das 
2346e9aff55SBiju Das static const struct clk_ops vc3_pfd_mux_ops = {
2356e9aff55SBiju Das 	.determine_rate = clk_hw_determine_rate_no_reparent,
2366e9aff55SBiju Das 	.set_parent = vc3_pfd_mux_set_parent,
2376e9aff55SBiju Das 	.get_parent = vc3_pfd_mux_get_parent,
2386e9aff55SBiju Das };
2396e9aff55SBiju Das 
vc3_pfd_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)2406e9aff55SBiju Das static unsigned long vc3_pfd_recalc_rate(struct clk_hw *hw,
2416e9aff55SBiju Das 					 unsigned long parent_rate)
2426e9aff55SBiju Das {
2436e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
2446e9aff55SBiju Das 	const struct vc3_pfd_data *pfd = vc3->data;
2456e9aff55SBiju Das 	unsigned int prediv, premul;
2466e9aff55SBiju Das 	unsigned long rate;
2476e9aff55SBiju Das 	u8 mdiv;
2486e9aff55SBiju Das 
2496e9aff55SBiju Das 	regmap_read(vc3->regmap, pfd->offs, &prediv);
2506e9aff55SBiju Das 	if (pfd->num == VC3_PFD1) {
2516e9aff55SBiju Das 		/* The bypass_prediv is set, PLL fed from Ref_in directly. */
2526e9aff55SBiju Das 		if (prediv & pfd->mdiv1_bitmsk) {
2536e9aff55SBiju Das 			/* check doubler is set or not */
2546e9aff55SBiju Das 			regmap_read(vc3->regmap, VC3_PLL1_CTRL_OUTDIV5, &premul);
2556e9aff55SBiju Das 			if (premul & VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER)
2566e9aff55SBiju Das 				parent_rate *= 2;
2576e9aff55SBiju Das 			return parent_rate;
2586e9aff55SBiju Das 		}
2596e9aff55SBiju Das 		mdiv = VC3_PLL1_M_DIV(prediv);
2606e9aff55SBiju Das 	} else if (pfd->num == VC3_PFD2) {
2616e9aff55SBiju Das 		/* The bypass_prediv is set, PLL fed from Ref_in directly. */
2626e9aff55SBiju Das 		if (prediv & pfd->mdiv1_bitmsk) {
2636e9aff55SBiju Das 			regmap_read(vc3->regmap, VC3_PLL2_M_DIVIDER, &premul);
2646e9aff55SBiju Das 			/* check doubler is set or not */
2656e9aff55SBiju Das 			if (premul & VC3_PLL2_MDIV_DOUBLER)
2666e9aff55SBiju Das 				parent_rate *= 2;
2676e9aff55SBiju Das 			return parent_rate;
2686e9aff55SBiju Das 		}
2696e9aff55SBiju Das 
2706e9aff55SBiju Das 		mdiv = VC3_PLL2_M_DIV(prediv);
2716e9aff55SBiju Das 	} else {
2726e9aff55SBiju Das 		/* The bypass_prediv is set, PLL fed from Ref_in directly. */
2736e9aff55SBiju Das 		if (prediv & pfd->mdiv1_bitmsk)
2746e9aff55SBiju Das 			return parent_rate;
2756e9aff55SBiju Das 
2766e9aff55SBiju Das 		mdiv = VC3_PLL3_M_DIV(prediv);
2776e9aff55SBiju Das 	}
2786e9aff55SBiju Das 
2796e9aff55SBiju Das 	if (prediv & pfd->mdiv2_bitmsk)
2806e9aff55SBiju Das 		rate = parent_rate / 2;
2816e9aff55SBiju Das 	else
2826e9aff55SBiju Das 		rate = parent_rate / mdiv;
2836e9aff55SBiju Das 
2846e9aff55SBiju Das 	return rate;
2856e9aff55SBiju Das }
2866e9aff55SBiju Das 
vc3_pfd_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)2876e9aff55SBiju Das static long vc3_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
2886e9aff55SBiju Das 			       unsigned long *parent_rate)
2896e9aff55SBiju Das {
2906e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
2916e9aff55SBiju Das 	const struct vc3_pfd_data *pfd = vc3->data;
2926e9aff55SBiju Das 	unsigned long idiv;
2936e9aff55SBiju Das 
2946e9aff55SBiju Das 	/* PLL cannot operate with input clock above 50 MHz. */
2956e9aff55SBiju Das 	if (rate > 50000000)
2966e9aff55SBiju Das 		return -EINVAL;
2976e9aff55SBiju Das 
2986e9aff55SBiju Das 	/* CLKIN within range of PLL input, feed directly to PLL. */
2996e9aff55SBiju Das 	if (*parent_rate <= 50000000)
3006e9aff55SBiju Das 		return *parent_rate;
3016e9aff55SBiju Das 
3026e9aff55SBiju Das 	idiv = DIV_ROUND_UP(*parent_rate, rate);
3036e9aff55SBiju Das 	if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) {
3046e9aff55SBiju Das 		if (idiv > 63)
3056e9aff55SBiju Das 			return -EINVAL;
3066e9aff55SBiju Das 	} else {
3076e9aff55SBiju Das 		if (idiv > 31)
3086e9aff55SBiju Das 			return -EINVAL;
3096e9aff55SBiju Das 	}
3106e9aff55SBiju Das 
3116e9aff55SBiju Das 	return *parent_rate / idiv;
3126e9aff55SBiju Das }
3136e9aff55SBiju Das 
vc3_pfd_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)3146e9aff55SBiju Das static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
3156e9aff55SBiju Das 			    unsigned long parent_rate)
3166e9aff55SBiju Das {
3176e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
3186e9aff55SBiju Das 	const struct vc3_pfd_data *pfd = vc3->data;
3196e9aff55SBiju Das 	unsigned long idiv;
3206e9aff55SBiju Das 	u8 div;
3216e9aff55SBiju Das 
3226e9aff55SBiju Das 	/* CLKIN within range of PLL input, feed directly to PLL. */
3236e9aff55SBiju Das 	if (parent_rate <= 50000000) {
3246e9aff55SBiju Das 		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk,
3256e9aff55SBiju Das 				   pfd->mdiv1_bitmsk);
3266e9aff55SBiju Das 		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0);
3276e9aff55SBiju Das 		return 0;
3286e9aff55SBiju Das 	}
3296e9aff55SBiju Das 
3306e9aff55SBiju Das 	idiv = DIV_ROUND_UP(parent_rate, rate);
3316e9aff55SBiju Das 	/* We have dedicated div-2 predivider. */
3326e9aff55SBiju Das 	if (idiv == 2) {
3336e9aff55SBiju Das 		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk,
3346e9aff55SBiju Das 				   pfd->mdiv2_bitmsk);
3356e9aff55SBiju Das 		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0);
3366e9aff55SBiju Das 	} else {
3376e9aff55SBiju Das 		if (pfd->num == VC3_PFD1)
3386e9aff55SBiju Das 			div = VC3_PLL1_M_DIV(idiv);
3396e9aff55SBiju Das 		else if (pfd->num == VC3_PFD2)
3406e9aff55SBiju Das 			div = VC3_PLL2_M_DIV(idiv);
3416e9aff55SBiju Das 		else
3426e9aff55SBiju Das 			div = VC3_PLL3_M_DIV(idiv);
3436e9aff55SBiju Das 
3446e9aff55SBiju Das 		regmap_write(vc3->regmap, pfd->offs, div);
3456e9aff55SBiju Das 	}
3466e9aff55SBiju Das 
3476e9aff55SBiju Das 	return 0;
3486e9aff55SBiju Das }
3496e9aff55SBiju Das 
3506e9aff55SBiju Das static const struct clk_ops vc3_pfd_ops = {
3516e9aff55SBiju Das 	.recalc_rate = vc3_pfd_recalc_rate,
3526e9aff55SBiju Das 	.round_rate = vc3_pfd_round_rate,
3536e9aff55SBiju Das 	.set_rate = vc3_pfd_set_rate,
3546e9aff55SBiju Das };
3556e9aff55SBiju Das 
vc3_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)3566e9aff55SBiju Das static unsigned long vc3_pll_recalc_rate(struct clk_hw *hw,
3576e9aff55SBiju Das 					 unsigned long parent_rate)
3586e9aff55SBiju Das {
3596e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
3606e9aff55SBiju Das 	const struct vc3_pll_data *pll = vc3->data;
3616e9aff55SBiju Das 	u32 div_int, div_frc, val;
3626e9aff55SBiju Das 	unsigned long rate;
3636e9aff55SBiju Das 
3646e9aff55SBiju Das 	regmap_read(vc3->regmap, pll->int_div_msb_offs, &val);
3656e9aff55SBiju Das 	div_int = (val & GENMASK(2, 0)) << 8;
3666e9aff55SBiju Das 	regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val);
3676e9aff55SBiju Das 	div_int |= val;
3686e9aff55SBiju Das 
3696e9aff55SBiju Das 	if (pll->num == VC3_PLL2) {
3706e9aff55SBiju Das 		regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val);
3716e9aff55SBiju Das 		div_frc = val << 8;
3726e9aff55SBiju Das 		regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val);
3736e9aff55SBiju Das 		div_frc |= val;
3746e9aff55SBiju Das 		rate = (parent_rate *
3756e9aff55SBiju Das 			(div_int * VC3_2_POW_16 + div_frc) / VC3_2_POW_16);
3766e9aff55SBiju Das 	} else {
3776e9aff55SBiju Das 		rate = parent_rate * div_int;
3786e9aff55SBiju Das 	}
3796e9aff55SBiju Das 
3806e9aff55SBiju Das 	return rate;
3816e9aff55SBiju Das }
3826e9aff55SBiju Das 
vc3_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)3836e9aff55SBiju Das static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate,
3846e9aff55SBiju Das 			       unsigned long *parent_rate)
3856e9aff55SBiju Das {
3866e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
3876e9aff55SBiju Das 	const struct vc3_pll_data *pll = vc3->data;
3886e9aff55SBiju Das 	u64 div_frc;
3896e9aff55SBiju Das 
3906e9aff55SBiju Das 	if (rate < pll->vco_min)
3916e9aff55SBiju Das 		rate = pll->vco_min;
3926e9aff55SBiju Das 	if (rate > pll->vco_max)
3936e9aff55SBiju Das 		rate = pll->vco_max;
3946e9aff55SBiju Das 
3956e9aff55SBiju Das 	vc3->div_int = rate / *parent_rate;
3966e9aff55SBiju Das 
3976e9aff55SBiju Das 	if (pll->num == VC3_PLL2) {
3986e9aff55SBiju Das 		if (vc3->div_int > 0x7ff)
3996e9aff55SBiju Das 			rate = *parent_rate * 0x7ff;
4006e9aff55SBiju Das 
4016e9aff55SBiju Das 		/* Determine best fractional part, which is 16 bit wide */
4026e9aff55SBiju Das 		div_frc = rate % *parent_rate;
4036e9aff55SBiju Das 		div_frc *= BIT(16) - 1;
4046e9aff55SBiju Das 
405576418e3SBiju Das 		vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX);
4066e9aff55SBiju Das 		rate = (*parent_rate *
407576418e3SBiju Das 			(vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16);
4086e9aff55SBiju Das 	} else {
4096e9aff55SBiju Das 		rate = *parent_rate * vc3->div_int;
4106e9aff55SBiju Das 	}
4116e9aff55SBiju Das 
4126e9aff55SBiju Das 	return rate;
4136e9aff55SBiju Das }
4146e9aff55SBiju Das 
vc3_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)4156e9aff55SBiju Das static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate,
4166e9aff55SBiju Das 			    unsigned long parent_rate)
4176e9aff55SBiju Das {
4186e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
4196e9aff55SBiju Das 	const struct vc3_pll_data *pll = vc3->data;
4206e9aff55SBiju Das 	u32 val;
4216e9aff55SBiju Das 
4226e9aff55SBiju Das 	regmap_read(vc3->regmap, pll->int_div_msb_offs, &val);
4236e9aff55SBiju Das 	val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7);
4246e9aff55SBiju Das 	regmap_write(vc3->regmap, pll->int_div_msb_offs, val);
4256e9aff55SBiju Das 	regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff);
4266e9aff55SBiju Das 
4276e9aff55SBiju Das 	if (pll->num == VC3_PLL2) {
4286e9aff55SBiju Das 		regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB,
4296e9aff55SBiju Das 			     vc3->div_frc >> 8);
4306e9aff55SBiju Das 		regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB,
4316e9aff55SBiju Das 			     vc3->div_frc & 0xff);
4326e9aff55SBiju Das 	}
4336e9aff55SBiju Das 
4346e9aff55SBiju Das 	return 0;
4356e9aff55SBiju Das }
4366e9aff55SBiju Das 
4376e9aff55SBiju Das static const struct clk_ops vc3_pll_ops = {
4386e9aff55SBiju Das 	.recalc_rate = vc3_pll_recalc_rate,
4396e9aff55SBiju Das 	.round_rate = vc3_pll_round_rate,
4406e9aff55SBiju Das 	.set_rate = vc3_pll_set_rate,
4416e9aff55SBiju Das };
4426e9aff55SBiju Das 
vc3_div_mux_get_parent(struct clk_hw * hw)4436e9aff55SBiju Das static unsigned char vc3_div_mux_get_parent(struct clk_hw *hw)
4446e9aff55SBiju Das {
4456e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
4466e9aff55SBiju Das 	const struct vc3_clk_data *div_mux = vc3->data;
4476e9aff55SBiju Das 	u32 src;
4486e9aff55SBiju Das 
4496e9aff55SBiju Das 	regmap_read(vc3->regmap, div_mux->offs, &src);
4506e9aff55SBiju Das 
4516e9aff55SBiju Das 	return !!(src & div_mux->bitmsk);
4526e9aff55SBiju Das }
4536e9aff55SBiju Das 
vc3_div_mux_set_parent(struct clk_hw * hw,u8 index)4546e9aff55SBiju Das static int vc3_div_mux_set_parent(struct clk_hw *hw, u8 index)
4556e9aff55SBiju Das {
4566e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
4576e9aff55SBiju Das 	const struct vc3_clk_data *div_mux = vc3->data;
4586e9aff55SBiju Das 
4596e9aff55SBiju Das 	regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk,
4606e9aff55SBiju Das 			   index ? div_mux->bitmsk : 0);
4616e9aff55SBiju Das 
4626e9aff55SBiju Das 	return 0;
4636e9aff55SBiju Das }
4646e9aff55SBiju Das 
4656e9aff55SBiju Das static const struct clk_ops vc3_div_mux_ops = {
4666e9aff55SBiju Das 	.determine_rate = clk_hw_determine_rate_no_reparent,
4676e9aff55SBiju Das 	.set_parent = vc3_div_mux_set_parent,
4686e9aff55SBiju Das 	.get_parent = vc3_div_mux_get_parent,
4696e9aff55SBiju Das };
4706e9aff55SBiju Das 
vc3_get_div(const struct clk_div_table * table,unsigned int val,unsigned long flag)4716e9aff55SBiju Das static unsigned int vc3_get_div(const struct clk_div_table *table,
4726e9aff55SBiju Das 				unsigned int val, unsigned long flag)
4736e9aff55SBiju Das {
4746e9aff55SBiju Das 	const struct clk_div_table *clkt;
4756e9aff55SBiju Das 
4766e9aff55SBiju Das 	for (clkt = table; clkt->div; clkt++)
4776e9aff55SBiju Das 		if (clkt->val == val)
4786e9aff55SBiju Das 			return clkt->div;
4796e9aff55SBiju Das 
4806e9aff55SBiju Das 	return 0;
4816e9aff55SBiju Das }
4826e9aff55SBiju Das 
vc3_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)4836e9aff55SBiju Das static unsigned long vc3_div_recalc_rate(struct clk_hw *hw,
4846e9aff55SBiju Das 					 unsigned long parent_rate)
4856e9aff55SBiju Das {
4866e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
4876e9aff55SBiju Das 	const struct vc3_div_data *div_data = vc3->data;
4886e9aff55SBiju Das 	unsigned int val;
4896e9aff55SBiju Das 
4906e9aff55SBiju Das 	regmap_read(vc3->regmap, div_data->offs, &val);
4916e9aff55SBiju Das 	val >>= div_data->shift;
4926e9aff55SBiju Das 	val &= VC3_DIV_MASK(div_data->width);
4936e9aff55SBiju Das 
4946e9aff55SBiju Das 	return divider_recalc_rate(hw, parent_rate, val, div_data->table,
4956e9aff55SBiju Das 				   div_data->flags, div_data->width);
4966e9aff55SBiju Das }
4976e9aff55SBiju Das 
vc3_div_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)4986e9aff55SBiju Das static long vc3_div_round_rate(struct clk_hw *hw, unsigned long rate,
4996e9aff55SBiju Das 			       unsigned long *parent_rate)
5006e9aff55SBiju Das {
5016e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
5026e9aff55SBiju Das 	const struct vc3_div_data *div_data = vc3->data;
5036e9aff55SBiju Das 	unsigned int bestdiv;
5046e9aff55SBiju Das 
5056e9aff55SBiju Das 	/* if read only, just return current value */
5066e9aff55SBiju Das 	if (div_data->flags & CLK_DIVIDER_READ_ONLY) {
5076e9aff55SBiju Das 		regmap_read(vc3->regmap, div_data->offs, &bestdiv);
5086e9aff55SBiju Das 		bestdiv >>= div_data->shift;
5096e9aff55SBiju Das 		bestdiv &= VC3_DIV_MASK(div_data->width);
5106e9aff55SBiju Das 		bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags);
5116e9aff55SBiju Das 		return DIV_ROUND_UP(*parent_rate, bestdiv);
5126e9aff55SBiju Das 	}
5136e9aff55SBiju Das 
5146e9aff55SBiju Das 	return divider_round_rate(hw, rate, parent_rate, div_data->table,
5156e9aff55SBiju Das 				  div_data->width, div_data->flags);
5166e9aff55SBiju Das }
5176e9aff55SBiju Das 
vc3_div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)5186e9aff55SBiju Das static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,
5196e9aff55SBiju Das 			    unsigned long parent_rate)
5206e9aff55SBiju Das {
5216e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
5226e9aff55SBiju Das 	const struct vc3_div_data *div_data = vc3->data;
5236e9aff55SBiju Das 	unsigned int value;
5246e9aff55SBiju Das 
5256e9aff55SBiju Das 	value = divider_get_val(rate, parent_rate, div_data->table,
5266e9aff55SBiju Das 				div_data->width, div_data->flags);
5276e9aff55SBiju Das 	regmap_update_bits(vc3->regmap, div_data->offs,
5286e9aff55SBiju Das 			   VC3_DIV_MASK(div_data->width) << div_data->shift,
5296e9aff55SBiju Das 			   value << div_data->shift);
5306e9aff55SBiju Das 	return 0;
5316e9aff55SBiju Das }
5326e9aff55SBiju Das 
5336e9aff55SBiju Das static const struct clk_ops vc3_div_ops = {
5346e9aff55SBiju Das 	.recalc_rate = vc3_div_recalc_rate,
5356e9aff55SBiju Das 	.round_rate = vc3_div_round_rate,
5366e9aff55SBiju Das 	.set_rate = vc3_div_set_rate,
5376e9aff55SBiju Das };
5386e9aff55SBiju Das 
vc3_clk_mux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)5396e9aff55SBiju Das static int vc3_clk_mux_determine_rate(struct clk_hw *hw,
5406e9aff55SBiju Das 				      struct clk_rate_request *req)
5416e9aff55SBiju Das {
5426e9aff55SBiju Das 	int ret;
5436e9aff55SBiju Das 	int frc;
5446e9aff55SBiju Das 
5456e9aff55SBiju Das 	ret = clk_mux_determine_rate_flags(hw, req, CLK_SET_RATE_PARENT);
5466e9aff55SBiju Das 	if (ret) {
5476e9aff55SBiju Das 		/* The below check is equivalent to (best_parent_rate/rate) */
5486e9aff55SBiju Das 		if (req->best_parent_rate >= req->rate) {
5496e9aff55SBiju Das 			frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate,
5506e9aff55SBiju Das 						    req->rate);
5516e9aff55SBiju Das 			req->rate *= frc;
5526e9aff55SBiju Das 			return clk_mux_determine_rate_flags(hw, req,
5536e9aff55SBiju Das 							    CLK_SET_RATE_PARENT);
5546e9aff55SBiju Das 		}
5556e9aff55SBiju Das 		ret = 0;
5566e9aff55SBiju Das 	}
5576e9aff55SBiju Das 
5586e9aff55SBiju Das 	return ret;
5596e9aff55SBiju Das }
5606e9aff55SBiju Das 
vc3_clk_mux_get_parent(struct clk_hw * hw)5616e9aff55SBiju Das static unsigned char vc3_clk_mux_get_parent(struct clk_hw *hw)
5626e9aff55SBiju Das {
5636e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
5646e9aff55SBiju Das 	const struct vc3_clk_data *clk_mux = vc3->data;
5656e9aff55SBiju Das 	u32 val;
5666e9aff55SBiju Das 
5676e9aff55SBiju Das 	regmap_read(vc3->regmap, clk_mux->offs, &val);
5686e9aff55SBiju Das 
5696e9aff55SBiju Das 	return !!(val & clk_mux->bitmsk);
5706e9aff55SBiju Das }
5716e9aff55SBiju Das 
vc3_clk_mux_set_parent(struct clk_hw * hw,u8 index)5726e9aff55SBiju Das static int vc3_clk_mux_set_parent(struct clk_hw *hw, u8 index)
5736e9aff55SBiju Das {
5746e9aff55SBiju Das 	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
5756e9aff55SBiju Das 	const struct vc3_clk_data *clk_mux = vc3->data;
5766e9aff55SBiju Das 
5776e9aff55SBiju Das 	regmap_update_bits(vc3->regmap, clk_mux->offs,
5786e9aff55SBiju Das 			   clk_mux->bitmsk, index ? clk_mux->bitmsk : 0);
5796e9aff55SBiju Das 	return 0;
5806e9aff55SBiju Das }
5816e9aff55SBiju Das 
5826e9aff55SBiju Das static const struct clk_ops vc3_clk_mux_ops = {
5836e9aff55SBiju Das 	.determine_rate = vc3_clk_mux_determine_rate,
5846e9aff55SBiju Das 	.set_parent = vc3_clk_mux_set_parent,
5856e9aff55SBiju Das 	.get_parent = vc3_clk_mux_get_parent,
5866e9aff55SBiju Das };
5876e9aff55SBiju Das 
vc3_regmap_is_writeable(struct device * dev,unsigned int reg)5886e9aff55SBiju Das static bool vc3_regmap_is_writeable(struct device *dev, unsigned int reg)
5896e9aff55SBiju Das {
5906e9aff55SBiju Das 	return true;
5916e9aff55SBiju Das }
5926e9aff55SBiju Das 
5936e9aff55SBiju Das static const struct regmap_config vc3_regmap_config = {
5946e9aff55SBiju Das 	.reg_bits = 8,
5956e9aff55SBiju Das 	.val_bits = 8,
5966e9aff55SBiju Das 	.cache_type = REGCACHE_RBTREE,
5976e9aff55SBiju Das 	.max_register = 0x24,
5986e9aff55SBiju Das 	.writeable_reg = vc3_regmap_is_writeable,
5996e9aff55SBiju Das };
6006e9aff55SBiju Das 
6016e9aff55SBiju Das static struct vc3_hw_data clk_div[5];
6026e9aff55SBiju Das 
6036e9aff55SBiju Das static const struct clk_parent_data pfd_mux_parent_data[] = {
6046e9aff55SBiju Das 	{ .index = 0, },
6056e9aff55SBiju Das 	{ .hw = &clk_div[VC3_DIV2].hw }
6066e9aff55SBiju Das };
6076e9aff55SBiju Das 
6086e9aff55SBiju Das static struct vc3_hw_data clk_pfd_mux[] = {
6096e9aff55SBiju Das 	[VC3_PFD2_MUX] = {
6106e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
6116e9aff55SBiju Das 			.offs = VC3_PLL_OP_CTRL,
6126e9aff55SBiju Das 			.bitmsk = BIT(VC3_PLL_OP_CTRL_PLL2_REFIN_SEL)
6136e9aff55SBiju Das 		},
6146e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
6156e9aff55SBiju Das 			.name = "pfd2_mux",
6166e9aff55SBiju Das 			.ops = &vc3_pfd_mux_ops,
6176e9aff55SBiju Das 			.parent_data = pfd_mux_parent_data,
6186e9aff55SBiju Das 			.num_parents = 2,
6196e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
6206e9aff55SBiju Das 		}
6216e9aff55SBiju Das 	},
6226e9aff55SBiju Das 	[VC3_PFD3_MUX] = {
6236e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
6246e9aff55SBiju Das 			.offs = VC3_GENERAL_CTR,
6256e9aff55SBiju Das 			.bitmsk = BIT(VC3_GENERAL_CTR_PLL3_REFIN_SEL)
6266e9aff55SBiju Das 		},
6276e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
6286e9aff55SBiju Das 			.name = "pfd3_mux",
6296e9aff55SBiju Das 			.ops = &vc3_pfd_mux_ops,
6306e9aff55SBiju Das 			.parent_data = pfd_mux_parent_data,
6316e9aff55SBiju Das 			.num_parents = 2,
6326e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
6336e9aff55SBiju Das 		}
6346e9aff55SBiju Das 	}
6356e9aff55SBiju Das };
6366e9aff55SBiju Das 
6376e9aff55SBiju Das static struct vc3_hw_data clk_pfd[] = {
6386e9aff55SBiju Das 	[VC3_PFD1] = {
6396e9aff55SBiju Das 		.data = &(struct vc3_pfd_data) {
6406e9aff55SBiju Das 			.num = VC3_PFD1,
6416e9aff55SBiju Das 			.offs = VC3_PLL1_M_DIVIDER,
6426e9aff55SBiju Das 			.mdiv1_bitmsk = VC3_PLL1_M_DIV1,
6436e9aff55SBiju Das 			.mdiv2_bitmsk = VC3_PLL1_M_DIV2
6446e9aff55SBiju Das 		},
6456e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
6466e9aff55SBiju Das 			.name = "pfd1",
6476e9aff55SBiju Das 			.ops = &vc3_pfd_ops,
6486e9aff55SBiju Das 			.parent_data = &(const struct clk_parent_data) {
6496e9aff55SBiju Das 				.index = 0
6506e9aff55SBiju Das 			},
6516e9aff55SBiju Das 			.num_parents = 1,
6526e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
6536e9aff55SBiju Das 		}
6546e9aff55SBiju Das 	},
6556e9aff55SBiju Das 	[VC3_PFD2] = {
6566e9aff55SBiju Das 		.data = &(struct vc3_pfd_data) {
6576e9aff55SBiju Das 			.num = VC3_PFD2,
6586e9aff55SBiju Das 			.offs = VC3_PLL2_M_DIVIDER,
6596e9aff55SBiju Das 			.mdiv1_bitmsk = VC3_PLL2_M_DIV1,
6606e9aff55SBiju Das 			.mdiv2_bitmsk = VC3_PLL2_M_DIV2
6616e9aff55SBiju Das 		},
6626e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
6636e9aff55SBiju Das 			.name = "pfd2",
6646e9aff55SBiju Das 			.ops = &vc3_pfd_ops,
6656e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
6666e9aff55SBiju Das 				&clk_pfd_mux[VC3_PFD2_MUX].hw
6676e9aff55SBiju Das 			},
6686e9aff55SBiju Das 			.num_parents = 1,
6696e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
6706e9aff55SBiju Das 		}
6716e9aff55SBiju Das 	},
6726e9aff55SBiju Das 	[VC3_PFD3] = {
6736e9aff55SBiju Das 		.data = &(struct vc3_pfd_data) {
6746e9aff55SBiju Das 			.num = VC3_PFD3,
6756e9aff55SBiju Das 			.offs = VC3_PLL3_M_DIVIDER,
6766e9aff55SBiju Das 			.mdiv1_bitmsk = VC3_PLL3_M_DIV1,
6776e9aff55SBiju Das 			.mdiv2_bitmsk = VC3_PLL3_M_DIV2
6786e9aff55SBiju Das 		},
6796e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
6806e9aff55SBiju Das 			.name = "pfd3",
6816e9aff55SBiju Das 			.ops = &vc3_pfd_ops,
6826e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
6836e9aff55SBiju Das 				&clk_pfd_mux[VC3_PFD3_MUX].hw
6846e9aff55SBiju Das 			},
6856e9aff55SBiju Das 			.num_parents = 1,
6866e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
6876e9aff55SBiju Das 		}
6886e9aff55SBiju Das 	}
6896e9aff55SBiju Das };
6906e9aff55SBiju Das 
6916e9aff55SBiju Das static struct vc3_hw_data clk_pll[] = {
6926e9aff55SBiju Das 	[VC3_PLL1] = {
6936e9aff55SBiju Das 		.data = &(struct vc3_pll_data) {
6946e9aff55SBiju Das 			.num = VC3_PLL1,
6956e9aff55SBiju Das 			.int_div_msb_offs = VC3_PLL1_LOOP_FILTER_N_DIV_MSB,
6966e9aff55SBiju Das 			.int_div_lsb_offs = VC3_PLL1_VCO_N_DIVIDER,
6976e9aff55SBiju Das 			.vco_min = VC3_PLL1_VCO_MIN,
6986e9aff55SBiju Das 			.vco_max = VC3_PLL1_VCO_MAX
6996e9aff55SBiju Das 		},
7006e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
7016e9aff55SBiju Das 			.name = "pll1",
7026e9aff55SBiju Das 			.ops = &vc3_pll_ops,
7036e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
7046e9aff55SBiju Das 				&clk_pfd[VC3_PFD1].hw
7056e9aff55SBiju Das 			},
7066e9aff55SBiju Das 			.num_parents = 1,
7076e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
7086e9aff55SBiju Das 		}
7096e9aff55SBiju Das 	},
7106e9aff55SBiju Das 	[VC3_PLL2] = {
7116e9aff55SBiju Das 		.data = &(struct vc3_pll_data) {
7126e9aff55SBiju Das 			.num = VC3_PLL2,
7136e9aff55SBiju Das 			.int_div_msb_offs = VC3_PLL2_FB_INT_DIV_MSB,
7146e9aff55SBiju Das 			.int_div_lsb_offs = VC3_PLL2_FB_INT_DIV_LSB,
7156e9aff55SBiju Das 			.vco_min = VC3_PLL2_VCO_MIN,
7166e9aff55SBiju Das 			.vco_max = VC3_PLL2_VCO_MAX
7176e9aff55SBiju Das 		},
7186e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
7196e9aff55SBiju Das 			.name = "pll2",
7206e9aff55SBiju Das 			.ops = &vc3_pll_ops,
7216e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
7226e9aff55SBiju Das 				&clk_pfd[VC3_PFD2].hw
7236e9aff55SBiju Das 			},
7246e9aff55SBiju Das 			.num_parents = 1,
7256e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
7266e9aff55SBiju Das 		}
7276e9aff55SBiju Das 	},
7286e9aff55SBiju Das 	[VC3_PLL3] = {
7296e9aff55SBiju Das 		.data = &(struct vc3_pll_data) {
7306e9aff55SBiju Das 			.num = VC3_PLL3,
7316e9aff55SBiju Das 			.int_div_msb_offs = VC3_PLL3_LOOP_FILTER_N_DIV_MSB,
7326e9aff55SBiju Das 			.int_div_lsb_offs = VC3_PLL3_N_DIVIDER,
7336e9aff55SBiju Das 			.vco_min = VC3_PLL3_VCO_MIN,
7346e9aff55SBiju Das 			.vco_max = VC3_PLL3_VCO_MAX
7356e9aff55SBiju Das 		},
7366e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
7376e9aff55SBiju Das 			.name = "pll3",
7386e9aff55SBiju Das 			.ops = &vc3_pll_ops,
7396e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
7406e9aff55SBiju Das 				&clk_pfd[VC3_PFD3].hw
7416e9aff55SBiju Das 			},
7426e9aff55SBiju Das 			.num_parents = 1,
7436e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
7446e9aff55SBiju Das 		}
7456e9aff55SBiju Das 	}
7466e9aff55SBiju Das };
7476e9aff55SBiju Das 
7486e9aff55SBiju Das static const struct clk_parent_data div_mux_parent_data[][2] = {
7496e9aff55SBiju Das 	[VC3_DIV1_MUX] = {
7506e9aff55SBiju Das 		{ .hw = &clk_pll[VC3_PLL1].hw },
7516e9aff55SBiju Das 		{ .index = 0 }
7526e9aff55SBiju Das 	},
7536e9aff55SBiju Das 	[VC3_DIV3_MUX] = {
7546e9aff55SBiju Das 		{ .hw = &clk_pll[VC3_PLL2].hw },
7556e9aff55SBiju Das 		{ .hw = &clk_pll[VC3_PLL3].hw }
7566e9aff55SBiju Das 	},
7576e9aff55SBiju Das 	[VC3_DIV4_MUX] = {
7586e9aff55SBiju Das 		{ .hw = &clk_pll[VC3_PLL2].hw },
7596e9aff55SBiju Das 		{ .index = 0 }
7606e9aff55SBiju Das 	}
7616e9aff55SBiju Das };
7626e9aff55SBiju Das 
7636e9aff55SBiju Das static struct vc3_hw_data clk_div_mux[] = {
7646e9aff55SBiju Das 	[VC3_DIV1_MUX] = {
7656e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
7666e9aff55SBiju Das 			.offs = VC3_GENERAL_CTR,
7676e9aff55SBiju Das 			.bitmsk = VC3_GENERAL_CTR_DIV1_SRC_SEL
7686e9aff55SBiju Das 		},
7696e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
7706e9aff55SBiju Das 			.name = "div1_mux",
7716e9aff55SBiju Das 			.ops = &vc3_div_mux_ops,
7726e9aff55SBiju Das 			.parent_data = div_mux_parent_data[VC3_DIV1_MUX],
7736e9aff55SBiju Das 			.num_parents = 2,
7746e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
7756e9aff55SBiju Das 		}
7766e9aff55SBiju Das 	},
7776e9aff55SBiju Das 	[VC3_DIV3_MUX] = {
7786e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
7796e9aff55SBiju Das 			.offs = VC3_PLL3_CHARGE_PUMP_CTRL,
7806e9aff55SBiju Das 			.bitmsk = VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL
7816e9aff55SBiju Das 		},
7826e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
7836e9aff55SBiju Das 			.name = "div3_mux",
7846e9aff55SBiju Das 			.ops = &vc3_div_mux_ops,
7856e9aff55SBiju Das 			.parent_data = div_mux_parent_data[VC3_DIV3_MUX],
7866e9aff55SBiju Das 			.num_parents = 2,
7876e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
7886e9aff55SBiju Das 		}
7896e9aff55SBiju Das 	},
7906e9aff55SBiju Das 	[VC3_DIV4_MUX] = {
7916e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
7926e9aff55SBiju Das 			.offs = VC3_OUTPUT_CTR,
7936e9aff55SBiju Das 			.bitmsk = VC3_OUTPUT_CTR_DIV4_SRC_SEL
7946e9aff55SBiju Das 		},
7956e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
7966e9aff55SBiju Das 			.name = "div4_mux",
7976e9aff55SBiju Das 			.ops = &vc3_div_mux_ops,
7986e9aff55SBiju Das 			.parent_data = div_mux_parent_data[VC3_DIV4_MUX],
7996e9aff55SBiju Das 			.num_parents = 2,
8006e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT
8016e9aff55SBiju Das 		}
8026e9aff55SBiju Das 	}
8036e9aff55SBiju Das };
8046e9aff55SBiju Das 
8056e9aff55SBiju Das static struct vc3_hw_data clk_div[] = {
8066e9aff55SBiju Das 	[VC3_DIV1] = {
8076e9aff55SBiju Das 		.data = &(struct vc3_div_data) {
8086e9aff55SBiju Das 			.offs = VC3_OUT_DIV1_DIV2_CTRL,
8096e9aff55SBiju Das 			.table = div1_divs,
8106e9aff55SBiju Das 			.shift = 4,
8116e9aff55SBiju Das 			.width = 4,
8126e9aff55SBiju Das 			.flags = CLK_DIVIDER_READ_ONLY
8136e9aff55SBiju Das 		},
8146e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
8156e9aff55SBiju Das 			.name = "div1",
8166e9aff55SBiju Das 			.ops = &vc3_div_ops,
8176e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
8186e9aff55SBiju Das 				&clk_div_mux[VC3_DIV1_MUX].hw
8196e9aff55SBiju Das 			},
8206e9aff55SBiju Das 			.num_parents = 1,
8216e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
8226e9aff55SBiju Das 		}
8236e9aff55SBiju Das 	},
8246e9aff55SBiju Das 	[VC3_DIV2] = {
8256e9aff55SBiju Das 		.data = &(struct vc3_div_data) {
8266e9aff55SBiju Das 			.offs = VC3_OUT_DIV1_DIV2_CTRL,
8276e9aff55SBiju Das 			.table = div245_divs,
8286e9aff55SBiju Das 			.shift = 0,
8296e9aff55SBiju Das 			.width = 4,
8306e9aff55SBiju Das 			.flags = CLK_DIVIDER_READ_ONLY
8316e9aff55SBiju Das 		},
8326e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
8336e9aff55SBiju Das 			.name = "div2",
8346e9aff55SBiju Das 			.ops = &vc3_div_ops,
8356e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
8366e9aff55SBiju Das 				&clk_pll[VC3_PLL1].hw
8376e9aff55SBiju Das 			},
8386e9aff55SBiju Das 			.num_parents = 1,
8396e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
8406e9aff55SBiju Das 		}
8416e9aff55SBiju Das 	},
8426e9aff55SBiju Das 	[VC3_DIV3] = {
8436e9aff55SBiju Das 		.data = &(struct vc3_div_data) {
8446e9aff55SBiju Das 			.offs = VC3_OUT_DIV3_DIV4_CTRL,
8456e9aff55SBiju Das 			.table = div3_divs,
8466e9aff55SBiju Das 			.shift = 4,
8476e9aff55SBiju Das 			.width = 4,
8486e9aff55SBiju Das 			.flags = CLK_DIVIDER_READ_ONLY
8496e9aff55SBiju Das 		},
8506e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
8516e9aff55SBiju Das 			.name = "div3",
8526e9aff55SBiju Das 			.ops = &vc3_div_ops,
8536e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
8546e9aff55SBiju Das 				&clk_div_mux[VC3_DIV3_MUX].hw
8556e9aff55SBiju Das 			},
8566e9aff55SBiju Das 			.num_parents = 1,
8576e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
8586e9aff55SBiju Das 		}
8596e9aff55SBiju Das 	},
8606e9aff55SBiju Das 	[VC3_DIV4] = {
8616e9aff55SBiju Das 		.data = &(struct vc3_div_data) {
8626e9aff55SBiju Das 			.offs = VC3_OUT_DIV3_DIV4_CTRL,
8636e9aff55SBiju Das 			.table = div245_divs,
8646e9aff55SBiju Das 			.shift = 0,
8656e9aff55SBiju Das 			.width = 4,
8666e9aff55SBiju Das 			.flags = CLK_DIVIDER_READ_ONLY
8676e9aff55SBiju Das 		},
8686e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
8696e9aff55SBiju Das 			.name = "div4",
8706e9aff55SBiju Das 			.ops = &vc3_div_ops,
8716e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
8726e9aff55SBiju Das 				&clk_div_mux[VC3_DIV4_MUX].hw
8736e9aff55SBiju Das 			},
8746e9aff55SBiju Das 			.num_parents = 1,
8756e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
8766e9aff55SBiju Das 		}
8776e9aff55SBiju Das 	},
8786e9aff55SBiju Das 	[VC3_DIV5] = {
8796e9aff55SBiju Das 		.data = &(struct vc3_div_data) {
8806e9aff55SBiju Das 			.offs = VC3_PLL1_CTRL_OUTDIV5,
8816e9aff55SBiju Das 			.table = div245_divs,
8826e9aff55SBiju Das 			.shift = 0,
8836e9aff55SBiju Das 			.width = 4,
8846e9aff55SBiju Das 			.flags = CLK_DIVIDER_READ_ONLY
8856e9aff55SBiju Das 		},
8866e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
8876e9aff55SBiju Das 			.name = "div5",
8886e9aff55SBiju Das 			.ops = &vc3_div_ops,
8896e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
8906e9aff55SBiju Das 				&clk_pll[VC3_PLL3].hw
8916e9aff55SBiju Das 			},
8926e9aff55SBiju Das 			.num_parents = 1,
8936e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
8946e9aff55SBiju Das 		}
8956e9aff55SBiju Das 	}
8966e9aff55SBiju Das };
8976e9aff55SBiju Das 
8986e9aff55SBiju Das static struct vc3_hw_data clk_mux[] = {
8996dcf03bcSBiju Das 	[VC3_SE1_MUX] = {
9006e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
9016dcf03bcSBiju Das 			.offs = VC3_SE1_DIV4_CTRL,
9026dcf03bcSBiju Das 			.bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL
9036e9aff55SBiju Das 		},
9046e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
9056dcf03bcSBiju Das 			.name = "se1_mux",
9066e9aff55SBiju Das 			.ops = &vc3_clk_mux_ops,
9076e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
9086dcf03bcSBiju Das 				&clk_div[VC3_DIV5].hw,
9096e9aff55SBiju Das 				&clk_div[VC3_DIV4].hw
9106e9aff55SBiju Das 			},
9116e9aff55SBiju Das 			.num_parents = 2,
9126e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
9136e9aff55SBiju Das 		}
9146e9aff55SBiju Das 	},
9156e9aff55SBiju Das 	[VC3_SE2_MUX] = {
9166e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
9176e9aff55SBiju Das 			.offs = VC3_SE2_CTRL_REG0,
9186e9aff55SBiju Das 			.bitmsk = VC3_SE2_CTRL_REG0_SE2_CLK_SEL
9196e9aff55SBiju Das 		},
9206e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
9216e9aff55SBiju Das 			.name = "se2_mux",
9226e9aff55SBiju Das 			.ops = &vc3_clk_mux_ops,
9236e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
9246e9aff55SBiju Das 				&clk_div[VC3_DIV5].hw,
9256e9aff55SBiju Das 				&clk_div[VC3_DIV4].hw
9266e9aff55SBiju Das 			},
9276e9aff55SBiju Das 			.num_parents = 2,
9286e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
9296e9aff55SBiju Das 		}
9306e9aff55SBiju Das 	},
9316dcf03bcSBiju Das 	[VC3_SE3_MUX] = {
9326e9aff55SBiju Das 		.data = &(struct vc3_clk_data) {
9336dcf03bcSBiju Das 			.offs = VC3_SE3_DIFF1_CTRL_REG,
9346dcf03bcSBiju Das 			.bitmsk = VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL
9356e9aff55SBiju Das 		},
9366e9aff55SBiju Das 		.hw.init = &(struct clk_init_data){
9376dcf03bcSBiju Das 			.name = "se3_mux",
9386e9aff55SBiju Das 			.ops = &vc3_clk_mux_ops,
9396e9aff55SBiju Das 			.parent_hws = (const struct clk_hw *[]) {
9406dcf03bcSBiju Das 				&clk_div[VC3_DIV2].hw,
9416e9aff55SBiju Das 				&clk_div[VC3_DIV4].hw
9426e9aff55SBiju Das 			},
9436e9aff55SBiju Das 			.num_parents = 2,
9446e9aff55SBiju Das 			.flags = CLK_SET_RATE_PARENT
9456e9aff55SBiju Das 		}
9466dcf03bcSBiju Das 	},
9476dcf03bcSBiju Das 	[VC3_DIFF1_MUX] = {
9486dcf03bcSBiju Das 		.data = &(struct vc3_clk_data) {
9496dcf03bcSBiju Das 			.offs = VC3_DIFF1_CTRL_REG,
9506dcf03bcSBiju Das 			.bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL
9516dcf03bcSBiju Das 		},
9526dcf03bcSBiju Das 		.hw.init = &(struct clk_init_data){
9536dcf03bcSBiju Das 			.name = "diff1_mux",
9546dcf03bcSBiju Das 			.ops = &vc3_clk_mux_ops,
9556dcf03bcSBiju Das 			.parent_hws = (const struct clk_hw *[]) {
9566dcf03bcSBiju Das 				&clk_div[VC3_DIV1].hw,
9576dcf03bcSBiju Das 				&clk_div[VC3_DIV3].hw
9586dcf03bcSBiju Das 			},
9596dcf03bcSBiju Das 			.num_parents = 2,
9606dcf03bcSBiju Das 			.flags = CLK_SET_RATE_PARENT
9616dcf03bcSBiju Das 		}
9626dcf03bcSBiju Das 	},
9636dcf03bcSBiju Das 	[VC3_DIFF2_MUX] = {
9646dcf03bcSBiju Das 		.data = &(struct vc3_clk_data) {
9656dcf03bcSBiju Das 			.offs = VC3_DIFF2_CTRL_REG,
9666dcf03bcSBiju Das 			.bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL
9676dcf03bcSBiju Das 		},
9686dcf03bcSBiju Das 		.hw.init = &(struct clk_init_data){
9696dcf03bcSBiju Das 			.name = "diff2_mux",
9706dcf03bcSBiju Das 			.ops = &vc3_clk_mux_ops,
9716dcf03bcSBiju Das 			.parent_hws = (const struct clk_hw *[]) {
9726dcf03bcSBiju Das 				&clk_div[VC3_DIV1].hw,
9736dcf03bcSBiju Das 				&clk_div[VC3_DIV3].hw
9746dcf03bcSBiju Das 			},
9756dcf03bcSBiju Das 			.num_parents = 2,
9766dcf03bcSBiju Das 			.flags = CLK_SET_RATE_PARENT
9776dcf03bcSBiju Das 		}
9786e9aff55SBiju Das 	}
9796e9aff55SBiju Das };
9806e9aff55SBiju Das 
vc3_of_clk_get(struct of_phandle_args * clkspec,void * data)9816e9aff55SBiju Das static struct clk_hw *vc3_of_clk_get(struct of_phandle_args *clkspec,
9826e9aff55SBiju Das 				     void *data)
9836e9aff55SBiju Das {
9846e9aff55SBiju Das 	unsigned int idx = clkspec->args[0];
9856e9aff55SBiju Das 	struct clk_hw **clkout_hw = data;
9866e9aff55SBiju Das 
9876e9aff55SBiju Das 	if (idx >= ARRAY_SIZE(clk_out)) {
9886e9aff55SBiju Das 		pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np);
9896e9aff55SBiju Das 		return ERR_PTR(-EINVAL);
9906e9aff55SBiju Das 	}
9916e9aff55SBiju Das 
9926e9aff55SBiju Das 	return clkout_hw[idx];
9936e9aff55SBiju Das }
9946e9aff55SBiju Das 
vc3_probe(struct i2c_client * client)9956e9aff55SBiju Das static int vc3_probe(struct i2c_client *client)
9966e9aff55SBiju Das {
9976e9aff55SBiju Das 	struct device *dev = &client->dev;
9986e9aff55SBiju Das 	u8 settings[NUM_CONFIG_REGISTERS];
9996e9aff55SBiju Das 	struct regmap *regmap;
10006e9aff55SBiju Das 	const char *name;
10016e9aff55SBiju Das 	int ret, i;
10026e9aff55SBiju Das 
10036e9aff55SBiju Das 	regmap = devm_regmap_init_i2c(client, &vc3_regmap_config);
10046e9aff55SBiju Das 	if (IS_ERR(regmap))
10056e9aff55SBiju Das 		return dev_err_probe(dev, PTR_ERR(regmap),
10066e9aff55SBiju Das 				     "failed to allocate register map\n");
10076e9aff55SBiju Das 
10086e9aff55SBiju Das 	ret = of_property_read_u8_array(dev->of_node, "renesas,settings",
10096e9aff55SBiju Das 					settings, ARRAY_SIZE(settings));
10106e9aff55SBiju Das 	if (!ret) {
10116e9aff55SBiju Das 		/*
10126e9aff55SBiju Das 		 * A raw settings array was specified in the DT. Write the
10136e9aff55SBiju Das 		 * settings to the device immediately.
10146e9aff55SBiju Das 		 */
10156e9aff55SBiju Das 		for  (i = 0; i < NUM_CONFIG_REGISTERS; i++) {
10166e9aff55SBiju Das 			ret = regmap_write(regmap, i, settings[i]);
10176e9aff55SBiju Das 			if (ret) {
10186e9aff55SBiju Das 				dev_err(dev, "error writing to chip (%i)\n", ret);
10196e9aff55SBiju Das 				return ret;
10206e9aff55SBiju Das 			}
10216e9aff55SBiju Das 		}
10226e9aff55SBiju Das 	} else if (ret == -EOVERFLOW) {
10236e9aff55SBiju Das 		dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu\n",
10246e9aff55SBiju Das 			ARRAY_SIZE(settings));
10256e9aff55SBiju Das 		return ret;
10266e9aff55SBiju Das 	}
10276e9aff55SBiju Das 
10286e9aff55SBiju Das 	/* Register pfd muxes */
10296e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_pfd_mux); i++) {
10306e9aff55SBiju Das 		clk_pfd_mux[i].regmap = regmap;
10316e9aff55SBiju Das 		ret = devm_clk_hw_register(dev, &clk_pfd_mux[i].hw);
10326e9aff55SBiju Das 		if (ret)
10336e9aff55SBiju Das 			return dev_err_probe(dev, ret, "%s failed\n",
10346e9aff55SBiju Das 					     clk_pfd_mux[i].hw.init->name);
10356e9aff55SBiju Das 	}
10366e9aff55SBiju Das 
10376e9aff55SBiju Das 	/* Register pfd's */
10386e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_pfd); i++) {
10396e9aff55SBiju Das 		clk_pfd[i].regmap = regmap;
10406e9aff55SBiju Das 		ret = devm_clk_hw_register(dev, &clk_pfd[i].hw);
10416e9aff55SBiju Das 		if (ret)
10426e9aff55SBiju Das 			return dev_err_probe(dev, ret, "%s failed\n",
10436e9aff55SBiju Das 					     clk_pfd[i].hw.init->name);
10446e9aff55SBiju Das 	}
10456e9aff55SBiju Das 
10466e9aff55SBiju Das 	/* Register pll's */
10476e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_pll); i++) {
10486e9aff55SBiju Das 		clk_pll[i].regmap = regmap;
10496e9aff55SBiju Das 		ret = devm_clk_hw_register(dev, &clk_pll[i].hw);
10506e9aff55SBiju Das 		if (ret)
10516e9aff55SBiju Das 			return dev_err_probe(dev, ret, "%s failed\n",
10526e9aff55SBiju Das 					     clk_pll[i].hw.init->name);
10536e9aff55SBiju Das 	}
10546e9aff55SBiju Das 
10556e9aff55SBiju Das 	/* Register divider muxes */
10566e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_div_mux); i++) {
10576e9aff55SBiju Das 		clk_div_mux[i].regmap = regmap;
10586e9aff55SBiju Das 		ret = devm_clk_hw_register(dev, &clk_div_mux[i].hw);
10596e9aff55SBiju Das 		if (ret)
10606e9aff55SBiju Das 			return dev_err_probe(dev, ret, "%s failed\n",
10616e9aff55SBiju Das 					     clk_div_mux[i].hw.init->name);
10626e9aff55SBiju Das 	}
10636e9aff55SBiju Das 
10646e9aff55SBiju Das 	/* Register dividers */
10656e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_div); i++) {
10666e9aff55SBiju Das 		clk_div[i].regmap = regmap;
10676e9aff55SBiju Das 		ret = devm_clk_hw_register(dev, &clk_div[i].hw);
10686e9aff55SBiju Das 		if (ret)
10696e9aff55SBiju Das 			return dev_err_probe(dev, ret, "%s failed\n",
10706e9aff55SBiju Das 					     clk_div[i].hw.init->name);
10716e9aff55SBiju Das 	}
10726e9aff55SBiju Das 
10736e9aff55SBiju Das 	/* Register clk muxes */
10746e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_mux); i++) {
10756e9aff55SBiju Das 		clk_mux[i].regmap = regmap;
10766e9aff55SBiju Das 		ret = devm_clk_hw_register(dev, &clk_mux[i].hw);
10776e9aff55SBiju Das 		if (ret)
10786e9aff55SBiju Das 			return dev_err_probe(dev, ret, "%s failed\n",
10796e9aff55SBiju Das 					     clk_mux[i].hw.init->name);
10806e9aff55SBiju Das 	}
10816e9aff55SBiju Das 
10826e9aff55SBiju Das 	/* Register clk outputs */
10836e9aff55SBiju Das 	for (i = 0; i < ARRAY_SIZE(clk_out); i++) {
10846e9aff55SBiju Das 		switch (i) {
10856e9aff55SBiju Das 		case VC3_DIFF2:
10866e9aff55SBiju Das 			name = "diff2";
10876e9aff55SBiju Das 			break;
10886e9aff55SBiju Das 		case VC3_DIFF1:
10896e9aff55SBiju Das 			name = "diff1";
10906e9aff55SBiju Das 			break;
10916e9aff55SBiju Das 		case VC3_SE3:
10926e9aff55SBiju Das 			name = "se3";
10936e9aff55SBiju Das 			break;
10946e9aff55SBiju Das 		case VC3_SE2:
10956e9aff55SBiju Das 			name = "se2";
10966e9aff55SBiju Das 			break;
10976e9aff55SBiju Das 		case VC3_SE1:
10986e9aff55SBiju Das 			name = "se1";
10996e9aff55SBiju Das 			break;
11006e9aff55SBiju Das 		case VC3_REF:
11016e9aff55SBiju Das 			name = "ref";
11026e9aff55SBiju Das 			break;
11036e9aff55SBiju Das 		default:
11046e9aff55SBiju Das 			return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i);
11056e9aff55SBiju Das 		}
11066e9aff55SBiju Das 
11076e9aff55SBiju Das 		if (i == VC3_REF)
11086e9aff55SBiju Das 			clk_out[i] = devm_clk_hw_register_fixed_factor_index(dev,
11096e9aff55SBiju Das 				name, 0, CLK_SET_RATE_PARENT, 1, 1);
11106e9aff55SBiju Das 		else
11116e9aff55SBiju Das 			clk_out[i] = devm_clk_hw_register_fixed_factor_parent_hw(dev,
11126dcf03bcSBiju Das 				name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1);
11136e9aff55SBiju Das 
11146e9aff55SBiju Das 		if (IS_ERR(clk_out[i]))
11156e9aff55SBiju Das 			return PTR_ERR(clk_out[i]);
11166e9aff55SBiju Das 	}
11176e9aff55SBiju Das 
11186e9aff55SBiju Das 	ret = devm_of_clk_add_hw_provider(dev, vc3_of_clk_get, clk_out);
11196e9aff55SBiju Das 	if (ret)
11206e9aff55SBiju Das 		return dev_err_probe(dev, ret, "unable to add clk provider\n");
11216e9aff55SBiju Das 
11226e9aff55SBiju Das 	return ret;
11236e9aff55SBiju Das }
11246e9aff55SBiju Das 
11256e9aff55SBiju Das static const struct of_device_id dev_ids[] = {
11266e9aff55SBiju Das 	{ .compatible = "renesas,5p35023" },
11276e9aff55SBiju Das 	{ /* Sentinel */ }
11286e9aff55SBiju Das };
11296e9aff55SBiju Das MODULE_DEVICE_TABLE(of, dev_ids);
11306e9aff55SBiju Das 
11316e9aff55SBiju Das static struct i2c_driver vc3_driver = {
11326e9aff55SBiju Das 	.driver = {
11336e9aff55SBiju Das 		.name = "vc3",
11346e9aff55SBiju Das 		.of_match_table = of_match_ptr(dev_ids),
11356e9aff55SBiju Das 	},
1136a53ef055SUwe Kleine-König 	.probe = vc3_probe,
11376e9aff55SBiju Das };
11386e9aff55SBiju Das module_i2c_driver(vc3_driver);
11396e9aff55SBiju Das 
11406e9aff55SBiju Das MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
11416e9aff55SBiju Das MODULE_DESCRIPTION("Renesas VersaClock 3 driver");
11426e9aff55SBiju Das MODULE_LICENSE("GPL");
1143