brintos

brintos / linux-shallow public Read only

0
0
Text · 27.9 KiB · 76d7ea1 Raw
1129 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Driver for Renesas Versaclock 34 *5 * Copyright (C) 2023 Renesas Electronics Corp.6 */7 8#include <linux/clk-provider.h>9#include <linux/i2c.h>10#include <linux/limits.h>11#include <linux/module.h>12#include <linux/regmap.h>13 14#define NUM_CONFIG_REGISTERS		3715 16#define VC3_GENERAL_CTR			0x017#define VC3_GENERAL_CTR_DIV1_SRC_SEL	BIT(3)18#define VC3_GENERAL_CTR_PLL3_REFIN_SEL	BIT(2)19 20#define VC3_PLL3_M_DIVIDER		0x321#define VC3_PLL3_M_DIV1			BIT(7)22#define VC3_PLL3_M_DIV2			BIT(6)23#define VC3_PLL3_M_DIV(n)		((n) & GENMASK(5, 0))24 25#define VC3_PLL3_N_DIVIDER		0x426#define VC3_PLL3_LOOP_FILTER_N_DIV_MSB	0x527 28#define VC3_PLL3_CHARGE_PUMP_CTRL	0x629#define VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL	BIT(7)30 31#define VC3_PLL1_CTRL_OUTDIV5		0x732#define VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER		BIT(7)33 34#define VC3_PLL1_M_DIVIDER		0x835#define VC3_PLL1_M_DIV1			BIT(7)36#define VC3_PLL1_M_DIV2			BIT(6)37#define VC3_PLL1_M_DIV(n)		((n) & GENMASK(5, 0))38 39#define VC3_PLL1_VCO_N_DIVIDER		0x940#define VC3_PLL1_LOOP_FILTER_N_DIV_MSB	0xa41 42#define VC3_OUT_DIV1_DIV2_CTRL		0xf43 44#define VC3_PLL2_FB_INT_DIV_MSB		0x1045#define VC3_PLL2_FB_INT_DIV_LSB		0x1146#define VC3_PLL2_FB_FRC_DIV_MSB		0x1247#define VC3_PLL2_FB_FRC_DIV_LSB		0x1348 49#define VC3_PLL2_M_DIVIDER		0x1a50#define VC3_PLL2_MDIV_DOUBLER		BIT(7)51#define VC3_PLL2_M_DIV1			BIT(6)52#define VC3_PLL2_M_DIV2			BIT(5)53#define VC3_PLL2_M_DIV(n)		((n) & GENMASK(4, 0))54 55#define VC3_OUT_DIV3_DIV4_CTRL		0x1b56 57#define VC3_PLL_OP_CTRL			0x1c58#define VC3_PLL_OP_CTRL_PLL2_REFIN_SEL	659 60#define VC3_OUTPUT_CTR			0x1d61#define VC3_OUTPUT_CTR_DIV4_SRC_SEL	BIT(3)62 63#define VC3_SE2_CTRL_REG0		0x1f64#define VC3_SE2_CTRL_REG0_SE2_CLK_SEL	BIT(6)65 66#define VC3_SE3_DIFF1_CTRL_REG		0x2167#define VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL	BIT(6)68 69#define VC3_DIFF1_CTRL_REG		0x2270#define VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL	BIT(7)71 72#define VC3_DIFF2_CTRL_REG		0x2373#define VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL	BIT(7)74 75#define VC3_SE1_DIV4_CTRL		0x2476#define VC3_SE1_DIV4_CTRL_SE1_CLK_SEL	BIT(3)77 78#define VC3_PLL1_VCO_MIN		300000000UL79#define VC3_PLL1_VCO_MAX		600000000UL80 81#define VC3_PLL2_VCO_MIN		400000000UL82#define VC3_PLL2_VCO_MAX		1200000000UL83 84#define VC3_PLL3_VCO_MIN		300000000UL85#define VC3_PLL3_VCO_MAX		800000000UL86 87#define VC3_2_POW_16			(U16_MAX + 1)88#define VC3_DIV_MASK(width)		((1 << (width)) - 1)89 90enum vc3_pfd_mux {91	VC3_PFD2_MUX,92	VC3_PFD3_MUX,93};94 95enum vc3_pfd {96	VC3_PFD1,97	VC3_PFD2,98	VC3_PFD3,99};100 101enum vc3_pll {102	VC3_PLL1,103	VC3_PLL2,104	VC3_PLL3,105};106 107enum vc3_div_mux {108	VC3_DIV1_MUX,109	VC3_DIV3_MUX,110	VC3_DIV4_MUX,111};112 113enum vc3_div {114	VC3_DIV1,115	VC3_DIV2,116	VC3_DIV3,117	VC3_DIV4,118	VC3_DIV5,119};120 121enum vc3_clk {122	VC3_REF,123	VC3_SE1,124	VC3_SE2,125	VC3_SE3,126	VC3_DIFF1,127	VC3_DIFF2,128};129 130enum vc3_clk_mux {131	VC3_SE1_MUX = VC3_SE1 - 1,132	VC3_SE2_MUX = VC3_SE2 - 1,133	VC3_SE3_MUX = VC3_SE3 - 1,134	VC3_DIFF1_MUX = VC3_DIFF1 - 1,135	VC3_DIFF2_MUX = VC3_DIFF2 - 1,136};137 138struct vc3_clk_data {139	u8 offs;140	u8 bitmsk;141};142 143struct vc3_pfd_data {144	u8 num;145	u8 offs;146	u8 mdiv1_bitmsk;147	u8 mdiv2_bitmsk;148};149 150struct vc3_pll_data {151	unsigned long vco_min;152	unsigned long vco_max;153	u8 num;154	u8 int_div_msb_offs;155	u8 int_div_lsb_offs;156};157 158struct vc3_div_data {159	const struct clk_div_table *table;160	u8 offs;161	u8 shift;162	u8 width;163	u8 flags;164};165 166struct vc3_hw_data {167	struct clk_hw hw;168	struct regmap *regmap;169	const void *data;170 171	u32 div_int;172	u32 div_frc;173};174 175static const struct clk_div_table div1_divs[] = {176	{ .val = 0, .div = 1, }, { .val = 1, .div = 4, },177	{ .val = 2, .div = 5, }, { .val = 3, .div = 6, },178	{ .val = 4, .div = 2, }, { .val = 5, .div = 8, },179	{ .val = 6, .div = 10, }, { .val = 7, .div = 12, },180	{ .val = 8, .div = 4, }, { .val = 9, .div = 16, },181	{ .val = 10, .div = 20, }, { .val = 11, .div = 24, },182	{ .val = 12, .div = 8, }, { .val = 13, .div = 32, },183	{ .val = 14, .div = 40, }, { .val = 15, .div = 48, },184	{}185};186 187static const struct clk_div_table div245_divs[] = {188	{ .val = 0, .div = 1, }, { .val = 1, .div = 3, },189	{ .val = 2, .div = 5, }, { .val = 3, .div = 10, },190	{ .val = 4, .div = 2, }, { .val = 5, .div = 6, },191	{ .val = 6, .div = 10, }, { .val = 7, .div = 20, },192	{ .val = 8, .div = 4, }, { .val = 9, .div = 12, },193	{ .val = 10, .div = 20, }, { .val = 11, .div = 40, },194	{ .val = 12, .div = 5, }, { .val = 13, .div = 15, },195	{ .val = 14, .div = 25, }, { .val = 15, .div = 50, },196	{}197};198 199static const struct clk_div_table div3_divs[] = {200	{ .val = 0, .div = 1, }, { .val = 1, .div = 3, },201	{ .val = 2, .div = 5, }, { .val = 3, .div = 10, },202	{ .val = 4, .div = 2, }, { .val = 5, .div = 6, },203	{ .val = 6, .div = 10, }, { .val = 7, .div = 20, },204	{ .val = 8, .div = 4, }, { .val = 9, .div = 12, },205	{ .val = 10, .div = 20, }, { .val = 11, .div = 40, },206	{ .val = 12, .div = 8, }, { .val = 13, .div = 24, },207	{ .val = 14, .div = 40, }, { .val = 15, .div = 80, },208	{}209};210 211static struct clk_hw *clk_out[6];212 213static u8 vc3_pfd_mux_get_parent(struct clk_hw *hw)214{215	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);216	const struct vc3_clk_data *pfd_mux = vc3->data;217	u32 src;218 219	regmap_read(vc3->regmap, pfd_mux->offs, &src);220 221	return !!(src & pfd_mux->bitmsk);222}223 224static int vc3_pfd_mux_set_parent(struct clk_hw *hw, u8 index)225{226	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);227	const struct vc3_clk_data *pfd_mux = vc3->data;228 229	return regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk,230				  index ? pfd_mux->bitmsk : 0);231}232 233static const struct clk_ops vc3_pfd_mux_ops = {234	.determine_rate = clk_hw_determine_rate_no_reparent,235	.set_parent = vc3_pfd_mux_set_parent,236	.get_parent = vc3_pfd_mux_get_parent,237};238 239static unsigned long vc3_pfd_recalc_rate(struct clk_hw *hw,240					 unsigned long parent_rate)241{242	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);243	const struct vc3_pfd_data *pfd = vc3->data;244	unsigned int prediv, premul;245	unsigned long rate;246	u8 mdiv;247 248	regmap_read(vc3->regmap, pfd->offs, &prediv);249	if (pfd->num == VC3_PFD1) {250		/* The bypass_prediv is set, PLL fed from Ref_in directly. */251		if (prediv & pfd->mdiv1_bitmsk) {252			/* check doubler is set or not */253			regmap_read(vc3->regmap, VC3_PLL1_CTRL_OUTDIV5, &premul);254			if (premul & VC3_PLL1_CTRL_OUTDIV5_PLL1_MDIV_DOUBLER)255				parent_rate *= 2;256			return parent_rate;257		}258		mdiv = VC3_PLL1_M_DIV(prediv);259	} else if (pfd->num == VC3_PFD2) {260		/* The bypass_prediv is set, PLL fed from Ref_in directly. */261		if (prediv & pfd->mdiv1_bitmsk) {262			regmap_read(vc3->regmap, VC3_PLL2_M_DIVIDER, &premul);263			/* check doubler is set or not */264			if (premul & VC3_PLL2_MDIV_DOUBLER)265				parent_rate *= 2;266			return parent_rate;267		}268 269		mdiv = VC3_PLL2_M_DIV(prediv);270	} else {271		/* The bypass_prediv is set, PLL fed from Ref_in directly. */272		if (prediv & pfd->mdiv1_bitmsk)273			return parent_rate;274 275		mdiv = VC3_PLL3_M_DIV(prediv);276	}277 278	if (prediv & pfd->mdiv2_bitmsk)279		rate = parent_rate / 2;280	else281		rate = parent_rate / mdiv;282 283	return rate;284}285 286static long vc3_pfd_round_rate(struct clk_hw *hw, unsigned long rate,287			       unsigned long *parent_rate)288{289	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);290	const struct vc3_pfd_data *pfd = vc3->data;291	unsigned long idiv;292 293	/* PLL cannot operate with input clock above 50 MHz. */294	if (rate > 50000000)295		return -EINVAL;296 297	/* CLKIN within range of PLL input, feed directly to PLL. */298	if (*parent_rate <= 50000000)299		return *parent_rate;300 301	idiv = DIV_ROUND_UP(*parent_rate, rate);302	if (pfd->num == VC3_PFD1 || pfd->num == VC3_PFD3) {303		if (idiv > 63)304			return -EINVAL;305	} else {306		if (idiv > 31)307			return -EINVAL;308	}309 310	return *parent_rate / idiv;311}312 313static int vc3_pfd_set_rate(struct clk_hw *hw, unsigned long rate,314			    unsigned long parent_rate)315{316	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);317	const struct vc3_pfd_data *pfd = vc3->data;318	unsigned long idiv;319	u8 div;320 321	/* CLKIN within range of PLL input, feed directly to PLL. */322	if (parent_rate <= 50000000) {323		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk,324				   pfd->mdiv1_bitmsk);325		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk, 0);326		return 0;327	}328 329	idiv = DIV_ROUND_UP(parent_rate, rate);330	/* We have dedicated div-2 predivider. */331	if (idiv == 2) {332		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv2_bitmsk,333				   pfd->mdiv2_bitmsk);334		regmap_update_bits(vc3->regmap, pfd->offs, pfd->mdiv1_bitmsk, 0);335	} else {336		if (pfd->num == VC3_PFD1)337			div = VC3_PLL1_M_DIV(idiv);338		else if (pfd->num == VC3_PFD2)339			div = VC3_PLL2_M_DIV(idiv);340		else341			div = VC3_PLL3_M_DIV(idiv);342 343		regmap_write(vc3->regmap, pfd->offs, div);344	}345 346	return 0;347}348 349static const struct clk_ops vc3_pfd_ops = {350	.recalc_rate = vc3_pfd_recalc_rate,351	.round_rate = vc3_pfd_round_rate,352	.set_rate = vc3_pfd_set_rate,353};354 355static unsigned long vc3_pll_recalc_rate(struct clk_hw *hw,356					 unsigned long parent_rate)357{358	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);359	const struct vc3_pll_data *pll = vc3->data;360	u32 div_int, div_frc, val;361	unsigned long rate;362 363	regmap_read(vc3->regmap, pll->int_div_msb_offs, &val);364	div_int = (val & GENMASK(2, 0)) << 8;365	regmap_read(vc3->regmap, pll->int_div_lsb_offs, &val);366	div_int |= val;367 368	if (pll->num == VC3_PLL2) {369		regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB, &val);370		div_frc = val << 8;371		regmap_read(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB, &val);372		div_frc |= val;373		rate = (parent_rate *374			(div_int * VC3_2_POW_16 + div_frc) / VC3_2_POW_16);375	} else {376		rate = parent_rate * div_int;377	}378 379	return rate;380}381 382static long vc3_pll_round_rate(struct clk_hw *hw, unsigned long rate,383			       unsigned long *parent_rate)384{385	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);386	const struct vc3_pll_data *pll = vc3->data;387	u64 div_frc;388 389	if (rate < pll->vco_min)390		rate = pll->vco_min;391	if (rate > pll->vco_max)392		rate = pll->vco_max;393 394	vc3->div_int = rate / *parent_rate;395 396	if (pll->num == VC3_PLL2) {397		if (vc3->div_int > 0x7ff)398			rate = *parent_rate * 0x7ff;399 400		/* Determine best fractional part, which is 16 bit wide */401		div_frc = rate % *parent_rate;402		div_frc *= BIT(16) - 1;403 404		vc3->div_frc = min_t(u64, div64_ul(div_frc, *parent_rate), U16_MAX);405		rate = (*parent_rate *406			(vc3->div_int * VC3_2_POW_16 + vc3->div_frc) / VC3_2_POW_16);407	} else {408		rate = *parent_rate * vc3->div_int;409	}410 411	return rate;412}413 414static int vc3_pll_set_rate(struct clk_hw *hw, unsigned long rate,415			    unsigned long parent_rate)416{417	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);418	const struct vc3_pll_data *pll = vc3->data;419	u32 val;420 421	regmap_read(vc3->regmap, pll->int_div_msb_offs, &val);422	val = (val & 0xf8) | ((vc3->div_int >> 8) & 0x7);423	regmap_write(vc3->regmap, pll->int_div_msb_offs, val);424	regmap_write(vc3->regmap, pll->int_div_lsb_offs, vc3->div_int & 0xff);425 426	if (pll->num == VC3_PLL2) {427		regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_MSB,428			     vc3->div_frc >> 8);429		regmap_write(vc3->regmap, VC3_PLL2_FB_FRC_DIV_LSB,430			     vc3->div_frc & 0xff);431	}432 433	return 0;434}435 436static const struct clk_ops vc3_pll_ops = {437	.recalc_rate = vc3_pll_recalc_rate,438	.round_rate = vc3_pll_round_rate,439	.set_rate = vc3_pll_set_rate,440};441 442static u8 vc3_div_mux_get_parent(struct clk_hw *hw)443{444	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);445	const struct vc3_clk_data *div_mux = vc3->data;446	u32 src;447 448	regmap_read(vc3->regmap, div_mux->offs, &src);449 450	return !!(src & div_mux->bitmsk);451}452 453static int vc3_div_mux_set_parent(struct clk_hw *hw, u8 index)454{455	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);456	const struct vc3_clk_data *div_mux = vc3->data;457 458	return regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk,459				  index ? div_mux->bitmsk : 0);460}461 462static const struct clk_ops vc3_div_mux_ops = {463	.determine_rate = clk_hw_determine_rate_no_reparent,464	.set_parent = vc3_div_mux_set_parent,465	.get_parent = vc3_div_mux_get_parent,466};467 468static unsigned int vc3_get_div(const struct clk_div_table *table,469				unsigned int val, unsigned long flag)470{471	const struct clk_div_table *clkt;472 473	for (clkt = table; clkt->div; clkt++)474		if (clkt->val == val)475			return clkt->div;476 477	return 1;478}479 480static unsigned long vc3_div_recalc_rate(struct clk_hw *hw,481					 unsigned long parent_rate)482{483	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);484	const struct vc3_div_data *div_data = vc3->data;485	unsigned int val;486 487	regmap_read(vc3->regmap, div_data->offs, &val);488	val >>= div_data->shift;489	val &= VC3_DIV_MASK(div_data->width);490 491	return divider_recalc_rate(hw, parent_rate, val, div_data->table,492				   div_data->flags, div_data->width);493}494 495static long vc3_div_round_rate(struct clk_hw *hw, unsigned long rate,496			       unsigned long *parent_rate)497{498	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);499	const struct vc3_div_data *div_data = vc3->data;500	unsigned int bestdiv;501 502	/* if read only, just return current value */503	if (div_data->flags & CLK_DIVIDER_READ_ONLY) {504		regmap_read(vc3->regmap, div_data->offs, &bestdiv);505		bestdiv >>= div_data->shift;506		bestdiv &= VC3_DIV_MASK(div_data->width);507		bestdiv = vc3_get_div(div_data->table, bestdiv, div_data->flags);508		return DIV_ROUND_UP(*parent_rate, bestdiv);509	}510 511	return divider_round_rate(hw, rate, parent_rate, div_data->table,512				  div_data->width, div_data->flags);513}514 515static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,516			    unsigned long parent_rate)517{518	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);519	const struct vc3_div_data *div_data = vc3->data;520	unsigned int value;521 522	value = divider_get_val(rate, parent_rate, div_data->table,523				div_data->width, div_data->flags);524	return regmap_update_bits(vc3->regmap, div_data->offs,525				  VC3_DIV_MASK(div_data->width) << div_data->shift,526				  value << div_data->shift);527}528 529static const struct clk_ops vc3_div_ops = {530	.recalc_rate = vc3_div_recalc_rate,531	.round_rate = vc3_div_round_rate,532	.set_rate = vc3_div_set_rate,533};534 535static int vc3_clk_mux_determine_rate(struct clk_hw *hw,536				      struct clk_rate_request *req)537{538	int frc;539 540	if (clk_mux_determine_rate_flags(hw, req, CLK_SET_RATE_PARENT)) {541		/* The below check is equivalent to (best_parent_rate/rate) */542		if (req->best_parent_rate >= req->rate) {543			frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate,544						    req->rate);545			req->rate *= frc;546			return clk_mux_determine_rate_flags(hw, req,547							    CLK_SET_RATE_PARENT);548		}549	}550 551	return 0;552}553 554static u8 vc3_clk_mux_get_parent(struct clk_hw *hw)555{556	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);557	const struct vc3_clk_data *clk_mux = vc3->data;558	u32 val;559 560	regmap_read(vc3->regmap, clk_mux->offs, &val);561 562	return !!(val & clk_mux->bitmsk);563}564 565static int vc3_clk_mux_set_parent(struct clk_hw *hw, u8 index)566{567	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);568	const struct vc3_clk_data *clk_mux = vc3->data;569 570	return regmap_update_bits(vc3->regmap, clk_mux->offs, clk_mux->bitmsk,571				  index ? clk_mux->bitmsk : 0);572}573 574static const struct clk_ops vc3_clk_mux_ops = {575	.determine_rate = vc3_clk_mux_determine_rate,576	.set_parent = vc3_clk_mux_set_parent,577	.get_parent = vc3_clk_mux_get_parent,578};579 580static const struct regmap_config vc3_regmap_config = {581	.reg_bits = 8,582	.val_bits = 8,583	.cache_type = REGCACHE_MAPLE,584	.max_register = 0x24,585};586 587static struct vc3_hw_data clk_div[5];588 589static const struct clk_parent_data pfd_mux_parent_data[] = {590	{ .index = 0, },591	{ .hw = &clk_div[VC3_DIV2].hw }592};593 594static struct vc3_hw_data clk_pfd_mux[] = {595	[VC3_PFD2_MUX] = {596		.data = &(struct vc3_clk_data) {597			.offs = VC3_PLL_OP_CTRL,598			.bitmsk = BIT(VC3_PLL_OP_CTRL_PLL2_REFIN_SEL)599		},600		.hw.init = &(struct clk_init_data) {601			.name = "pfd2_mux",602			.ops = &vc3_pfd_mux_ops,603			.parent_data = pfd_mux_parent_data,604			.num_parents = 2,605			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT606		}607	},608	[VC3_PFD3_MUX] = {609		.data = &(struct vc3_clk_data) {610			.offs = VC3_GENERAL_CTR,611			.bitmsk = BIT(VC3_GENERAL_CTR_PLL3_REFIN_SEL)612		},613		.hw.init = &(struct clk_init_data) {614			.name = "pfd3_mux",615			.ops = &vc3_pfd_mux_ops,616			.parent_data = pfd_mux_parent_data,617			.num_parents = 2,618			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT619		}620	}621};622 623static struct vc3_hw_data clk_pfd[] = {624	[VC3_PFD1] = {625		.data = &(struct vc3_pfd_data) {626			.num = VC3_PFD1,627			.offs = VC3_PLL1_M_DIVIDER,628			.mdiv1_bitmsk = VC3_PLL1_M_DIV1,629			.mdiv2_bitmsk = VC3_PLL1_M_DIV2630		},631		.hw.init = &(struct clk_init_data) {632			.name = "pfd1",633			.ops = &vc3_pfd_ops,634			.parent_data = &(const struct clk_parent_data) {635				.index = 0636			},637			.num_parents = 1,638			.flags = CLK_SET_RATE_PARENT639		}640	},641	[VC3_PFD2] = {642		.data = &(struct vc3_pfd_data) {643			.num = VC3_PFD2,644			.offs = VC3_PLL2_M_DIVIDER,645			.mdiv1_bitmsk = VC3_PLL2_M_DIV1,646			.mdiv2_bitmsk = VC3_PLL2_M_DIV2647		},648		.hw.init = &(struct clk_init_data) {649			.name = "pfd2",650			.ops = &vc3_pfd_ops,651			.parent_hws = (const struct clk_hw *[]) {652				&clk_pfd_mux[VC3_PFD2_MUX].hw653			},654			.num_parents = 1,655			.flags = CLK_SET_RATE_PARENT656		}657	},658	[VC3_PFD3] = {659		.data = &(struct vc3_pfd_data) {660			.num = VC3_PFD3,661			.offs = VC3_PLL3_M_DIVIDER,662			.mdiv1_bitmsk = VC3_PLL3_M_DIV1,663			.mdiv2_bitmsk = VC3_PLL3_M_DIV2664		},665		.hw.init = &(struct clk_init_data) {666			.name = "pfd3",667			.ops = &vc3_pfd_ops,668			.parent_hws = (const struct clk_hw *[]) {669				&clk_pfd_mux[VC3_PFD3_MUX].hw670			},671			.num_parents = 1,672			.flags = CLK_SET_RATE_PARENT673		}674	}675};676 677static struct vc3_hw_data clk_pll[] = {678	[VC3_PLL1] = {679		.data = &(struct vc3_pll_data) {680			.num = VC3_PLL1,681			.int_div_msb_offs = VC3_PLL1_LOOP_FILTER_N_DIV_MSB,682			.int_div_lsb_offs = VC3_PLL1_VCO_N_DIVIDER,683			.vco_min = VC3_PLL1_VCO_MIN,684			.vco_max = VC3_PLL1_VCO_MAX685		},686		.hw.init = &(struct clk_init_data) {687			.name = "pll1",688			.ops = &vc3_pll_ops,689			.parent_hws = (const struct clk_hw *[]) {690				&clk_pfd[VC3_PFD1].hw691			},692			.num_parents = 1,693			.flags = CLK_SET_RATE_PARENT694		}695	},696	[VC3_PLL2] = {697		.data = &(struct vc3_pll_data) {698			.num = VC3_PLL2,699			.int_div_msb_offs = VC3_PLL2_FB_INT_DIV_MSB,700			.int_div_lsb_offs = VC3_PLL2_FB_INT_DIV_LSB,701			.vco_min = VC3_PLL2_VCO_MIN,702			.vco_max = VC3_PLL2_VCO_MAX703		},704		.hw.init = &(struct clk_init_data) {705			.name = "pll2",706			.ops = &vc3_pll_ops,707			.parent_hws = (const struct clk_hw *[]) {708				&clk_pfd[VC3_PFD2].hw709			},710			.num_parents = 1,711			.flags = CLK_SET_RATE_PARENT712		}713	},714	[VC3_PLL3] = {715		.data = &(struct vc3_pll_data) {716			.num = VC3_PLL3,717			.int_div_msb_offs = VC3_PLL3_LOOP_FILTER_N_DIV_MSB,718			.int_div_lsb_offs = VC3_PLL3_N_DIVIDER,719			.vco_min = VC3_PLL3_VCO_MIN,720			.vco_max = VC3_PLL3_VCO_MAX721		},722		.hw.init = &(struct clk_init_data) {723			.name = "pll3",724			.ops = &vc3_pll_ops,725			.parent_hws = (const struct clk_hw *[]) {726				&clk_pfd[VC3_PFD3].hw727			},728			.num_parents = 1,729			.flags = CLK_SET_RATE_PARENT730		}731	}732};733 734static const struct clk_parent_data div_mux_parent_data[][2] = {735	[VC3_DIV1_MUX] = {736		{ .hw = &clk_pll[VC3_PLL1].hw },737		{ .index = 0 }738	},739	[VC3_DIV3_MUX] = {740		{ .hw = &clk_pll[VC3_PLL2].hw },741		{ .hw = &clk_pll[VC3_PLL3].hw }742	},743	[VC3_DIV4_MUX] = {744		{ .hw = &clk_pll[VC3_PLL2].hw },745		{ .index = 0 }746	}747};748 749static struct vc3_hw_data clk_div_mux[] = {750	[VC3_DIV1_MUX] = {751		.data = &(struct vc3_clk_data) {752			.offs = VC3_GENERAL_CTR,753			.bitmsk = VC3_GENERAL_CTR_DIV1_SRC_SEL754		},755		.hw.init = &(struct clk_init_data) {756			.name = "div1_mux",757			.ops = &vc3_div_mux_ops,758			.parent_data = div_mux_parent_data[VC3_DIV1_MUX],759			.num_parents = 2,760			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT761		}762	},763	[VC3_DIV3_MUX] = {764		.data = &(struct vc3_clk_data) {765			.offs = VC3_PLL3_CHARGE_PUMP_CTRL,766			.bitmsk = VC3_PLL3_CHARGE_PUMP_CTRL_OUTDIV3_SRC_SEL767		},768		.hw.init = &(struct clk_init_data) {769			.name = "div3_mux",770			.ops = &vc3_div_mux_ops,771			.parent_data = div_mux_parent_data[VC3_DIV3_MUX],772			.num_parents = 2,773			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT774		}775	},776	[VC3_DIV4_MUX] = {777		.data = &(struct vc3_clk_data) {778			.offs = VC3_OUTPUT_CTR,779			.bitmsk = VC3_OUTPUT_CTR_DIV4_SRC_SEL780		},781		.hw.init = &(struct clk_init_data) {782			.name = "div4_mux",783			.ops = &vc3_div_mux_ops,784			.parent_data = div_mux_parent_data[VC3_DIV4_MUX],785			.num_parents = 2,786			.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT787		}788	}789};790 791static struct vc3_hw_data clk_div[] = {792	[VC3_DIV1] = {793		.data = &(struct vc3_div_data) {794			.offs = VC3_OUT_DIV1_DIV2_CTRL,795			.table = div1_divs,796			.shift = 4,797			.width = 4,798			.flags = CLK_DIVIDER_READ_ONLY799		},800		.hw.init = &(struct clk_init_data) {801			.name = "div1",802			.ops = &vc3_div_ops,803			.parent_hws = (const struct clk_hw *[]) {804				&clk_div_mux[VC3_DIV1_MUX].hw805			},806			.num_parents = 1,807			.flags = CLK_SET_RATE_PARENT808		}809	},810	[VC3_DIV2] = {811		.data = &(struct vc3_div_data) {812			.offs = VC3_OUT_DIV1_DIV2_CTRL,813			.table = div245_divs,814			.shift = 0,815			.width = 4,816			.flags = CLK_DIVIDER_READ_ONLY817		},818		.hw.init = &(struct clk_init_data) {819			.name = "div2",820			.ops = &vc3_div_ops,821			.parent_hws = (const struct clk_hw *[]) {822				&clk_pll[VC3_PLL1].hw823			},824			.num_parents = 1,825			.flags = CLK_SET_RATE_PARENT826		}827	},828	[VC3_DIV3] = {829		.data = &(struct vc3_div_data) {830			.offs = VC3_OUT_DIV3_DIV4_CTRL,831			.table = div3_divs,832			.shift = 4,833			.width = 4,834			.flags = CLK_DIVIDER_READ_ONLY835		},836		.hw.init = &(struct clk_init_data) {837			.name = "div3",838			.ops = &vc3_div_ops,839			.parent_hws = (const struct clk_hw *[]) {840				&clk_div_mux[VC3_DIV3_MUX].hw841			},842			.num_parents = 1,843			.flags = CLK_SET_RATE_PARENT844		}845	},846	[VC3_DIV4] = {847		.data = &(struct vc3_div_data) {848			.offs = VC3_OUT_DIV3_DIV4_CTRL,849			.table = div245_divs,850			.shift = 0,851			.width = 4,852			.flags = CLK_DIVIDER_READ_ONLY853		},854		.hw.init = &(struct clk_init_data) {855			.name = "div4",856			.ops = &vc3_div_ops,857			.parent_hws = (const struct clk_hw *[]) {858				&clk_div_mux[VC3_DIV4_MUX].hw859			},860			.num_parents = 1,861			.flags = CLK_SET_RATE_PARENT862		}863	},864	[VC3_DIV5] = {865		.data = &(struct vc3_div_data) {866			.offs = VC3_PLL1_CTRL_OUTDIV5,867			.table = div245_divs,868			.shift = 0,869			.width = 4,870			.flags = CLK_DIVIDER_READ_ONLY871		},872		.hw.init = &(struct clk_init_data) {873			.name = "div5",874			.ops = &vc3_div_ops,875			.parent_hws = (const struct clk_hw *[]) {876				&clk_pll[VC3_PLL3].hw877			},878			.num_parents = 1,879			.flags = CLK_SET_RATE_PARENT880		}881	}882};883 884static struct vc3_hw_data clk_mux[] = {885	[VC3_SE1_MUX] = {886		.data = &(struct vc3_clk_data) {887			.offs = VC3_SE1_DIV4_CTRL,888			.bitmsk = VC3_SE1_DIV4_CTRL_SE1_CLK_SEL889		},890		.hw.init = &(struct clk_init_data) {891			.name = "se1_mux",892			.ops = &vc3_clk_mux_ops,893			.parent_hws = (const struct clk_hw *[]) {894				&clk_div[VC3_DIV5].hw,895				&clk_div[VC3_DIV4].hw896			},897			.num_parents = 2,898			.flags = CLK_SET_RATE_PARENT899		}900	},901	[VC3_SE2_MUX] = {902		.data = &(struct vc3_clk_data) {903			.offs = VC3_SE2_CTRL_REG0,904			.bitmsk = VC3_SE2_CTRL_REG0_SE2_CLK_SEL905		},906		.hw.init = &(struct clk_init_data) {907			.name = "se2_mux",908			.ops = &vc3_clk_mux_ops,909			.parent_hws = (const struct clk_hw *[]) {910				&clk_div[VC3_DIV5].hw,911				&clk_div[VC3_DIV4].hw912			},913			.num_parents = 2,914			.flags = CLK_SET_RATE_PARENT915		}916	},917	[VC3_SE3_MUX] = {918		.data = &(struct vc3_clk_data) {919			.offs = VC3_SE3_DIFF1_CTRL_REG,920			.bitmsk = VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL921		},922		.hw.init = &(struct clk_init_data) {923			.name = "se3_mux",924			.ops = &vc3_clk_mux_ops,925			.parent_hws = (const struct clk_hw *[]) {926				&clk_div[VC3_DIV2].hw,927				&clk_div[VC3_DIV4].hw928			},929			.num_parents = 2,930			.flags = CLK_SET_RATE_PARENT931		}932	},933	[VC3_DIFF1_MUX] = {934		.data = &(struct vc3_clk_data) {935			.offs = VC3_DIFF1_CTRL_REG,936			.bitmsk = VC3_DIFF1_CTRL_REG_DIFF1_CLK_SEL937		},938		.hw.init = &(struct clk_init_data) {939			.name = "diff1_mux",940			.ops = &vc3_clk_mux_ops,941			.parent_hws = (const struct clk_hw *[]) {942				&clk_div[VC3_DIV1].hw,943				&clk_div[VC3_DIV3].hw944			},945			.num_parents = 2,946			.flags = CLK_SET_RATE_PARENT947		}948	},949	[VC3_DIFF2_MUX] = {950		.data = &(struct vc3_clk_data) {951			.offs = VC3_DIFF2_CTRL_REG,952			.bitmsk = VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL953		},954		.hw.init = &(struct clk_init_data) {955			.name = "diff2_mux",956			.ops = &vc3_clk_mux_ops,957			.parent_hws = (const struct clk_hw *[]) {958				&clk_div[VC3_DIV1].hw,959				&clk_div[VC3_DIV3].hw960			},961			.num_parents = 2,962			.flags = CLK_SET_RATE_PARENT963		}964	}965};966 967static struct clk_hw *vc3_of_clk_get(struct of_phandle_args *clkspec,968				     void *data)969{970	unsigned int idx = clkspec->args[0];971	struct clk_hw **clkout_hw = data;972 973	if (idx >= ARRAY_SIZE(clk_out)) {974		pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np);975		return ERR_PTR(-EINVAL);976	}977 978	return clkout_hw[idx];979}980 981static int vc3_probe(struct i2c_client *client)982{983	struct device *dev = &client->dev;984	u8 settings[NUM_CONFIG_REGISTERS];985	struct regmap *regmap;986	const char *name;987	int ret, i;988 989	regmap = devm_regmap_init_i2c(client, &vc3_regmap_config);990	if (IS_ERR(regmap))991		return dev_err_probe(dev, PTR_ERR(regmap),992				     "failed to allocate register map\n");993 994	ret = of_property_read_u8_array(dev->of_node, "renesas,settings",995					settings, ARRAY_SIZE(settings));996	if (!ret) {997		/*998		 * A raw settings array was specified in the DT. Write the999		 * settings to the device immediately.1000		 */1001		for  (i = 0; i < NUM_CONFIG_REGISTERS; i++) {1002			ret = regmap_write(regmap, i, settings[i]);1003			if (ret) {1004				dev_err(dev, "error writing to chip (%i)\n", ret);1005				return ret;1006			}1007		}1008	} else if (ret == -EOVERFLOW) {1009		dev_err(&client->dev, "EOVERFLOW reg settings. ARRAY_SIZE: %zu\n",1010			ARRAY_SIZE(settings));1011		return ret;1012	}1013 1014	/* Register pfd muxes */1015	for (i = 0; i < ARRAY_SIZE(clk_pfd_mux); i++) {1016		clk_pfd_mux[i].regmap = regmap;1017		ret = devm_clk_hw_register(dev, &clk_pfd_mux[i].hw);1018		if (ret)1019			return dev_err_probe(dev, ret, "%s failed\n",1020					     clk_pfd_mux[i].hw.init->name);1021	}1022 1023	/* Register pfd's */1024	for (i = 0; i < ARRAY_SIZE(clk_pfd); i++) {1025		clk_pfd[i].regmap = regmap;1026		ret = devm_clk_hw_register(dev, &clk_pfd[i].hw);1027		if (ret)1028			return dev_err_probe(dev, ret, "%s failed\n",1029					     clk_pfd[i].hw.init->name);1030	}1031 1032	/* Register pll's */1033	for (i = 0; i < ARRAY_SIZE(clk_pll); i++) {1034		clk_pll[i].regmap = regmap;1035		ret = devm_clk_hw_register(dev, &clk_pll[i].hw);1036		if (ret)1037			return dev_err_probe(dev, ret, "%s failed\n",1038					     clk_pll[i].hw.init->name);1039	}1040 1041	/* Register divider muxes */1042	for (i = 0; i < ARRAY_SIZE(clk_div_mux); i++) {1043		clk_div_mux[i].regmap = regmap;1044		ret = devm_clk_hw_register(dev, &clk_div_mux[i].hw);1045		if (ret)1046			return dev_err_probe(dev, ret, "%s failed\n",1047					     clk_div_mux[i].hw.init->name);1048	}1049 1050	/* Register dividers */1051	for (i = 0; i < ARRAY_SIZE(clk_div); i++) {1052		clk_div[i].regmap = regmap;1053		ret = devm_clk_hw_register(dev, &clk_div[i].hw);1054		if (ret)1055			return dev_err_probe(dev, ret, "%s failed\n",1056					     clk_div[i].hw.init->name);1057	}1058 1059	/* Register clk muxes */1060	for (i = 0; i < ARRAY_SIZE(clk_mux); i++) {1061		clk_mux[i].regmap = regmap;1062		ret = devm_clk_hw_register(dev, &clk_mux[i].hw);1063		if (ret)1064			return dev_err_probe(dev, ret, "%s failed\n",1065					     clk_mux[i].hw.init->name);1066	}1067 1068	/* Register clk outputs */1069	for (i = 0; i < ARRAY_SIZE(clk_out); i++) {1070		switch (i) {1071		case VC3_DIFF2:1072			name = "diff2";1073			break;1074		case VC3_DIFF1:1075			name = "diff1";1076			break;1077		case VC3_SE3:1078			name = "se3";1079			break;1080		case VC3_SE2:1081			name = "se2";1082			break;1083		case VC3_SE1:1084			name = "se1";1085			break;1086		case VC3_REF:1087			name = "ref";1088			break;1089		default:1090			return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i);1091		}1092 1093		if (i == VC3_REF)1094			clk_out[i] = devm_clk_hw_register_fixed_factor_index(dev,1095				name, 0, CLK_SET_RATE_PARENT, 1, 1);1096		else1097			clk_out[i] = devm_clk_hw_register_fixed_factor_parent_hw(dev,1098				name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1);1099 1100		if (IS_ERR(clk_out[i]))1101			return PTR_ERR(clk_out[i]);1102	}1103 1104	ret = devm_of_clk_add_hw_provider(dev, vc3_of_clk_get, clk_out);1105	if (ret)1106		return dev_err_probe(dev, ret, "unable to add clk provider\n");1107 1108	return ret;1109}1110 1111static const struct of_device_id dev_ids[] = {1112	{ .compatible = "renesas,5p35023" },1113	{ /* Sentinel */ }1114};1115MODULE_DEVICE_TABLE(of, dev_ids);1116 1117static struct i2c_driver vc3_driver = {1118	.driver = {1119		.name = "vc3",1120		.of_match_table = of_match_ptr(dev_ids),1121	},1122	.probe = vc3_probe,1123};1124module_i2c_driver(vc3_driver);1125 1126MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");1127MODULE_DESCRIPTION("Renesas VersaClock 3 driver");1128MODULE_LICENSE("GPL");1129