clk: Renesas versaclock7 ccf device driver

Renesas Versaclock7 is a family of configurable clock generator ICs
with fractional and integer dividers. This driver has basic support
for the RC21008A device, a clock synthesizer with a crystal input and
8 outputs. The supports changing the FOD and IOD rates, and each
output can be gated.

Signed-off-by: Alex Helms <alexander.helms.jy@renesas.com>
Link: https://lore.kernel.org/r/20220912183613.22213-3-alexander.helms.jy@renesas.com
Tested-by: Saeed Nowshadi <saeed.nowshadi@amd.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by Alex Helms and committed by Stephen Boyd 48c5e98f 09d18556

+1322
+1
MAINTAINERS
··· 17445 17445 M: Alex Helms <alexander.helms.jy@renesas.com> 17446 17446 S: Maintained 17447 17447 F: Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml 17448 + F: drivers/clk/clk-versaclock7.c 17448 17449 17449 17450 RESET CONTROLLER FRAMEWORK 17450 17451 M: Philipp Zabel <p.zabel@pengutronix.de>
+9
drivers/clk/Kconfig
··· 377 377 This driver supports the IDT VersaClock 5 and VersaClock 6 378 378 programmable clock generators. 379 379 380 + config COMMON_CLK_VC7 381 + tristate "Clock driver for Renesas Versaclock 7 devices" 382 + depends on I2C 383 + depends on OF 384 + select REGMAP_I2C 385 + help 386 + Renesas Versaclock7 is a family of configurable clock generator 387 + and jitter attenuator ICs with fractional and integer dividers. 388 + 380 389 config COMMON_CLK_STM32MP135 381 390 def_bool COMMON_CLK && MACH_STM32MP13 382 391 help
+1
drivers/clk/Makefile
··· 73 73 obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o 74 74 obj-$(CONFIG_COMMON_CLK_RS9_PCIE) += clk-renesas-pcie.o 75 75 obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o 76 + obj-$(CONFIG_COMMON_CLK_VC7) += clk-versaclock7.o 76 77 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o 77 78 obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o 78 79
+1311
drivers/clk/clk-versaclock7.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Common clock framework driver for the Versaclock7 family of timing devices. 4 + * 5 + * Copyright (c) 2022 Renesas Electronics Corporation 6 + */ 7 + 8 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 + 10 + #include <linux/bitfield.h> 11 + #include <linux/clk.h> 12 + #include <linux/clk-provider.h> 13 + #include <linux/i2c.h> 14 + #include <linux/math64.h> 15 + #include <linux/module.h> 16 + #include <linux/of.h> 17 + #include <linux/of_platform.h> 18 + #include <linux/regmap.h> 19 + #include <linux/swab.h> 20 + 21 + /* 22 + * 16-bit register address: the lower 8 bits of the register address come 23 + * from the offset addr byte and the upper 8 bits come from the page register. 24 + */ 25 + #define VC7_PAGE_ADDR 0xFD 26 + #define VC7_PAGE_WINDOW 256 27 + #define VC7_MAX_REG 0x364 28 + 29 + /* Maximum number of banks supported by VC7 */ 30 + #define VC7_NUM_BANKS 7 31 + 32 + /* Maximum number of FODs supported by VC7 */ 33 + #define VC7_NUM_FOD 3 34 + 35 + /* Maximum number of IODs supported by VC7 */ 36 + #define VC7_NUM_IOD 4 37 + 38 + /* Maximum number of outputs supported by VC7 */ 39 + #define VC7_NUM_OUT 12 40 + 41 + /* VCO valid range is 9.5 GHz to 10.7 GHz */ 42 + #define VC7_APLL_VCO_MIN 9500000000UL 43 + #define VC7_APLL_VCO_MAX 10700000000UL 44 + 45 + /* APLL denominator is fixed at 2^27 */ 46 + #define VC7_APLL_DENOMINATOR_BITS 27 47 + 48 + /* FOD 1st stage denominator is fixed 2^34 */ 49 + #define VC7_FOD_DENOMINATOR_BITS 34 50 + 51 + /* IOD can operate between 1kHz and 650MHz */ 52 + #define VC7_IOD_RATE_MIN 1000UL 53 + #define VC7_IOD_RATE_MAX 650000000UL 54 + #define VC7_IOD_MIN_DIVISOR 14 55 + #define VC7_IOD_MAX_DIVISOR 0x1ffffff /* 25-bit */ 56 + 57 + #define VC7_FOD_RATE_MIN 1000UL 58 + #define VC7_FOD_RATE_MAX 650000000UL 59 + #define VC7_FOD_1ST_STAGE_RATE_MIN 33000000UL /* 33 MHz */ 60 + #define VC7_FOD_1ST_STAGE_RATE_MAX 650000000UL /* 650 MHz */ 61 + #define VC7_FOD_1ST_INT_MAX 324 62 + #define VC7_FOD_2ND_INT_MIN 2 63 + #define VC7_FOD_2ND_INT_MAX 0x1ffff /* 17-bit */ 64 + 65 + /* VC7 Registers */ 66 + 67 + #define VC7_REG_XO_CNFG 0x2C 68 + #define VC7_REG_XO_CNFG_COUNT 4 69 + #define VC7_REG_XO_IB_H_DIV_SHIFT 24 70 + #define VC7_REG_XO_IB_H_DIV_MASK GENMASK(28, VC7_REG_XO_IB_H_DIV_SHIFT) 71 + 72 + #define VC7_REG_APLL_FB_DIV_FRAC 0x120 73 + #define VC7_REG_APLL_FB_DIV_FRAC_COUNT 4 74 + #define VC7_REG_APLL_FB_DIV_FRAC_MASK GENMASK(26, 0) 75 + 76 + #define VC7_REG_APLL_FB_DIV_INT 0x124 77 + #define VC7_REG_APLL_FB_DIV_INT_COUNT 2 78 + #define VC7_REG_APLL_FB_DIV_INT_MASK GENMASK(9, 0) 79 + 80 + #define VC7_REG_APLL_CNFG 0x127 81 + #define VC7_REG_APLL_EN_DOUBLER BIT(0) 82 + 83 + #define VC7_REG_OUT_BANK_CNFG(idx) (0x280 + (0x4 * (idx))) 84 + #define VC7_REG_OUTPUT_BANK_SRC_MASK GENMASK(2, 0) 85 + 86 + #define VC7_REG_FOD_INT_CNFG(idx) (0x1E0 + (0x10 * (idx))) 87 + #define VC7_REG_FOD_INT_CNFG_COUNT 8 88 + #define VC7_REG_FOD_1ST_INT_MASK GENMASK(8, 0) 89 + #define VC7_REG_FOD_2ND_INT_SHIFT 9 90 + #define VC7_REG_FOD_2ND_INT_MASK GENMASK(25, VC7_REG_FOD_2ND_INT_SHIFT) 91 + #define VC7_REG_FOD_FRAC_SHIFT 26 92 + #define VC7_REG_FOD_FRAC_MASK GENMASK_ULL(59, VC7_REG_FOD_FRAC_SHIFT) 93 + 94 + #define VC7_REG_IOD_INT_CNFG(idx) (0x1C0 + (0x8 * (idx))) 95 + #define VC7_REG_IOD_INT_CNFG_COUNT 4 96 + #define VC7_REG_IOD_INT_MASK GENMASK(24, 0) 97 + 98 + #define VC7_REG_ODRV_EN(idx) (0x240 + (0x4 * (idx))) 99 + #define VC7_REG_OUT_DIS BIT(0) 100 + 101 + struct vc7_driver_data; 102 + static const struct regmap_config vc7_regmap_config; 103 + 104 + /* Supported Renesas VC7 models */ 105 + enum vc7_model { 106 + VC7_RC21008A, 107 + }; 108 + 109 + struct vc7_chip_info { 110 + const enum vc7_model model; 111 + const unsigned int banks[VC7_NUM_BANKS]; 112 + const unsigned int num_banks; 113 + const unsigned int outputs[VC7_NUM_OUT]; 114 + const unsigned int num_outputs; 115 + }; 116 + 117 + /* 118 + * Changing the APLL frequency is currently not supported. 119 + * The APLL will consist of an opaque block between the XO and FOD/IODs and 120 + * its frequency will be computed based on the current state of the device. 121 + */ 122 + struct vc7_apll_data { 123 + struct clk *clk; 124 + struct vc7_driver_data *vc7; 125 + u8 xo_ib_h_div; 126 + u8 en_doubler; 127 + u16 apll_fb_div_int; 128 + u32 apll_fb_div_frac; 129 + }; 130 + 131 + struct vc7_fod_data { 132 + struct clk_hw hw; 133 + struct vc7_driver_data *vc7; 134 + unsigned int num; 135 + u32 fod_1st_int; 136 + u32 fod_2nd_int; 137 + u64 fod_frac; 138 + }; 139 + 140 + struct vc7_iod_data { 141 + struct clk_hw hw; 142 + struct vc7_driver_data *vc7; 143 + unsigned int num; 144 + u32 iod_int; 145 + }; 146 + 147 + struct vc7_out_data { 148 + struct clk_hw hw; 149 + struct vc7_driver_data *vc7; 150 + unsigned int num; 151 + unsigned int out_dis; 152 + }; 153 + 154 + struct vc7_driver_data { 155 + struct i2c_client *client; 156 + struct regmap *regmap; 157 + const struct vc7_chip_info *chip_info; 158 + 159 + struct clk *pin_xin; 160 + struct vc7_apll_data clk_apll; 161 + struct vc7_fod_data clk_fod[VC7_NUM_FOD]; 162 + struct vc7_iod_data clk_iod[VC7_NUM_IOD]; 163 + struct vc7_out_data clk_out[VC7_NUM_OUT]; 164 + }; 165 + 166 + struct vc7_bank_src_map { 167 + enum vc7_bank_src_type { 168 + VC7_FOD, 169 + VC7_IOD, 170 + } type; 171 + union _divider { 172 + struct vc7_iod_data *iod; 173 + struct vc7_fod_data *fod; 174 + } src; 175 + }; 176 + 177 + static struct clk_hw *vc7_of_clk_get(struct of_phandle_args *clkspec, 178 + void *data) 179 + { 180 + struct vc7_driver_data *vc7 = data; 181 + unsigned int idx = clkspec->args[0]; 182 + 183 + if (idx >= vc7->chip_info->num_outputs) 184 + return ERR_PTR(-EINVAL); 185 + 186 + return &vc7->clk_out[idx].hw; 187 + } 188 + 189 + static const unsigned int RC21008A_index_to_output_mapping[] = { 190 + 1, 2, 3, 6, 7, 8, 10, 11 191 + }; 192 + 193 + static int vc7_map_index_to_output(const enum vc7_model model, const unsigned int i) 194 + { 195 + switch (model) { 196 + case VC7_RC21008A: 197 + return RC21008A_index_to_output_mapping[i]; 198 + default: 199 + return i; 200 + } 201 + } 202 + 203 + /* bank to output mapping, same across all variants */ 204 + static const unsigned int output_bank_mapping[] = { 205 + 0, /* Output 0 */ 206 + 1, /* Output 1 */ 207 + 2, /* Output 2 */ 208 + 2, /* Output 3 */ 209 + 3, /* Output 4 */ 210 + 3, /* Output 5 */ 211 + 3, /* Output 6 */ 212 + 3, /* Output 7 */ 213 + 4, /* Output 8 */ 214 + 4, /* Output 9 */ 215 + 5, /* Output 10 */ 216 + 6 /* Output 11 */ 217 + }; 218 + 219 + /** 220 + * vc7_64_mul_64_to_128() - Multiply two u64 and return an unsigned 128-bit integer 221 + * as an upper and lower part. 222 + * 223 + * @left: The left argument. 224 + * @right: The right argument. 225 + * @hi: The upper 64-bits of the 128-bit product. 226 + * @lo: The lower 64-bits of the 128-bit product. 227 + * 228 + * From mul_64_64 in crypto/ecc.c:350 in the linux kernel, accessed in v5.17.2. 229 + */ 230 + static void vc7_64_mul_64_to_128(u64 left, u64 right, u64 *hi, u64 *lo) 231 + { 232 + u64 a0 = left & 0xffffffffull; 233 + u64 a1 = left >> 32; 234 + u64 b0 = right & 0xffffffffull; 235 + u64 b1 = right >> 32; 236 + u64 m0 = a0 * b0; 237 + u64 m1 = a0 * b1; 238 + u64 m2 = a1 * b0; 239 + u64 m3 = a1 * b1; 240 + 241 + m2 += (m0 >> 32); 242 + m2 += m1; 243 + 244 + /* Overflow */ 245 + if (m2 < m1) 246 + m3 += 0x100000000ull; 247 + 248 + *lo = (m0 & 0xffffffffull) | (m2 << 32); 249 + *hi = m3 + (m2 >> 32); 250 + } 251 + 252 + /** 253 + * vc7_128_div_64_to_64() - Divides a 128-bit uint by a 64-bit divisor, return a 64-bit quotient. 254 + * 255 + * @numhi: The uppper 64-bits of the dividend. 256 + * @numlo: The lower 64-bits of the dividend. 257 + * @den: The denominator (divisor). 258 + * @r: The remainder, pass NULL if the remainder is not needed. 259 + * 260 + * Originally from libdivide, modified to use kernel u64/u32 types. 261 + * 262 + * See https://github.com/ridiculousfish/libdivide/blob/master/libdivide.h#L471. 263 + * 264 + * Return: The 64-bit quotient of the division. 265 + * 266 + * In case of overflow of division by zero, max(u64) is returned. 267 + */ 268 + static u64 vc7_128_div_64_to_64(u64 numhi, u64 numlo, u64 den, u64 *r) 269 + { 270 + /* 271 + * We work in base 2**32. 272 + * A uint32 holds a single digit. A uint64 holds two digits. 273 + * Our numerator is conceptually [num3, num2, num1, num0]. 274 + * Our denominator is [den1, den0]. 275 + */ 276 + const u64 b = ((u64)1 << 32); 277 + 278 + /* The high and low digits of our computed quotient. */ 279 + u32 q1, q0; 280 + 281 + /* The normalization shift factor */ 282 + int shift; 283 + 284 + /* 285 + * The high and low digits of our denominator (after normalizing). 286 + * Also the low 2 digits of our numerator (after normalizing). 287 + */ 288 + u32 den1, den0, num1, num0; 289 + 290 + /* A partial remainder; */ 291 + u64 rem; 292 + 293 + /* 294 + * The estimated quotient, and its corresponding remainder (unrelated 295 + * to true remainder). 296 + */ 297 + u64 qhat, rhat; 298 + 299 + /* Variables used to correct the estimated quotient. */ 300 + u64 c1, c2; 301 + 302 + /* Check for overflow and divide by 0. */ 303 + if (numhi >= den) { 304 + if (r) 305 + *r = ~0ull; 306 + return ~0ull; 307 + } 308 + 309 + /* 310 + * Determine the normalization factor. We multiply den by this, so that 311 + * its leading digit is at least half b. In binary this means just 312 + * shifting left by the number of leading zeros, so that there's a 1 in 313 + * the MSB. 314 + * 315 + * We also shift numer by the same amount. This cannot overflow because 316 + * numhi < den. The expression (-shift & 63) is the same as (64 - 317 + * shift), except it avoids the UB of shifting by 64. The funny bitwise 318 + * 'and' ensures that numlo does not get shifted into numhi if shift is 319 + * 0. clang 11 has an x86 codegen bug here: see LLVM bug 50118. The 320 + * sequence below avoids it. 321 + */ 322 + shift = __builtin_clzll(den); 323 + den <<= shift; 324 + numhi <<= shift; 325 + numhi |= (numlo >> (-shift & 63)) & (-(s64)shift >> 63); 326 + numlo <<= shift; 327 + 328 + /* 329 + * Extract the low digits of the numerator and both digits of the 330 + * denominator. 331 + */ 332 + num1 = (u32)(numlo >> 32); 333 + num0 = (u32)(numlo & 0xFFFFFFFFu); 334 + den1 = (u32)(den >> 32); 335 + den0 = (u32)(den & 0xFFFFFFFFu); 336 + 337 + /* 338 + * We wish to compute q1 = [n3 n2 n1] / [d1 d0]. 339 + * Estimate q1 as [n3 n2] / [d1], and then correct it. 340 + * Note while qhat may be 2 digits, q1 is always 1 digit. 341 + */ 342 + qhat = div64_u64_rem(numhi, den1, &rhat); 343 + c1 = qhat * den0; 344 + c2 = rhat * b + num1; 345 + if (c1 > c2) 346 + qhat -= (c1 - c2 > den) ? 2 : 1; 347 + q1 = (u32)qhat; 348 + 349 + /* Compute the true (partial) remainder. */ 350 + rem = numhi * b + num1 - q1 * den; 351 + 352 + /* 353 + * We wish to compute q0 = [rem1 rem0 n0] / [d1 d0]. 354 + * Estimate q0 as [rem1 rem0] / [d1] and correct it. 355 + */ 356 + qhat = div64_u64_rem(rem, den1, &rhat); 357 + c1 = qhat * den0; 358 + c2 = rhat * b + num0; 359 + if (c1 > c2) 360 + qhat -= (c1 - c2 > den) ? 2 : 1; 361 + q0 = (u32)qhat; 362 + 363 + /* Return remainder if requested. */ 364 + if (r) 365 + *r = (rem * b + num0 - q0 * den) >> shift; 366 + return ((u64)q1 << 32) | q0; 367 + } 368 + 369 + static int vc7_get_bank_clk(struct vc7_driver_data *vc7, 370 + unsigned int bank_idx, 371 + unsigned int output_bank_src, 372 + struct vc7_bank_src_map *map) 373 + { 374 + /* Mapping from Table 38 in datasheet */ 375 + if (bank_idx == 0 || bank_idx == 1) { 376 + switch (output_bank_src) { 377 + case 0: 378 + map->type = VC7_IOD, 379 + map->src.iod = &vc7->clk_iod[0]; 380 + return 0; 381 + case 1: 382 + map->type = VC7_IOD, 383 + map->src.iod = &vc7->clk_iod[1]; 384 + return 0; 385 + case 4: 386 + map->type = VC7_FOD, 387 + map->src.fod = &vc7->clk_fod[0]; 388 + return 0; 389 + case 5: 390 + map->type = VC7_FOD, 391 + map->src.fod = &vc7->clk_fod[1]; 392 + return 0; 393 + default: 394 + break; 395 + } 396 + } else if (bank_idx == 2) { 397 + switch (output_bank_src) { 398 + case 1: 399 + map->type = VC7_IOD, 400 + map->src.iod = &vc7->clk_iod[1]; 401 + return 0; 402 + case 4: 403 + map->type = VC7_FOD, 404 + map->src.fod = &vc7->clk_fod[0]; 405 + return 0; 406 + case 5: 407 + map->type = VC7_FOD, 408 + map->src.fod = &vc7->clk_fod[1]; 409 + return 0; 410 + default: 411 + break; 412 + } 413 + } else if (bank_idx == 3) { 414 + switch (output_bank_src) { 415 + case 4: 416 + map->type = VC7_FOD, 417 + map->src.fod = &vc7->clk_fod[0]; 418 + return 0; 419 + case 5: 420 + map->type = VC7_FOD, 421 + map->src.fod = &vc7->clk_fod[1]; 422 + return 0; 423 + case 6: 424 + map->type = VC7_FOD, 425 + map->src.fod = &vc7->clk_fod[2]; 426 + return 0; 427 + default: 428 + break; 429 + } 430 + } else if (bank_idx == 4) { 431 + switch (output_bank_src) { 432 + case 0: 433 + /* CLKIN1 not supported in this driver */ 434 + break; 435 + case 2: 436 + map->type = VC7_IOD, 437 + map->src.iod = &vc7->clk_iod[2]; 438 + return 0; 439 + case 5: 440 + map->type = VC7_FOD, 441 + map->src.fod = &vc7->clk_fod[1]; 442 + return 0; 443 + case 6: 444 + map->type = VC7_FOD, 445 + map->src.fod = &vc7->clk_fod[2]; 446 + return 0; 447 + case 7: 448 + /* CLKIN0 not supported in this driver */ 449 + break; 450 + default: 451 + break; 452 + } 453 + } else if (bank_idx == 5) { 454 + switch (output_bank_src) { 455 + case 0: 456 + /* CLKIN1 not supported in this driver */ 457 + break; 458 + case 1: 459 + /* XIN_REFIN not supported in this driver */ 460 + break; 461 + case 2: 462 + map->type = VC7_IOD, 463 + map->src.iod = &vc7->clk_iod[2]; 464 + return 0; 465 + case 3: 466 + map->type = VC7_IOD, 467 + map->src.iod = &vc7->clk_iod[3]; 468 + return 0; 469 + case 5: 470 + map->type = VC7_FOD, 471 + map->src.fod = &vc7->clk_fod[1]; 472 + return 0; 473 + case 6: 474 + map->type = VC7_FOD, 475 + map->src.fod = &vc7->clk_fod[2]; 476 + return 0; 477 + case 7: 478 + /* CLKIN0 not supported in this driver */ 479 + break; 480 + default: 481 + break; 482 + } 483 + } else if (bank_idx == 6) { 484 + switch (output_bank_src) { 485 + case 0: 486 + /* CLKIN1 not supported in this driver */ 487 + break; 488 + case 2: 489 + map->type = VC7_IOD, 490 + map->src.iod = &vc7->clk_iod[2]; 491 + return 0; 492 + case 3: 493 + map->type = VC7_IOD, 494 + map->src.iod = &vc7->clk_iod[3]; 495 + return 0; 496 + case 5: 497 + map->type = VC7_FOD, 498 + map->src.fod = &vc7->clk_fod[1]; 499 + return 0; 500 + case 6: 501 + map->type = VC7_FOD, 502 + map->src.fod = &vc7->clk_fod[2]; 503 + return 0; 504 + case 7: 505 + /* CLKIN0 not supported in this driver */ 506 + break; 507 + default: 508 + break; 509 + } 510 + } 511 + 512 + pr_warn("bank_src%d = %d is not supported\n", bank_idx, output_bank_src); 513 + return -1; 514 + } 515 + 516 + static int vc7_read_apll(struct vc7_driver_data *vc7) 517 + { 518 + int err; 519 + u32 val32; 520 + u16 val16; 521 + 522 + err = regmap_bulk_read(vc7->regmap, 523 + VC7_REG_XO_CNFG, 524 + (u32 *)&val32, 525 + VC7_REG_XO_CNFG_COUNT); 526 + if (err) { 527 + dev_err(&vc7->client->dev, "failed to read XO_CNFG\n"); 528 + return err; 529 + } 530 + 531 + vc7->clk_apll.xo_ib_h_div = (val32 & VC7_REG_XO_IB_H_DIV_MASK) 532 + >> VC7_REG_XO_IB_H_DIV_SHIFT; 533 + 534 + err = regmap_read(vc7->regmap, 535 + VC7_REG_APLL_CNFG, 536 + &val32); 537 + if (err) { 538 + dev_err(&vc7->client->dev, "failed to read APLL_CNFG\n"); 539 + return err; 540 + } 541 + 542 + vc7->clk_apll.en_doubler = val32 & VC7_REG_APLL_EN_DOUBLER; 543 + 544 + err = regmap_bulk_read(vc7->regmap, 545 + VC7_REG_APLL_FB_DIV_FRAC, 546 + (u32 *)&val32, 547 + VC7_REG_APLL_FB_DIV_FRAC_COUNT); 548 + if (err) { 549 + dev_err(&vc7->client->dev, "failed to read APLL_FB_DIV_FRAC\n"); 550 + return err; 551 + } 552 + 553 + vc7->clk_apll.apll_fb_div_frac = val32 & VC7_REG_APLL_FB_DIV_FRAC_MASK; 554 + 555 + err = regmap_bulk_read(vc7->regmap, 556 + VC7_REG_APLL_FB_DIV_INT, 557 + (u16 *)&val16, 558 + VC7_REG_APLL_FB_DIV_INT_COUNT); 559 + if (err) { 560 + dev_err(&vc7->client->dev, "failed to read APLL_FB_DIV_INT\n"); 561 + return err; 562 + } 563 + 564 + vc7->clk_apll.apll_fb_div_int = val16 & VC7_REG_APLL_FB_DIV_INT_MASK; 565 + 566 + return 0; 567 + } 568 + 569 + static int vc7_read_fod(struct vc7_driver_data *vc7, unsigned int idx) 570 + { 571 + int err; 572 + u64 val; 573 + 574 + err = regmap_bulk_read(vc7->regmap, 575 + VC7_REG_FOD_INT_CNFG(idx), 576 + (u64 *)&val, 577 + VC7_REG_FOD_INT_CNFG_COUNT); 578 + if (err) { 579 + dev_err(&vc7->client->dev, "failed to read FOD%d\n", idx); 580 + return err; 581 + } 582 + 583 + vc7->clk_fod[idx].fod_1st_int = (val & VC7_REG_FOD_1ST_INT_MASK); 584 + vc7->clk_fod[idx].fod_2nd_int = 585 + (val & VC7_REG_FOD_2ND_INT_MASK) >> VC7_REG_FOD_2ND_INT_SHIFT; 586 + vc7->clk_fod[idx].fod_frac = (val & VC7_REG_FOD_FRAC_MASK) 587 + >> VC7_REG_FOD_FRAC_SHIFT; 588 + 589 + return 0; 590 + } 591 + 592 + static int vc7_write_fod(struct vc7_driver_data *vc7, unsigned int idx) 593 + { 594 + int err; 595 + u64 val; 596 + 597 + /* 598 + * FOD dividers are part of an atomic group where fod_1st_int, 599 + * fod_2nd_int, and fod_frac must be written together. The new divider 600 + * is applied when the MSB of fod_frac is written. 601 + */ 602 + 603 + err = regmap_bulk_read(vc7->regmap, 604 + VC7_REG_FOD_INT_CNFG(idx), 605 + (u64 *)&val, 606 + VC7_REG_FOD_INT_CNFG_COUNT); 607 + if (err) { 608 + dev_err(&vc7->client->dev, "failed to read FOD%d\n", idx); 609 + return err; 610 + } 611 + 612 + val = u64_replace_bits(val, 613 + vc7->clk_fod[idx].fod_1st_int, 614 + VC7_REG_FOD_1ST_INT_MASK); 615 + val = u64_replace_bits(val, 616 + vc7->clk_fod[idx].fod_2nd_int, 617 + VC7_REG_FOD_2ND_INT_MASK); 618 + val = u64_replace_bits(val, 619 + vc7->clk_fod[idx].fod_frac, 620 + VC7_REG_FOD_FRAC_MASK); 621 + 622 + err = regmap_bulk_write(vc7->regmap, 623 + VC7_REG_FOD_INT_CNFG(idx), 624 + (u64 *)&val, 625 + sizeof(u64)); 626 + if (err) { 627 + dev_err(&vc7->client->dev, "failed to write FOD%d\n", idx); 628 + return err; 629 + } 630 + 631 + return 0; 632 + } 633 + 634 + static int vc7_read_iod(struct vc7_driver_data *vc7, unsigned int idx) 635 + { 636 + int err; 637 + u32 val; 638 + 639 + err = regmap_bulk_read(vc7->regmap, 640 + VC7_REG_IOD_INT_CNFG(idx), 641 + (u32 *)&val, 642 + VC7_REG_IOD_INT_CNFG_COUNT); 643 + if (err) { 644 + dev_err(&vc7->client->dev, "failed to read IOD%d\n", idx); 645 + return err; 646 + } 647 + 648 + vc7->clk_iod[idx].iod_int = (val & VC7_REG_IOD_INT_MASK); 649 + 650 + return 0; 651 + } 652 + 653 + static int vc7_write_iod(struct vc7_driver_data *vc7, unsigned int idx) 654 + { 655 + int err; 656 + u32 val; 657 + 658 + /* 659 + * IOD divider field is atomic and all bits must be written. 660 + * The new divider is applied when the MSB of iod_int is written. 661 + */ 662 + 663 + err = regmap_bulk_read(vc7->regmap, 664 + VC7_REG_IOD_INT_CNFG(idx), 665 + (u32 *)&val, 666 + VC7_REG_IOD_INT_CNFG_COUNT); 667 + if (err) { 668 + dev_err(&vc7->client->dev, "failed to read IOD%d\n", idx); 669 + return err; 670 + } 671 + 672 + val = u32_replace_bits(val, 673 + vc7->clk_iod[idx].iod_int, 674 + VC7_REG_IOD_INT_MASK); 675 + 676 + err = regmap_bulk_write(vc7->regmap, 677 + VC7_REG_IOD_INT_CNFG(idx), 678 + (u32 *)&val, 679 + sizeof(u32)); 680 + if (err) { 681 + dev_err(&vc7->client->dev, "failed to write IOD%d\n", idx); 682 + return err; 683 + } 684 + 685 + return 0; 686 + } 687 + 688 + static int vc7_read_output(struct vc7_driver_data *vc7, unsigned int idx) 689 + { 690 + int err; 691 + unsigned int val, out_num; 692 + 693 + out_num = vc7_map_index_to_output(vc7->chip_info->model, idx); 694 + err = regmap_read(vc7->regmap, 695 + VC7_REG_ODRV_EN(out_num), 696 + &val); 697 + if (err) { 698 + dev_err(&vc7->client->dev, "failed to read ODRV_EN[%d]\n", idx); 699 + return err; 700 + } 701 + 702 + vc7->clk_out[idx].out_dis = val & VC7_REG_OUT_DIS; 703 + 704 + return 0; 705 + } 706 + 707 + static int vc7_write_output(struct vc7_driver_data *vc7, unsigned int idx) 708 + { 709 + int err; 710 + unsigned int out_num; 711 + 712 + out_num = vc7_map_index_to_output(vc7->chip_info->model, idx); 713 + err = regmap_write_bits(vc7->regmap, 714 + VC7_REG_ODRV_EN(out_num), 715 + VC7_REG_OUT_DIS, 716 + vc7->clk_out[idx].out_dis); 717 + 718 + if (err) { 719 + dev_err(&vc7->client->dev, "failed to write ODRV_EN[%d]\n", idx); 720 + return err; 721 + } 722 + 723 + return 0; 724 + } 725 + 726 + static unsigned long vc7_get_apll_rate(struct vc7_driver_data *vc7) 727 + { 728 + int err; 729 + unsigned long xtal_rate; 730 + u64 refin_div, apll_rate; 731 + 732 + xtal_rate = clk_get_rate(vc7->pin_xin); 733 + err = vc7_read_apll(vc7); 734 + if (err) { 735 + dev_err(&vc7->client->dev, "unable to read apll\n"); 736 + return err; 737 + } 738 + 739 + /* 0 is bypassed, 1 is reserved */ 740 + if (vc7->clk_apll.xo_ib_h_div < 2) 741 + refin_div = xtal_rate; 742 + else 743 + refin_div = div64_u64(xtal_rate, vc7->clk_apll.xo_ib_h_div); 744 + 745 + if (vc7->clk_apll.en_doubler) 746 + refin_div *= 2; 747 + 748 + /* divider = int + (frac / 2^27) */ 749 + apll_rate = (refin_div * vc7->clk_apll.apll_fb_div_int) + 750 + ((refin_div * vc7->clk_apll.apll_fb_div_frac) >> VC7_APLL_DENOMINATOR_BITS); 751 + 752 + pr_debug("%s - xo_ib_h_div: %u, apll_fb_div_int: %u, apll_fb_div_frac: %u\n", 753 + __func__, vc7->clk_apll.xo_ib_h_div, vc7->clk_apll.apll_fb_div_int, 754 + vc7->clk_apll.apll_fb_div_frac); 755 + pr_debug("%s - refin_div: %llu, apll rate: %llu\n", 756 + __func__, refin_div, apll_rate); 757 + 758 + return apll_rate; 759 + } 760 + 761 + static void vc7_calc_iod_divider(unsigned long rate, unsigned long parent_rate, 762 + u32 *divider) 763 + { 764 + *divider = DIV_ROUND_UP(parent_rate, rate); 765 + if (*divider < VC7_IOD_MIN_DIVISOR) 766 + *divider = VC7_IOD_MIN_DIVISOR; 767 + if (*divider > VC7_IOD_MAX_DIVISOR) 768 + *divider = VC7_IOD_MAX_DIVISOR; 769 + } 770 + 771 + static void vc7_calc_fod_1st_stage(unsigned long rate, unsigned long parent_rate, 772 + u32 *div_int, u64 *div_frac) 773 + { 774 + u64 rem; 775 + 776 + *div_int = (u32)div64_u64_rem(parent_rate, rate, &rem); 777 + *div_frac = div64_u64(rem << VC7_FOD_DENOMINATOR_BITS, rate); 778 + } 779 + 780 + static unsigned long vc7_calc_fod_1st_stage_rate(unsigned long parent_rate, 781 + u32 fod_1st_int, u64 fod_frac) 782 + { 783 + u64 numer, denom, hi, lo, divisor; 784 + 785 + numer = fod_frac; 786 + denom = BIT_ULL(VC7_FOD_DENOMINATOR_BITS); 787 + 788 + if (fod_frac) { 789 + vc7_64_mul_64_to_128(parent_rate, denom, &hi, &lo); 790 + divisor = ((u64)fod_1st_int * denom) + numer; 791 + return vc7_128_div_64_to_64(hi, lo, divisor, NULL); 792 + } 793 + 794 + return div64_u64(parent_rate, fod_1st_int); 795 + } 796 + 797 + static unsigned long vc7_calc_fod_2nd_stage_rate(unsigned long parent_rate, 798 + u32 fod_1st_int, u32 fod_2nd_int, u64 fod_frac) 799 + { 800 + unsigned long fod_1st_stage_rate; 801 + 802 + fod_1st_stage_rate = vc7_calc_fod_1st_stage_rate(parent_rate, fod_1st_int, fod_frac); 803 + 804 + if (fod_2nd_int < 2) 805 + return fod_1st_stage_rate; 806 + 807 + /* 808 + * There is a div-by-2 preceding the 2nd stage integer divider 809 + * (not shown on block diagram) so the actual 2nd stage integer 810 + * divisor is 2 * N. 811 + */ 812 + return div64_u64(fod_1st_stage_rate >> 1, fod_2nd_int); 813 + } 814 + 815 + static void vc7_calc_fod_divider(unsigned long rate, unsigned long parent_rate, 816 + u32 *fod_1st_int, u32 *fod_2nd_int, u64 *fod_frac) 817 + { 818 + unsigned int allow_frac, i, best_frac_i; 819 + unsigned long first_stage_rate; 820 + 821 + vc7_calc_fod_1st_stage(rate, parent_rate, fod_1st_int, fod_frac); 822 + first_stage_rate = vc7_calc_fod_1st_stage_rate(parent_rate, *fod_1st_int, *fod_frac); 823 + 824 + *fod_2nd_int = 0; 825 + 826 + /* Do we need the second stage integer divider? */ 827 + if (first_stage_rate < VC7_FOD_1ST_STAGE_RATE_MIN) { 828 + allow_frac = 0; 829 + best_frac_i = VC7_FOD_2ND_INT_MIN; 830 + 831 + for (i = VC7_FOD_2ND_INT_MIN; i <= VC7_FOD_2ND_INT_MAX; i++) { 832 + /* 833 + * 1) There is a div-by-2 preceding the 2nd stage integer divider 834 + * (not shown on block diagram) so the actual 2nd stage integer 835 + * divisor is 2 * N. 836 + * 2) Attempt to find an integer solution first. This means stepping 837 + * through each 2nd stage integer and recalculating the 1st stage 838 + * until the 1st stage frequency is out of bounds. If no integer 839 + * solution is found, use the best fractional solution. 840 + */ 841 + vc7_calc_fod_1st_stage(parent_rate, rate * 2 * i, fod_1st_int, fod_frac); 842 + first_stage_rate = vc7_calc_fod_1st_stage_rate(parent_rate, 843 + *fod_1st_int, 844 + *fod_frac); 845 + 846 + /* Remember the first viable fractional solution */ 847 + if (best_frac_i == VC7_FOD_2ND_INT_MIN && 848 + first_stage_rate > VC7_FOD_1ST_STAGE_RATE_MIN) { 849 + best_frac_i = i; 850 + } 851 + 852 + /* Is the divider viable? Prefer integer solutions over fractional. */ 853 + if (*fod_1st_int < VC7_FOD_1ST_INT_MAX && 854 + first_stage_rate >= VC7_FOD_1ST_STAGE_RATE_MIN && 855 + (allow_frac || *fod_frac == 0)) { 856 + *fod_2nd_int = i; 857 + break; 858 + } 859 + 860 + /* Ran out of divisors or the 1st stage frequency is out of range */ 861 + if (i >= VC7_FOD_2ND_INT_MAX || 862 + first_stage_rate > VC7_FOD_1ST_STAGE_RATE_MAX) { 863 + allow_frac = 1; 864 + i = best_frac_i; 865 + 866 + /* Restore the best frac and rerun the loop for the last time */ 867 + if (best_frac_i != VC7_FOD_2ND_INT_MIN) 868 + i--; 869 + 870 + continue; 871 + } 872 + } 873 + } 874 + } 875 + 876 + static unsigned long vc7_fod_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 877 + { 878 + struct vc7_fod_data *fod = container_of(hw, struct vc7_fod_data, hw); 879 + struct vc7_driver_data *vc7 = fod->vc7; 880 + int err; 881 + unsigned long fod_rate; 882 + 883 + err = vc7_read_fod(vc7, fod->num); 884 + if (err) { 885 + dev_err(&vc7->client->dev, "error reading registers for %s\n", 886 + clk_hw_get_name(hw)); 887 + return err; 888 + } 889 + 890 + pr_debug("%s - %s: parent_rate: %lu\n", __func__, clk_hw_get_name(hw), parent_rate); 891 + 892 + fod_rate = vc7_calc_fod_2nd_stage_rate(parent_rate, fod->fod_1st_int, 893 + fod->fod_2nd_int, fod->fod_frac); 894 + 895 + pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n", 896 + __func__, clk_hw_get_name(hw), 897 + fod->fod_1st_int, fod->fod_2nd_int, fod->fod_frac); 898 + pr_debug("%s - %s rate: %lu\n", __func__, clk_hw_get_name(hw), fod_rate); 899 + 900 + return fod_rate; 901 + } 902 + 903 + static long vc7_fod_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) 904 + { 905 + struct vc7_fod_data *fod = container_of(hw, struct vc7_fod_data, hw); 906 + unsigned long fod_rate; 907 + 908 + pr_debug("%s - %s: requested rate: %lu, parent_rate: %lu\n", 909 + __func__, clk_hw_get_name(hw), rate, *parent_rate); 910 + 911 + vc7_calc_fod_divider(rate, *parent_rate, 912 + &fod->fod_1st_int, &fod->fod_2nd_int, &fod->fod_frac); 913 + fod_rate = vc7_calc_fod_2nd_stage_rate(*parent_rate, fod->fod_1st_int, 914 + fod->fod_2nd_int, fod->fod_frac); 915 + 916 + pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n", 917 + __func__, clk_hw_get_name(hw), 918 + fod->fod_1st_int, fod->fod_2nd_int, fod->fod_frac); 919 + pr_debug("%s - %s rate: %lu\n", __func__, clk_hw_get_name(hw), fod_rate); 920 + 921 + return fod_rate; 922 + } 923 + 924 + static int vc7_fod_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) 925 + { 926 + struct vc7_fod_data *fod = container_of(hw, struct vc7_fod_data, hw); 927 + struct vc7_driver_data *vc7 = fod->vc7; 928 + unsigned long fod_rate; 929 + 930 + pr_debug("%s - %s: rate: %lu, parent_rate: %lu\n", 931 + __func__, clk_hw_get_name(hw), rate, parent_rate); 932 + 933 + if (rate < VC7_FOD_RATE_MIN || rate > VC7_FOD_RATE_MAX) { 934 + dev_err(&vc7->client->dev, 935 + "requested frequency %lu Hz for %s is out of range\n", 936 + rate, clk_hw_get_name(hw)); 937 + return -EINVAL; 938 + } 939 + 940 + vc7_write_fod(vc7, fod->num); 941 + 942 + fod_rate = vc7_calc_fod_2nd_stage_rate(parent_rate, fod->fod_1st_int, 943 + fod->fod_2nd_int, fod->fod_frac); 944 + 945 + pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n", 946 + __func__, clk_hw_get_name(hw), 947 + fod->fod_1st_int, fod->fod_2nd_int, fod->fod_frac); 948 + pr_debug("%s - %s rate: %lu\n", __func__, clk_hw_get_name(hw), fod_rate); 949 + 950 + return 0; 951 + } 952 + 953 + static const struct clk_ops vc7_fod_ops = { 954 + .recalc_rate = vc7_fod_recalc_rate, 955 + .round_rate = vc7_fod_round_rate, 956 + .set_rate = vc7_fod_set_rate, 957 + }; 958 + 959 + static unsigned long vc7_iod_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) 960 + { 961 + struct vc7_iod_data *iod = container_of(hw, struct vc7_iod_data, hw); 962 + struct vc7_driver_data *vc7 = iod->vc7; 963 + int err; 964 + unsigned long iod_rate; 965 + 966 + err = vc7_read_iod(vc7, iod->num); 967 + if (err) { 968 + dev_err(&vc7->client->dev, "error reading registers for %s\n", 969 + clk_hw_get_name(hw)); 970 + return err; 971 + } 972 + 973 + iod_rate = div64_u64(parent_rate, iod->iod_int); 974 + 975 + pr_debug("%s - %s: iod_int: %u\n", __func__, clk_hw_get_name(hw), iod->iod_int); 976 + pr_debug("%s - %s rate: %lu\n", __func__, clk_hw_get_name(hw), iod_rate); 977 + 978 + return iod_rate; 979 + } 980 + 981 + static long vc7_iod_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) 982 + { 983 + struct vc7_iod_data *iod = container_of(hw, struct vc7_iod_data, hw); 984 + unsigned long iod_rate; 985 + 986 + pr_debug("%s - %s: requested rate: %lu, parent_rate: %lu\n", 987 + __func__, clk_hw_get_name(hw), rate, *parent_rate); 988 + 989 + vc7_calc_iod_divider(rate, *parent_rate, &iod->iod_int); 990 + iod_rate = div64_u64(*parent_rate, iod->iod_int); 991 + 992 + pr_debug("%s - %s: iod_int: %u\n", __func__, clk_hw_get_name(hw), iod->iod_int); 993 + pr_debug("%s - %s rate: %ld\n", __func__, clk_hw_get_name(hw), iod_rate); 994 + 995 + return iod_rate; 996 + } 997 + 998 + static int vc7_iod_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) 999 + { 1000 + struct vc7_iod_data *iod = container_of(hw, struct vc7_iod_data, hw); 1001 + struct vc7_driver_data *vc7 = iod->vc7; 1002 + unsigned long iod_rate; 1003 + 1004 + pr_debug("%s - %s: rate: %lu, parent_rate: %lu\n", 1005 + __func__, clk_hw_get_name(hw), rate, parent_rate); 1006 + 1007 + if (rate < VC7_IOD_RATE_MIN || rate > VC7_IOD_RATE_MAX) { 1008 + dev_err(&vc7->client->dev, 1009 + "requested frequency %lu Hz for %s is out of range\n", 1010 + rate, clk_hw_get_name(hw)); 1011 + return -EINVAL; 1012 + } 1013 + 1014 + vc7_write_iod(vc7, iod->num); 1015 + 1016 + iod_rate = div64_u64(parent_rate, iod->iod_int); 1017 + 1018 + pr_debug("%s - %s: iod_int: %u\n", __func__, clk_hw_get_name(hw), iod->iod_int); 1019 + pr_debug("%s - %s rate: %ld\n", __func__, clk_hw_get_name(hw), iod_rate); 1020 + 1021 + return 0; 1022 + } 1023 + 1024 + static const struct clk_ops vc7_iod_ops = { 1025 + .recalc_rate = vc7_iod_recalc_rate, 1026 + .round_rate = vc7_iod_round_rate, 1027 + .set_rate = vc7_iod_set_rate, 1028 + }; 1029 + 1030 + static int vc7_clk_out_prepare(struct clk_hw *hw) 1031 + { 1032 + struct vc7_out_data *out = container_of(hw, struct vc7_out_data, hw); 1033 + struct vc7_driver_data *vc7 = out->vc7; 1034 + int err; 1035 + 1036 + out->out_dis = 0; 1037 + 1038 + err = vc7_write_output(vc7, out->num); 1039 + if (err) { 1040 + dev_err(&vc7->client->dev, "error writing registers for %s\n", 1041 + clk_hw_get_name(hw)); 1042 + return err; 1043 + } 1044 + 1045 + pr_debug("%s - %s: clk prepared\n", __func__, clk_hw_get_name(hw)); 1046 + 1047 + return 0; 1048 + } 1049 + 1050 + static void vc7_clk_out_unprepare(struct clk_hw *hw) 1051 + { 1052 + struct vc7_out_data *out = container_of(hw, struct vc7_out_data, hw); 1053 + struct vc7_driver_data *vc7 = out->vc7; 1054 + int err; 1055 + 1056 + out->out_dis = 1; 1057 + 1058 + err = vc7_write_output(vc7, out->num); 1059 + if (err) { 1060 + dev_err(&vc7->client->dev, "error writing registers for %s\n", 1061 + clk_hw_get_name(hw)); 1062 + return; 1063 + } 1064 + 1065 + pr_debug("%s - %s: clk unprepared\n", __func__, clk_hw_get_name(hw)); 1066 + } 1067 + 1068 + static int vc7_clk_out_is_enabled(struct clk_hw *hw) 1069 + { 1070 + struct vc7_out_data *out = container_of(hw, struct vc7_out_data, hw); 1071 + struct vc7_driver_data *vc7 = out->vc7; 1072 + int err, is_enabled; 1073 + 1074 + err = vc7_read_output(vc7, out->num); 1075 + if (err) { 1076 + dev_err(&vc7->client->dev, "error reading registers for %s\n", 1077 + clk_hw_get_name(hw)); 1078 + return err; 1079 + } 1080 + 1081 + is_enabled = !out->out_dis; 1082 + 1083 + pr_debug("%s - %s: is_enabled=%d\n", __func__, clk_hw_get_name(hw), is_enabled); 1084 + 1085 + return is_enabled; 1086 + } 1087 + 1088 + static const struct clk_ops vc7_clk_out_ops = { 1089 + .prepare = vc7_clk_out_prepare, 1090 + .unprepare = vc7_clk_out_unprepare, 1091 + .is_enabled = vc7_clk_out_is_enabled, 1092 + }; 1093 + 1094 + static int vc7_probe(struct i2c_client *client) 1095 + { 1096 + struct vc7_driver_data *vc7; 1097 + struct clk_init_data clk_init; 1098 + struct vc7_bank_src_map bank_src_map; 1099 + const char *node_name, *apll_name; 1100 + const char *parent_names[1]; 1101 + unsigned int i, val, bank_idx, out_num; 1102 + unsigned long apll_rate; 1103 + int ret; 1104 + 1105 + vc7 = devm_kzalloc(&client->dev, sizeof(*vc7), GFP_KERNEL); 1106 + if (!vc7) 1107 + return -ENOMEM; 1108 + 1109 + i2c_set_clientdata(client, vc7); 1110 + vc7->client = client; 1111 + vc7->chip_info = of_device_get_match_data(&client->dev); 1112 + 1113 + vc7->pin_xin = devm_clk_get(&client->dev, "xin"); 1114 + if (PTR_ERR(vc7->pin_xin) == -EPROBE_DEFER) { 1115 + return dev_err_probe(&client->dev, -EPROBE_DEFER, 1116 + "xin not specified\n"); 1117 + } 1118 + 1119 + vc7->regmap = devm_regmap_init_i2c(client, &vc7_regmap_config); 1120 + if (IS_ERR(vc7->regmap)) { 1121 + return dev_err_probe(&client->dev, PTR_ERR(vc7->regmap), 1122 + "failed to allocate register map\n"); 1123 + } 1124 + 1125 + if (of_property_read_string(client->dev.of_node, "clock-output-names", 1126 + &node_name)) 1127 + node_name = client->dev.of_node->name; 1128 + 1129 + /* Register APLL */ 1130 + apll_rate = vc7_get_apll_rate(vc7); 1131 + apll_name = kasprintf(GFP_KERNEL, "%s_apll", node_name); 1132 + vc7->clk_apll.clk = clk_register_fixed_rate(&client->dev, apll_name, 1133 + __clk_get_name(vc7->pin_xin), 1134 + 0, apll_rate); 1135 + kfree(apll_name); /* ccf made a copy of the name */ 1136 + if (IS_ERR(vc7->clk_apll.clk)) { 1137 + return dev_err_probe(&client->dev, PTR_ERR(vc7->clk_apll.clk), 1138 + "failed to register apll\n"); 1139 + } 1140 + 1141 + /* Register FODs */ 1142 + for (i = 0; i < VC7_NUM_FOD; i++) { 1143 + memset(&clk_init, 0, sizeof(clk_init)); 1144 + clk_init.name = kasprintf(GFP_KERNEL, "%s_fod%d", node_name, i); 1145 + clk_init.ops = &vc7_fod_ops; 1146 + clk_init.parent_names = parent_names; 1147 + parent_names[0] = __clk_get_name(vc7->clk_apll.clk); 1148 + clk_init.num_parents = 1; 1149 + vc7->clk_fod[i].num = i; 1150 + vc7->clk_fod[i].vc7 = vc7; 1151 + vc7->clk_fod[i].hw.init = &clk_init; 1152 + ret = devm_clk_hw_register(&client->dev, &vc7->clk_fod[i].hw); 1153 + if (ret) 1154 + goto err_clk_register; 1155 + kfree(clk_init.name); /* ccf made a copy of the name */ 1156 + } 1157 + 1158 + /* Register IODs */ 1159 + for (i = 0; i < VC7_NUM_IOD; i++) { 1160 + memset(&clk_init, 0, sizeof(clk_init)); 1161 + clk_init.name = kasprintf(GFP_KERNEL, "%s_iod%d", node_name, i); 1162 + clk_init.ops = &vc7_iod_ops; 1163 + clk_init.parent_names = parent_names; 1164 + parent_names[0] = __clk_get_name(vc7->clk_apll.clk); 1165 + clk_init.num_parents = 1; 1166 + vc7->clk_iod[i].num = i; 1167 + vc7->clk_iod[i].vc7 = vc7; 1168 + vc7->clk_iod[i].hw.init = &clk_init; 1169 + ret = devm_clk_hw_register(&client->dev, &vc7->clk_iod[i].hw); 1170 + if (ret) 1171 + goto err_clk_register; 1172 + kfree(clk_init.name); /* ccf made a copy of the name */ 1173 + } 1174 + 1175 + /* Register outputs */ 1176 + for (i = 0; i < vc7->chip_info->num_outputs; i++) { 1177 + out_num = vc7_map_index_to_output(vc7->chip_info->model, i); 1178 + 1179 + /* 1180 + * This driver does not support remapping FOD/IOD to banks. 1181 + * The device state is read and the driver is setup to match 1182 + * the device's existing mapping. 1183 + */ 1184 + bank_idx = output_bank_mapping[out_num]; 1185 + 1186 + regmap_read(vc7->regmap, VC7_REG_OUT_BANK_CNFG(bank_idx), &val); 1187 + val &= VC7_REG_OUTPUT_BANK_SRC_MASK; 1188 + 1189 + memset(&bank_src_map, 0, sizeof(bank_src_map)); 1190 + ret = vc7_get_bank_clk(vc7, bank_idx, val, &bank_src_map); 1191 + if (ret) { 1192 + dev_err_probe(&client->dev, ret, 1193 + "unable to register output %d\n", i); 1194 + return ret; 1195 + } 1196 + 1197 + switch (bank_src_map.type) { 1198 + case VC7_FOD: 1199 + parent_names[0] = clk_hw_get_name(&bank_src_map.src.fod->hw); 1200 + break; 1201 + case VC7_IOD: 1202 + parent_names[0] = clk_hw_get_name(&bank_src_map.src.iod->hw); 1203 + break; 1204 + } 1205 + 1206 + memset(&clk_init, 0, sizeof(clk_init)); 1207 + clk_init.name = kasprintf(GFP_KERNEL, "%s_out%d", node_name, i); 1208 + clk_init.ops = &vc7_clk_out_ops; 1209 + clk_init.flags = CLK_SET_RATE_PARENT; 1210 + clk_init.parent_names = parent_names; 1211 + clk_init.num_parents = 1; 1212 + vc7->clk_out[i].num = i; 1213 + vc7->clk_out[i].vc7 = vc7; 1214 + vc7->clk_out[i].hw.init = &clk_init; 1215 + ret = devm_clk_hw_register(&client->dev, &vc7->clk_out[i].hw); 1216 + if (ret) 1217 + goto err_clk_register; 1218 + kfree(clk_init.name); /* ccf made a copy of the name */ 1219 + } 1220 + 1221 + ret = of_clk_add_hw_provider(client->dev.of_node, vc7_of_clk_get, vc7); 1222 + if (ret) { 1223 + dev_err_probe(&client->dev, ret, "unable to add clk provider\n"); 1224 + goto err_clk; 1225 + } 1226 + 1227 + return ret; 1228 + 1229 + err_clk_register: 1230 + dev_err_probe(&client->dev, ret, 1231 + "unable to register %s\n", clk_init.name); 1232 + kfree(clk_init.name); /* ccf made a copy of the name */ 1233 + err_clk: 1234 + clk_unregister_fixed_rate(vc7->clk_apll.clk); 1235 + return ret; 1236 + } 1237 + 1238 + static int vc7_remove(struct i2c_client *client) 1239 + { 1240 + struct vc7_driver_data *vc7 = i2c_get_clientdata(client); 1241 + 1242 + of_clk_del_provider(client->dev.of_node); 1243 + clk_unregister_fixed_rate(vc7->clk_apll.clk); 1244 + 1245 + return 0; 1246 + } 1247 + 1248 + static bool vc7_volatile_reg(struct device *dev, unsigned int reg) 1249 + { 1250 + if (reg == VC7_PAGE_ADDR) 1251 + return false; 1252 + 1253 + return true; 1254 + } 1255 + 1256 + static const struct vc7_chip_info vc7_rc21008a_info = { 1257 + .model = VC7_RC21008A, 1258 + .num_banks = 6, 1259 + .num_outputs = 8, 1260 + }; 1261 + 1262 + static struct regmap_range_cfg vc7_range_cfg[] = { 1263 + { 1264 + .range_min = 0, 1265 + .range_max = VC7_MAX_REG, 1266 + .selector_reg = VC7_PAGE_ADDR, 1267 + .selector_mask = 0xFF, 1268 + .selector_shift = 0, 1269 + .window_start = 0, 1270 + .window_len = VC7_PAGE_WINDOW, 1271 + }}; 1272 + 1273 + static const struct regmap_config vc7_regmap_config = { 1274 + .reg_bits = 8, 1275 + .val_bits = 8, 1276 + .max_register = VC7_MAX_REG, 1277 + .ranges = vc7_range_cfg, 1278 + .num_ranges = ARRAY_SIZE(vc7_range_cfg), 1279 + .volatile_reg = vc7_volatile_reg, 1280 + .cache_type = REGCACHE_RBTREE, 1281 + .can_multi_write = true, 1282 + .reg_format_endian = REGMAP_ENDIAN_LITTLE, 1283 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 1284 + }; 1285 + 1286 + static const struct i2c_device_id vc7_i2c_id[] = { 1287 + { "rc21008a", VC7_RC21008A }, 1288 + {} 1289 + }; 1290 + MODULE_DEVICE_TABLE(i2c, vc7_i2c_id); 1291 + 1292 + static const struct of_device_id vc7_of_match[] = { 1293 + { .compatible = "renesas,rc21008a", .data = &vc7_rc21008a_info }, 1294 + {} 1295 + }; 1296 + MODULE_DEVICE_TABLE(of, vc7_of_match); 1297 + 1298 + static struct i2c_driver vc7_i2c_driver = { 1299 + .driver = { 1300 + .name = "vc7", 1301 + .of_match_table = vc7_of_match, 1302 + }, 1303 + .probe_new = vc7_probe, 1304 + .remove = vc7_remove, 1305 + .id_table = vc7_i2c_id, 1306 + }; 1307 + module_i2c_driver(vc7_i2c_driver); 1308 + 1309 + MODULE_LICENSE("GPL"); 1310 + MODULE_AUTHOR("Alex Helms <alexander.helms.jy@renesas.com"); 1311 + MODULE_DESCRIPTION("Renesas Versaclock7 common clock framework driver");