1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Xilinx VCU Init 4 * 5 * Copyright (C) 2016 - 2017 Xilinx, Inc. 6 * 7 * Contacts Dhaval Shah <dshah@xilinx.com> 8 */ 9 #include <linux/bitfield.h> 10 #include <linux/clk.h> 11 #include <linux/clk-provider.h> 12 #include <linux/device.h> 13 #include <linux/errno.h> 14 #include <linux/gpio/consumer.h> 15 #include <linux/io.h> 16 #include <linux/mfd/syscon.h> 17 #include <linux/mfd/syscon/xlnx-vcu.h> 18 #include <linux/module.h> 19 #include <linux/mod_devicetable.h> 20 #include <linux/platform_device.h> 21 #include <linux/regmap.h> 22 23 #include <dt-bindings/clock/xlnx-vcu.h> 24 25 #define VCU_PLL_CTRL 0x24 26 #define VCU_PLL_CTRL_RESET BIT(0) 27 #define VCU_PLL_CTRL_POR_IN BIT(1) 28 #define VCU_PLL_CTRL_PWR_POR BIT(2) 29 #define VCU_PLL_CTRL_BYPASS BIT(3) 30 #define VCU_PLL_CTRL_FBDIV GENMASK(14, 8) 31 #define VCU_PLL_CTRL_CLKOUTDIV GENMASK(18, 16) 32 33 #define VCU_PLL_CFG 0x28 34 #define VCU_PLL_CFG_RES GENMASK(3, 0) 35 #define VCU_PLL_CFG_CP GENMASK(8, 5) 36 #define VCU_PLL_CFG_LFHF GENMASK(12, 10) 37 #define VCU_PLL_CFG_LOCK_CNT GENMASK(22, 13) 38 #define VCU_PLL_CFG_LOCK_DLY GENMASK(31, 25) 39 #define VCU_ENC_CORE_CTRL 0x30 40 #define VCU_ENC_MCU_CTRL 0x34 41 #define VCU_DEC_CORE_CTRL 0x38 42 #define VCU_DEC_MCU_CTRL 0x3c 43 #define VCU_PLL_STATUS 0x60 44 #define VCU_PLL_STATUS_LOCK_STATUS BIT(0) 45 46 #define MHZ 1000000 47 #define FVCO_MIN (1500U * MHZ) 48 #define FVCO_MAX (3000U * MHZ) 49 50 /** 51 * struct xvcu_device - Xilinx VCU init device structure 52 * @dev: Platform device 53 * @pll_ref: pll ref clock source 54 * @aclk: axi clock source 55 * @reset_gpio: vcu reset gpio 56 * @logicore_reg_ba: logicore reg base address 57 * @vcu_slcr_ba: vcu_slcr Register base address 58 * @pll: handle for the VCU PLL 59 * @pll_post: handle for the VCU PLL post divider 60 * @clk_data: clocks provided by the vcu clock provider 61 */ 62 struct xvcu_device { 63 struct device *dev; 64 struct clk *pll_ref; 65 struct clk *aclk; 66 struct gpio_desc *reset_gpio; 67 struct regmap *logicore_reg_ba; 68 void __iomem *vcu_slcr_ba; 69 struct clk_hw *pll; 70 struct clk_hw *pll_post; 71 struct clk_hw_onecell_data *clk_data; 72 }; 73 74 static const struct regmap_config vcu_settings_regmap_config = { 75 .name = "regmap", 76 .reg_bits = 32, 77 .val_bits = 32, 78 .reg_stride = 4, 79 .max_register = 0xfff, 80 .cache_type = REGCACHE_NONE, 81 }; 82 83 /** 84 * struct xvcu_pll_cfg - Helper data 85 * @fbdiv: The integer portion of the feedback divider to the PLL 86 * @cp: PLL charge pump control 87 * @res: PLL loop filter resistor control 88 * @lfhf: PLL loop filter high frequency capacitor control 89 * @lock_dly: Lock circuit configuration settings for lock windowsize 90 * @lock_cnt: Lock circuit counter setting 91 */ 92 struct xvcu_pll_cfg { 93 u32 fbdiv; 94 u32 cp; 95 u32 res; 96 u32 lfhf; 97 u32 lock_dly; 98 u32 lock_cnt; 99 }; 100 101 static const struct xvcu_pll_cfg xvcu_pll_cfg[] = { 102 { 25, 3, 10, 3, 63, 1000 }, 103 { 26, 3, 10, 3, 63, 1000 }, 104 { 27, 4, 6, 3, 63, 1000 }, 105 { 28, 4, 6, 3, 63, 1000 }, 106 { 29, 4, 6, 3, 63, 1000 }, 107 { 30, 4, 6, 3, 63, 1000 }, 108 { 31, 6, 1, 3, 63, 1000 }, 109 { 32, 6, 1, 3, 63, 1000 }, 110 { 33, 4, 10, 3, 63, 1000 }, 111 { 34, 5, 6, 3, 63, 1000 }, 112 { 35, 5, 6, 3, 63, 1000 }, 113 { 36, 5, 6, 3, 63, 1000 }, 114 { 37, 5, 6, 3, 63, 1000 }, 115 { 38, 5, 6, 3, 63, 975 }, 116 { 39, 3, 12, 3, 63, 950 }, 117 { 40, 3, 12, 3, 63, 925 }, 118 { 41, 3, 12, 3, 63, 900 }, 119 { 42, 3, 12, 3, 63, 875 }, 120 { 43, 3, 12, 3, 63, 850 }, 121 { 44, 3, 12, 3, 63, 850 }, 122 { 45, 3, 12, 3, 63, 825 }, 123 { 46, 3, 12, 3, 63, 800 }, 124 { 47, 3, 12, 3, 63, 775 }, 125 { 48, 3, 12, 3, 63, 775 }, 126 { 49, 3, 12, 3, 63, 750 }, 127 { 50, 3, 12, 3, 63, 750 }, 128 { 51, 3, 2, 3, 63, 725 }, 129 { 52, 3, 2, 3, 63, 700 }, 130 { 53, 3, 2, 3, 63, 700 }, 131 { 54, 3, 2, 3, 63, 675 }, 132 { 55, 3, 2, 3, 63, 675 }, 133 { 56, 3, 2, 3, 63, 650 }, 134 { 57, 3, 2, 3, 63, 650 }, 135 { 58, 3, 2, 3, 63, 625 }, 136 { 59, 3, 2, 3, 63, 625 }, 137 { 60, 3, 2, 3, 63, 625 }, 138 { 61, 3, 2, 3, 63, 600 }, 139 { 62, 3, 2, 3, 63, 600 }, 140 { 63, 3, 2, 3, 63, 600 }, 141 { 64, 3, 2, 3, 63, 600 }, 142 { 65, 3, 2, 3, 63, 600 }, 143 { 66, 3, 2, 3, 63, 600 }, 144 { 67, 3, 2, 3, 63, 600 }, 145 { 68, 3, 2, 3, 63, 600 }, 146 { 69, 3, 2, 3, 63, 600 }, 147 { 70, 3, 2, 3, 63, 600 }, 148 { 71, 3, 2, 3, 63, 600 }, 149 { 72, 3, 2, 3, 63, 600 }, 150 { 73, 3, 2, 3, 63, 600 }, 151 { 74, 3, 2, 3, 63, 600 }, 152 { 75, 3, 2, 3, 63, 600 }, 153 { 76, 3, 2, 3, 63, 600 }, 154 { 77, 3, 2, 3, 63, 600 }, 155 { 78, 3, 2, 3, 63, 600 }, 156 { 79, 3, 2, 3, 63, 600 }, 157 { 80, 3, 2, 3, 63, 600 }, 158 { 81, 3, 2, 3, 63, 600 }, 159 { 82, 3, 2, 3, 63, 600 }, 160 { 83, 4, 2, 3, 63, 600 }, 161 { 84, 4, 2, 3, 63, 600 }, 162 { 85, 4, 2, 3, 63, 600 }, 163 { 86, 4, 2, 3, 63, 600 }, 164 { 87, 4, 2, 3, 63, 600 }, 165 { 88, 4, 2, 3, 63, 600 }, 166 { 89, 4, 2, 3, 63, 600 }, 167 { 90, 4, 2, 3, 63, 600 }, 168 { 91, 4, 2, 3, 63, 600 }, 169 { 92, 4, 2, 3, 63, 600 }, 170 { 93, 4, 2, 3, 63, 600 }, 171 { 94, 4, 2, 3, 63, 600 }, 172 { 95, 4, 2, 3, 63, 600 }, 173 { 96, 4, 2, 3, 63, 600 }, 174 { 97, 4, 2, 3, 63, 600 }, 175 { 98, 4, 2, 3, 63, 600 }, 176 { 99, 4, 2, 3, 63, 600 }, 177 { 100, 4, 2, 3, 63, 600 }, 178 { 101, 4, 2, 3, 63, 600 }, 179 { 102, 4, 2, 3, 63, 600 }, 180 { 103, 5, 2, 3, 63, 600 }, 181 { 104, 5, 2, 3, 63, 600 }, 182 { 105, 5, 2, 3, 63, 600 }, 183 { 106, 5, 2, 3, 63, 600 }, 184 { 107, 3, 4, 3, 63, 600 }, 185 { 108, 3, 4, 3, 63, 600 }, 186 { 109, 3, 4, 3, 63, 600 }, 187 { 110, 3, 4, 3, 63, 600 }, 188 { 111, 3, 4, 3, 63, 600 }, 189 { 112, 3, 4, 3, 63, 600 }, 190 { 113, 3, 4, 3, 63, 600 }, 191 { 114, 3, 4, 3, 63, 600 }, 192 { 115, 3, 4, 3, 63, 600 }, 193 { 116, 3, 4, 3, 63, 600 }, 194 { 117, 3, 4, 3, 63, 600 }, 195 { 118, 3, 4, 3, 63, 600 }, 196 { 119, 3, 4, 3, 63, 600 }, 197 { 120, 3, 4, 3, 63, 600 }, 198 { 121, 3, 4, 3, 63, 600 }, 199 { 122, 3, 4, 3, 63, 600 }, 200 { 123, 3, 4, 3, 63, 600 }, 201 { 124, 3, 4, 3, 63, 600 }, 202 { 125, 3, 4, 3, 63, 600 }, 203 }; 204 205 /** 206 * xvcu_read - Read from the VCU register space 207 * @iomem: vcu reg space base address 208 * @offset: vcu reg offset from base 209 * 210 * Return: Returns 32bit value from VCU register specified 211 * 212 */ 213 static inline u32 xvcu_read(void __iomem *iomem, u32 offset) 214 { 215 return ioread32(iomem + offset); 216 } 217 218 /** 219 * xvcu_write - Write to the VCU register space 220 * @iomem: vcu reg space base address 221 * @offset: vcu reg offset from base 222 * @value: Value to write 223 */ 224 static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value) 225 { 226 iowrite32(value, iomem + offset); 227 } 228 229 #define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw) 230 231 struct vcu_pll { 232 struct clk_hw hw; 233 void __iomem *reg_base; 234 unsigned long fvco_min; 235 unsigned long fvco_max; 236 }; 237 238 static int xvcu_pll_wait_for_lock(struct vcu_pll *pll) 239 { 240 void __iomem *base = pll->reg_base; 241 unsigned long timeout; 242 u32 lock_status; 243 244 timeout = jiffies + msecs_to_jiffies(2000); 245 do { 246 lock_status = xvcu_read(base, VCU_PLL_STATUS); 247 if (lock_status & VCU_PLL_STATUS_LOCK_STATUS) 248 return 0; 249 } while (!time_after(jiffies, timeout)); 250 251 return -ETIMEDOUT; 252 } 253 254 static struct clk_hw *xvcu_register_pll_post(struct device *dev, 255 const char *name, 256 const struct clk_hw *parent_hw, 257 void __iomem *reg_base) 258 { 259 u32 div; 260 u32 vcu_pll_ctrl; 261 262 /* 263 * The output divider of the PLL must be set to 1/2 to meet the 264 * timing in the design. 265 */ 266 vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL); 267 div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl); 268 if (div != 1) 269 return ERR_PTR(-EINVAL); 270 271 return clk_hw_register_fixed_factor(dev, "vcu_pll_post", 272 clk_hw_get_name(parent_hw), 273 CLK_SET_RATE_PARENT, 1, 2); 274 } 275 276 static const struct xvcu_pll_cfg *xvcu_find_cfg(int div) 277 { 278 const struct xvcu_pll_cfg *cfg = NULL; 279 unsigned int i; 280 281 for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++) 282 if (xvcu_pll_cfg[i].fbdiv == div) 283 cfg = &xvcu_pll_cfg[i]; 284 285 return cfg; 286 } 287 288 static int xvcu_pll_set_div(struct vcu_pll *pll, int div) 289 { 290 void __iomem *base = pll->reg_base; 291 const struct xvcu_pll_cfg *cfg = NULL; 292 u32 vcu_pll_ctrl; 293 u32 cfg_val; 294 295 cfg = xvcu_find_cfg(div); 296 if (!cfg) 297 return -EINVAL; 298 299 vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); 300 vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV; 301 vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv); 302 xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); 303 304 cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) | 305 FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) | 306 FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) | 307 FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) | 308 FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly); 309 xvcu_write(base, VCU_PLL_CFG, cfg_val); 310 311 return 0; 312 } 313 314 static int xvcu_pll_determine_rate(struct clk_hw *hw, 315 struct clk_rate_request *req) 316 { 317 struct vcu_pll *pll = to_vcu_pll(hw); 318 unsigned int feedback_div; 319 320 req->rate = clamp_t(unsigned long, req->rate, pll->fvco_min, 321 pll->fvco_max); 322 323 feedback_div = DIV_ROUND_CLOSEST_ULL(req->rate, req->best_parent_rate); 324 feedback_div = clamp_t(unsigned int, feedback_div, 25, 125); 325 326 req->rate = req->best_parent_rate * feedback_div; 327 328 return 0; 329 } 330 331 static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw, 332 unsigned long parent_rate) 333 { 334 struct vcu_pll *pll = to_vcu_pll(hw); 335 void __iomem *base = pll->reg_base; 336 unsigned int div; 337 u32 vcu_pll_ctrl; 338 339 vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); 340 div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl); 341 342 return div * parent_rate; 343 } 344 345 static int xvcu_pll_set_rate(struct clk_hw *hw, 346 unsigned long rate, unsigned long parent_rate) 347 { 348 struct vcu_pll *pll = to_vcu_pll(hw); 349 350 return xvcu_pll_set_div(pll, rate / parent_rate); 351 } 352 353 static int xvcu_pll_enable(struct clk_hw *hw) 354 { 355 struct vcu_pll *pll = to_vcu_pll(hw); 356 void __iomem *base = pll->reg_base; 357 u32 vcu_pll_ctrl; 358 int ret; 359 360 vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); 361 vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS; 362 xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); 363 364 vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); 365 vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN; 366 vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR; 367 vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET; 368 xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); 369 370 ret = xvcu_pll_wait_for_lock(pll); 371 if (ret) { 372 pr_err("VCU PLL is not locked\n"); 373 goto err; 374 } 375 376 vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); 377 vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS; 378 xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); 379 380 err: 381 return ret; 382 } 383 384 static void xvcu_pll_disable(struct clk_hw *hw) 385 { 386 struct vcu_pll *pll = to_vcu_pll(hw); 387 void __iomem *base = pll->reg_base; 388 u32 vcu_pll_ctrl; 389 390 vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); 391 vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN; 392 vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR; 393 vcu_pll_ctrl |= VCU_PLL_CTRL_RESET; 394 xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); 395 } 396 397 static const struct clk_ops vcu_pll_ops = { 398 .enable = xvcu_pll_enable, 399 .disable = xvcu_pll_disable, 400 .determine_rate = xvcu_pll_determine_rate, 401 .recalc_rate = xvcu_pll_recalc_rate, 402 .set_rate = xvcu_pll_set_rate, 403 }; 404 405 static struct clk_hw *xvcu_register_pll(struct device *dev, 406 void __iomem *reg_base, 407 const char *name, const char *parent, 408 unsigned long flags) 409 { 410 struct vcu_pll *pll; 411 struct clk_hw *hw; 412 struct clk_init_data init; 413 int ret; 414 415 init.name = name; 416 init.parent_names = &parent; 417 init.ops = &vcu_pll_ops; 418 init.num_parents = 1; 419 init.flags = flags; 420 421 pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL); 422 if (!pll) 423 return ERR_PTR(-ENOMEM); 424 425 pll->hw.init = &init; 426 pll->reg_base = reg_base; 427 pll->fvco_min = FVCO_MIN; 428 pll->fvco_max = FVCO_MAX; 429 430 hw = &pll->hw; 431 ret = devm_clk_hw_register(dev, hw); 432 if (ret) 433 return ERR_PTR(ret); 434 435 clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max); 436 437 return hw; 438 } 439 440 static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev, 441 const char *name, 442 const struct clk_parent_data *parent_data, 443 u8 num_parents, 444 void __iomem *reg) 445 { 446 u8 mux_flags = CLK_MUX_ROUND_CLOSEST; 447 u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO | 448 CLK_DIVIDER_ROUND_CLOSEST; 449 struct clk_hw *mux = NULL; 450 struct clk_hw *divider = NULL; 451 struct clk_hw *gate = NULL; 452 char *name_mux; 453 char *name_div; 454 int err; 455 /* Protect register shared by clocks */ 456 spinlock_t *lock; 457 458 lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL); 459 if (!lock) 460 return ERR_PTR(-ENOMEM); 461 spin_lock_init(lock); 462 463 name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux"); 464 if (!name_mux) 465 return ERR_PTR(-ENOMEM); 466 mux = clk_hw_register_mux_parent_data(dev, name_mux, 467 parent_data, num_parents, 468 CLK_SET_RATE_PARENT, 469 reg, 0, 1, mux_flags, lock); 470 if (IS_ERR(mux)) 471 return mux; 472 473 name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div"); 474 if (!name_div) { 475 err = -ENOMEM; 476 goto unregister_mux; 477 } 478 divider = clk_hw_register_divider_parent_hw(dev, name_div, mux, 479 CLK_SET_RATE_PARENT, 480 reg, 4, 6, divider_flags, 481 lock); 482 if (IS_ERR(divider)) { 483 err = PTR_ERR(divider); 484 goto unregister_mux; 485 } 486 487 gate = clk_hw_register_gate_parent_hw(dev, name, divider, 488 CLK_SET_RATE_PARENT, reg, 12, 0, 489 lock); 490 if (IS_ERR(gate)) { 491 err = PTR_ERR(gate); 492 goto unregister_divider; 493 } 494 495 return gate; 496 497 unregister_divider: 498 clk_hw_unregister_divider(divider); 499 unregister_mux: 500 clk_hw_unregister_mux(mux); 501 502 return ERR_PTR(err); 503 } 504 505 static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw) 506 { 507 struct clk_hw *gate = hw; 508 struct clk_hw *divider; 509 struct clk_hw *mux; 510 511 if (!gate) 512 return; 513 514 divider = clk_hw_get_parent(gate); 515 clk_hw_unregister_gate(gate); 516 if (!divider) 517 return; 518 519 mux = clk_hw_get_parent(divider); 520 clk_hw_unregister_mux(mux); 521 if (!divider) 522 return; 523 524 clk_hw_unregister_divider(divider); 525 } 526 527 static int xvcu_register_clock_provider(struct xvcu_device *xvcu) 528 { 529 struct device *dev = xvcu->dev; 530 struct clk_parent_data parent_data[2] = { 0 }; 531 struct clk_hw_onecell_data *data; 532 struct clk_hw **hws; 533 struct clk_hw *hw; 534 void __iomem *reg_base = xvcu->vcu_slcr_ba; 535 536 data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL); 537 if (!data) 538 return -ENOMEM; 539 data->num = CLK_XVCU_NUM_CLOCKS; 540 hws = data->hws; 541 542 xvcu->clk_data = data; 543 544 hw = xvcu_register_pll(dev, reg_base, 545 "vcu_pll", __clk_get_name(xvcu->pll_ref), 546 CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE); 547 if (IS_ERR(hw)) 548 return PTR_ERR(hw); 549 xvcu->pll = hw; 550 551 hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base); 552 if (IS_ERR(hw)) 553 return PTR_ERR(hw); 554 xvcu->pll_post = hw; 555 556 parent_data[0].fw_name = "pll_ref"; 557 parent_data[1].hw = xvcu->pll_post; 558 559 hws[CLK_XVCU_ENC_CORE] = 560 xvcu_clk_hw_register_leaf(dev, "venc_core_clk", 561 parent_data, 562 ARRAY_SIZE(parent_data), 563 reg_base + VCU_ENC_CORE_CTRL); 564 hws[CLK_XVCU_ENC_MCU] = 565 xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk", 566 parent_data, 567 ARRAY_SIZE(parent_data), 568 reg_base + VCU_ENC_MCU_CTRL); 569 hws[CLK_XVCU_DEC_CORE] = 570 xvcu_clk_hw_register_leaf(dev, "vdec_core_clk", 571 parent_data, 572 ARRAY_SIZE(parent_data), 573 reg_base + VCU_DEC_CORE_CTRL); 574 hws[CLK_XVCU_DEC_MCU] = 575 xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk", 576 parent_data, 577 ARRAY_SIZE(parent_data), 578 reg_base + VCU_DEC_MCU_CTRL); 579 580 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data); 581 } 582 583 static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu) 584 { 585 struct clk_hw_onecell_data *data = xvcu->clk_data; 586 struct clk_hw **hws = data->hws; 587 588 if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU])) 589 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]); 590 if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE])) 591 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]); 592 if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU])) 593 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]); 594 if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE])) 595 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]); 596 if (!IS_ERR_OR_NULL(xvcu->pll_post)) 597 clk_hw_unregister_fixed_factor(xvcu->pll_post); 598 } 599 600 /** 601 * xvcu_probe - Probe existence of the logicoreIP 602 * and initialize PLL 603 * 604 * @pdev: Pointer to the platform_device structure 605 * 606 * Return: Returns 0 on success 607 * Negative error code otherwise 608 */ 609 static int xvcu_probe(struct platform_device *pdev) 610 { 611 struct resource *res; 612 struct xvcu_device *xvcu; 613 void __iomem *regs; 614 int ret; 615 616 xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL); 617 if (!xvcu) 618 return -ENOMEM; 619 620 xvcu->dev = &pdev->dev; 621 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr"); 622 if (!res) { 623 dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n"); 624 return -ENODEV; 625 } 626 627 xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, 628 resource_size(res)); 629 if (!xvcu->vcu_slcr_ba) { 630 dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); 631 return -ENOMEM; 632 } 633 634 xvcu->logicore_reg_ba = 635 syscon_regmap_lookup_by_compatible("xlnx,vcu-settings"); 636 if (IS_ERR(xvcu->logicore_reg_ba)) { 637 dev_info(&pdev->dev, 638 "could not find xlnx,vcu-settings: trying direct register access\n"); 639 640 res = platform_get_resource_byname(pdev, 641 IORESOURCE_MEM, "logicore"); 642 if (!res) { 643 dev_err(&pdev->dev, "get logicore memory resource failed.\n"); 644 return -ENODEV; 645 } 646 647 regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 648 if (!regs) { 649 dev_err(&pdev->dev, "logicore register mapping failed.\n"); 650 return -ENOMEM; 651 } 652 653 xvcu->logicore_reg_ba = 654 devm_regmap_init_mmio(&pdev->dev, regs, 655 &vcu_settings_regmap_config); 656 if (IS_ERR(xvcu->logicore_reg_ba)) { 657 dev_err(&pdev->dev, "failed to init regmap\n"); 658 return PTR_ERR(xvcu->logicore_reg_ba); 659 } 660 } 661 662 xvcu->aclk = devm_clk_get(&pdev->dev, "aclk"); 663 if (IS_ERR(xvcu->aclk)) { 664 dev_err(&pdev->dev, "Could not get aclk clock\n"); 665 return PTR_ERR(xvcu->aclk); 666 } 667 668 xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); 669 if (IS_ERR(xvcu->pll_ref)) { 670 dev_err(&pdev->dev, "Could not get pll_ref clock\n"); 671 return PTR_ERR(xvcu->pll_ref); 672 } 673 674 ret = clk_prepare_enable(xvcu->aclk); 675 if (ret) { 676 dev_err(&pdev->dev, "aclk clock enable failed\n"); 677 return ret; 678 } 679 680 /* 681 * Do the Gasket isolation and put the VCU out of reset 682 * Bit 0 : Gasket isolation 683 * Bit 1 : put VCU out of reset 684 */ 685 xvcu->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", 686 GPIOD_OUT_LOW); 687 if (IS_ERR(xvcu->reset_gpio)) { 688 ret = PTR_ERR(xvcu->reset_gpio); 689 dev_err_probe(&pdev->dev, ret, "failed to get reset gpio for vcu.\n"); 690 goto error_get_gpio; 691 } 692 693 if (xvcu->reset_gpio) { 694 gpiod_set_value(xvcu->reset_gpio, 0); 695 /* min 2 clock cycle of vcu pll_ref, slowest freq is 33.33KHz */ 696 usleep_range(60, 120); 697 gpiod_set_value(xvcu->reset_gpio, 1); 698 usleep_range(60, 120); 699 } else { 700 dev_dbg(&pdev->dev, "No reset gpio info found in dts for VCU. This may result in incorrect functionality if VCU isolation is removed after initialization in designs where the VCU reset is driven by gpio.\n"); 701 } 702 703 regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); 704 705 ret = xvcu_register_clock_provider(xvcu); 706 if (ret) { 707 dev_err(&pdev->dev, "failed to register clock provider\n"); 708 goto error_clk_provider; 709 } 710 711 dev_set_drvdata(&pdev->dev, xvcu); 712 713 return 0; 714 715 error_clk_provider: 716 xvcu_unregister_clock_provider(xvcu); 717 error_get_gpio: 718 clk_disable_unprepare(xvcu->aclk); 719 return ret; 720 } 721 722 /** 723 * xvcu_remove - Insert gasket isolation 724 * and disable the clock 725 * @pdev: Pointer to the platform_device structure 726 * 727 * Return: Returns 0 on success 728 * Negative error code otherwise 729 */ 730 static void xvcu_remove(struct platform_device *pdev) 731 { 732 struct xvcu_device *xvcu; 733 734 xvcu = platform_get_drvdata(pdev); 735 736 xvcu_unregister_clock_provider(xvcu); 737 738 /* Add the Gasket isolation and put the VCU in reset. */ 739 if (xvcu->reset_gpio) { 740 gpiod_set_value(xvcu->reset_gpio, 0); 741 /* min 2 clock cycle of vcu pll_ref, slowest freq is 33.33KHz */ 742 usleep_range(60, 120); 743 gpiod_set_value(xvcu->reset_gpio, 1); 744 usleep_range(60, 120); 745 } 746 regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); 747 748 clk_disable_unprepare(xvcu->aclk); 749 } 750 751 static const struct of_device_id xvcu_of_id_table[] = { 752 { .compatible = "xlnx,vcu" }, 753 { .compatible = "xlnx,vcu-logicoreip-1.0" }, 754 { } 755 }; 756 MODULE_DEVICE_TABLE(of, xvcu_of_id_table); 757 758 static struct platform_driver xvcu_driver = { 759 .driver = { 760 .name = "xilinx-vcu", 761 .of_match_table = xvcu_of_id_table, 762 }, 763 .probe = xvcu_probe, 764 .remove = xvcu_remove, 765 }; 766 767 module_platform_driver(xvcu_driver); 768 769 MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>"); 770 MODULE_DESCRIPTION("Xilinx VCU init Driver"); 771 MODULE_LICENSE("GPL v2"); 772