sifive-prci.c (c816e1ddf2b60b31d121118488c5a854d9a2fad9) | sifive-prci.c (efc91ae43c8d4bbf64e4b9a28113b24a74ffd58d) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2020 SiFive, Inc. 4 * Copyright (C) 2020 Zong Li 5 */ 6 7#include <linux/clkdev.h> 8#include <linux/delay.h> 9#include <linux/io.h> 10#include <linux/of_device.h> 11#include "sifive-prci.h" 12#include "fu540-prci.h" | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2020 SiFive, Inc. 4 * Copyright (C) 2020 Zong Li 5 */ 6 7#include <linux/clkdev.h> 8#include <linux/delay.h> 9#include <linux/io.h> 10#include <linux/of_device.h> 11#include "sifive-prci.h" 12#include "fu540-prci.h" |
13#include "fu740-prci.h" |
|
13 14/* 15 * Private functions 16 */ 17 18/** 19 * __prci_readl() - read from a PRCI register 20 * @pd: PRCI context --- 199 unchanged lines hidden (view full) --- 220 221 v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET); 222 v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK; 223 div = v ? 1 : 2; 224 225 return div_u64(parent_rate, div); 226} 227 | 14 15/* 16 * Private functions 17 */ 18 19/** 20 * __prci_readl() - read from a PRCI register 21 * @pd: PRCI context --- 199 unchanged lines hidden (view full) --- 221 222 v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET); 223 v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK; 224 div = v ? 1 : 2; 225 226 return div_u64(parent_rate, div); 227} 228 |
229/* HFPCLK clock integration */ 230 231unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw, 232 unsigned long parent_rate) 233{ 234 struct __prci_clock *pc = clk_hw_to_prci_clock(hw); 235 struct __prci_data *pd = pc->pd; 236 u32 div = __prci_readl(pd, PRCI_HFPCLKPLLDIV_OFFSET); 237 238 return div_u64(parent_rate, div + 2); 239} 240 |
|
228/* 229 * Core clock mux control 230 */ 231 232/** 233 * sifive_prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK 234 * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg 235 * --- 30 unchanged lines hidden (view full) --- 266 r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); 267 r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK; 268 __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd); 269 270 r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */ 271} 272 273/** | 241/* 242 * Core clock mux control 243 */ 244 245/** 246 * sifive_prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK 247 * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg 248 * --- 30 unchanged lines hidden (view full) --- 279 r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); 280 r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK; 281 __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd); 282 283 r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */ 284} 285 286/** |
287 * sifive_prci_coreclksel_use_final_corepll() - switch the CORECLK mux to output 288 * FINAL_COREPLL 289 * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg 290 * 291 * Switch the CORECLK mux to the final COREPLL output clock; return once 292 * complete. 293 * 294 * Context: Any context. Caller must prevent concurrent changes to the 295 * PRCI_CORECLKSEL_OFFSET register. 296 */ 297void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd) 298{ 299 u32 r; 300 301 r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); 302 r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK; 303 __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd); 304 305 r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */ 306} 307 308/** 309 * sifive_prci_corepllsel_use_dvfscorepll() - switch the COREPLL mux to 310 * output DVFS_COREPLL 311 * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg 312 * 313 * Switch the COREPLL mux to the DVFSCOREPLL output clock; return once complete. 314 * 315 * Context: Any context. Caller must prevent concurrent changes to the 316 * PRCI_COREPLLSEL_OFFSET register. 317 */ 318void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd) 319{ 320 u32 r; 321 322 r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); 323 r |= PRCI_COREPLLSEL_COREPLLSEL_MASK; 324 __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd); 325 326 r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); /* barrier */ 327} 328 329/** 330 * sifive_prci_corepllsel_use_corepll() - switch the COREPLL mux to 331 * output COREPLL 332 * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg 333 * 334 * Switch the COREPLL mux to the COREPLL output clock; return once complete. 335 * 336 * Context: Any context. Caller must prevent concurrent changes to the 337 * PRCI_COREPLLSEL_OFFSET register. 338 */ 339void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd) 340{ 341 u32 r; 342 343 r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); 344 r &= ~PRCI_COREPLLSEL_COREPLLSEL_MASK; 345 __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd); 346 347 r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET); /* barrier */ 348} 349 350/** 351 * sifive_prci_hfpclkpllsel_use_hfclk() - switch the HFPCLKPLL mux to 352 * output HFCLK 353 * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg 354 * 355 * Switch the HFPCLKPLL mux to the HFCLK input source; return once complete. 356 * 357 * Context: Any context. Caller must prevent concurrent changes to the 358 * PRCI_HFPCLKPLLSEL_OFFSET register. 359 */ 360void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd) 361{ 362 u32 r; 363 364 r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); 365 r |= PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK; 366 __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd); 367 368 r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */ 369} 370 371/** 372 * sifive_prci_hfpclkpllsel_use_hfpclkpll() - switch the HFPCLKPLL mux to 373 * output HFPCLKPLL 374 * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg 375 * 376 * Switch the HFPCLKPLL mux to the HFPCLKPLL output clock; return once complete. 377 * 378 * Context: Any context. Caller must prevent concurrent changes to the 379 * PRCI_HFPCLKPLLSEL_OFFSET register. 380 */ 381void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd) 382{ 383 u32 r; 384 385 r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); 386 r &= ~PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK; 387 __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd); 388 389 r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */ 390} 391 392/** |
|
274 * __prci_register_clocks() - register clock controls in the PRCI 275 * @dev: Linux struct device 276 * @pd: The pointer for PRCI per-device instance data 277 * @desc: The pointer for the information of clocks of each SoCs 278 * 279 * Register the list of clock controls described in __prci_init_clocks[] with 280 * the Linux clock framework. 281 * --- 90 unchanged lines hidden (view full) --- 372 373 dev_dbg(dev, "SiFive PRCI probed\n"); 374 375 return 0; 376} 377 378static const struct of_device_id sifive_prci_of_match[] = { 379 {.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540}, | 393 * __prci_register_clocks() - register clock controls in the PRCI 394 * @dev: Linux struct device 395 * @pd: The pointer for PRCI per-device instance data 396 * @desc: The pointer for the information of clocks of each SoCs 397 * 398 * Register the list of clock controls described in __prci_init_clocks[] with 399 * the Linux clock framework. 400 * --- 90 unchanged lines hidden (view full) --- 491 492 dev_dbg(dev, "SiFive PRCI probed\n"); 493 494 return 0; 495} 496 497static const struct of_device_id sifive_prci_of_match[] = { 498 {.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540}, |
499 {.compatible = "sifive,fu740-c000-prci", .data = &prci_clk_fu740}, |
|
380 {} 381}; 382 383static struct platform_driver sifive_prci_driver = { 384 .driver = { 385 .name = "sifive-clk-prci", 386 .of_match_table = sifive_prci_of_match, 387 }, 388 .probe = sifive_prci_probe, 389}; 390 391static int __init sifive_prci_init(void) 392{ 393 return platform_driver_register(&sifive_prci_driver); 394} 395core_initcall(sifive_prci_init); | 500 {} 501}; 502 503static struct platform_driver sifive_prci_driver = { 504 .driver = { 505 .name = "sifive-clk-prci", 506 .of_match_table = sifive_prci_of_match, 507 }, 508 .probe = sifive_prci_probe, 509}; 510 511static int __init sifive_prci_init(void) 512{ 513 return platform_driver_register(&sifive_prci_driver); 514} 515core_initcall(sifive_prci_init); |