Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2018-2019 SiFive, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Wesley Terpstra
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Paul Walmsley
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * it under the terms of the GNU General Public License version 2 as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * The FU540 PRCI implements clock and reset control for the SiFive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * FU540-C000 chip.  This driver assumes that it has sole control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * over all PRCI resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * This driver is based on the PRCI driver written by Wesley Terpstra:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * https://github.com/riscv/riscv-linux/commit/999529edf517ed75b56659d456d221b2ee56bb60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * References:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * - SiFive FU540-C000 manual v1p0, Chapter 7 "Clocking and Reset"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <dt-bindings/clock/sifive-fu540-prci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/clk/analogbits-wrpll-cln28hpc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <linux/of_clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *     hfclk and rtcclk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define EXPECTED_CLK_PARENT_COUNT		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * Register offsets and bitmasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) /* COREPLLCFG0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define PRCI_COREPLLCFG0_OFFSET			0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) # define PRCI_COREPLLCFG0_DIVR_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) # define PRCI_COREPLLCFG0_DIVR_MASK		(0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) # define PRCI_COREPLLCFG0_DIVF_SHIFT		6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) # define PRCI_COREPLLCFG0_DIVF_MASK		(0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) # define PRCI_COREPLLCFG0_DIVQ_SHIFT		15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) # define PRCI_COREPLLCFG0_DIVQ_MASK		(0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) # define PRCI_COREPLLCFG0_RANGE_SHIFT		18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) # define PRCI_COREPLLCFG0_RANGE_MASK		(0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) # define PRCI_COREPLLCFG0_BYPASS_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) # define PRCI_COREPLLCFG0_BYPASS_MASK		(0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) # define PRCI_COREPLLCFG0_FSE_SHIFT		25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) # define PRCI_COREPLLCFG0_FSE_MASK		(0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) # define PRCI_COREPLLCFG0_LOCK_SHIFT		31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) # define PRCI_COREPLLCFG0_LOCK_MASK		(0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) /* DDRPLLCFG0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define PRCI_DDRPLLCFG0_OFFSET			0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) # define PRCI_DDRPLLCFG0_DIVR_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) # define PRCI_DDRPLLCFG0_DIVR_MASK		(0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) # define PRCI_DDRPLLCFG0_DIVF_SHIFT		6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) # define PRCI_DDRPLLCFG0_DIVF_MASK		(0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) # define PRCI_DDRPLLCFG0_DIVQ_SHIFT		15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) # define PRCI_DDRPLLCFG0_DIVQ_MASK		(0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) # define PRCI_DDRPLLCFG0_RANGE_SHIFT		18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) # define PRCI_DDRPLLCFG0_RANGE_MASK		(0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) # define PRCI_DDRPLLCFG0_BYPASS_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) # define PRCI_DDRPLLCFG0_BYPASS_MASK		(0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) # define PRCI_DDRPLLCFG0_FSE_SHIFT		25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) # define PRCI_DDRPLLCFG0_FSE_MASK		(0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) # define PRCI_DDRPLLCFG0_LOCK_SHIFT		31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) # define PRCI_DDRPLLCFG0_LOCK_MASK		(0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) /* DDRPLLCFG1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) #define PRCI_DDRPLLCFG1_OFFSET			0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) # define PRCI_DDRPLLCFG1_CKE_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) # define PRCI_DDRPLLCFG1_CKE_MASK		(0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) /* GEMGXLPLLCFG0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #define PRCI_GEMGXLPLLCFG0_OFFSET		0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) # define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT		0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) # define PRCI_GEMGXLPLLCFG0_DIVR_MASK		(0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) # define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT		6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) # define PRCI_GEMGXLPLLCFG0_DIVF_MASK		(0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) # define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT		15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) # define PRCI_GEMGXLPLLCFG0_DIVQ_MASK		(0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) # define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT		18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) # define PRCI_GEMGXLPLLCFG0_RANGE_MASK		(0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) # define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT	24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) # define PRCI_GEMGXLPLLCFG0_BYPASS_MASK		(0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) # define PRCI_GEMGXLPLLCFG0_FSE_SHIFT		25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) # define PRCI_GEMGXLPLLCFG0_FSE_MASK		(0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) # define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT		31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) # define PRCI_GEMGXLPLLCFG0_LOCK_MASK		(0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* GEMGXLPLLCFG1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PRCI_GEMGXLPLLCFG1_OFFSET		0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) # define PRCI_GEMGXLPLLCFG1_CKE_SHIFT		24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) # define PRCI_GEMGXLPLLCFG1_CKE_MASK		(0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* CORECLKSEL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define PRCI_CORECLKSEL_OFFSET			0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) # define PRCI_CORECLKSEL_CORECLKSEL_SHIFT	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) # define PRCI_CORECLKSEL_CORECLKSEL_MASK	(0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* DEVICESRESETREG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define PRCI_DEVICESRESETREG_OFFSET			0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) # define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) # define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK	(0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) # define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) # define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK	(0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) # define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) # define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK	(0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) # define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT	3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) # define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK	(0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) # define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) # define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK		(0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* CLKMUXSTATUSREG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define PRCI_CLKMUXSTATUSREG_OFFSET			0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) # define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) # define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK	(0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  * Private structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * struct __prci_data - per-device-instance data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * @va: base virtual address of the PRCI IP block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  * @hw_clks: encapsulates struct clk_hw records
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * PRCI per-device instance data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct __prci_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	void __iomem *va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	struct clk_hw_onecell_data hw_clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  * struct __prci_wrpll_data - WRPLL configuration and integration data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * @c: WRPLL current configuration record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * @enable_bypass and @disable_bypass are used for WRPLL instances
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  * that contain a separate external glitchless clock mux downstream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  * from the PLL.  The WRPLL internal bypass mux is not glitchless.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct __prci_wrpll_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	struct wrpll_cfg c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	void (*enable_bypass)(struct __prci_data *pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	void (*disable_bypass)(struct __prci_data *pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	u8 cfg0_offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * struct __prci_clock - describes a clock device managed by PRCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * @name: user-readable clock name string - should match the manual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  * @parent_name: parent name for this clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  * @ops: struct clk_ops for the Linux clock framework to use for control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)  * @hw: Linux-private clock data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)  * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * @pd: PRCI-specific data associated with this clock (if not NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * clocks to the Linux clock infrastructure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct __prci_clock {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	const struct clk_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	struct __prci_wrpll_data *pwd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	struct __prci_data *pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  * Private functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * __prci_readl() - read from a PRCI register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * @pd: PRCI context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * @offs: register offset to read from (in bytes, from PRCI base address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * Read the register located at offset @offs from the base virtual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  * address of the PRCI register target described by @pd, and return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  * the value to the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * Context: Any context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * Return: the contents of the register described by @pd and @offs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static u32 __prci_readl(struct __prci_data *pd, u32 offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	return readl_relaxed(pd->va + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	writel_relaxed(v, pd->va + offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* WRPLL-related private functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * @c: ptr to a struct wrpll_cfg record to write config into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  * @r: value read from the PRCI PLL configuration register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * Given a value @r read from an FU540 PRCI PLL configuration register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  * split it into fields and populate it into the WRPLL configuration record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  * pointed to by @c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  * have the same register layout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  * Context: Any context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	v = r & PRCI_COREPLLCFG0_DIVR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	c->divr = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	v = r & PRCI_COREPLLCFG0_DIVF_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	c->divf = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	c->divq = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	v = r & PRCI_COREPLLCFG0_RANGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	c->range = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		     WRPLL_FLAGS_EXT_FEEDBACK_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	/* external feedback mode not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)  * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)  * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)  * Using a set of WRPLL configuration values pointed to by @c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)  * assemble a PRCI PLL configuration register value, and return it to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)  * the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)  * Context: Any context.  Caller must ensure that the contents of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)  *          record pointed to by @c do not change during the execution
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  *          of this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * Returns: a value suitable for writing into a PRCI PLL configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  *          register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	u32 r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	/* external feedback mode not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	r |= PRCI_COREPLLCFG0_FSE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * @pd: PRCI context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  * @pwd: PRCI WRPLL metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  * Read the current configuration of the PLL identified by @pwd from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  * the PRCI identified by @pd, and store it into the local configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  * cache in @pwd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)  * Context: Any context.  Caller must prevent the records pointed to by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)  *          @pd and @pwd from changing during execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void __prci_wrpll_read_cfg(struct __prci_data *pd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 				  struct __prci_wrpll_data *pwd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	__prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)  * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)  * @pd: PRCI context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)  * @pwd: PRCI WRPLL metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)  * @c: WRPLL configuration record to write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)  * Write the WRPLL configuration described by @c into the WRPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)  * configuration register identified by @pwd in the PRCI instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  * described by @c.  Make a cached copy of the WRPLL's current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  * configuration so it can be used by other code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  * Context: Any context.  Caller must prevent the records pointed to by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  *          @pd and @pwd from changing during execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void __prci_wrpll_write_cfg(struct __prci_data *pd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 				   struct __prci_wrpll_data *pwd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 				   struct wrpll_cfg *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	__prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	memcpy(&pwd->c, c, sizeof(*c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Core clock mux control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * __prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  * Switch the CORECLK mux to the HFCLK input source; return once complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  * Context: Any context.  Caller must prevent concurrent changes to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  *          PRCI_CORECLKSEL_OFFSET register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static void __prci_coreclksel_use_hfclk(struct __prci_data *pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	__prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  * __prci_coreclksel_use_corepll() - switch the CORECLK mux to output COREPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)  * Switch the CORECLK mux to the PLL output clock; return once complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)  * Context: Any context.  Caller must prevent concurrent changes to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)  *          PRCI_CORECLKSEL_OFFSET register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) static void __prci_coreclksel_use_corepll(struct __prci_data *pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	__prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)  * Linux clock framework integration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)  * See the Linux clock framework documentation for more information on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)  * these functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static unsigned long sifive_fu540_prci_wrpll_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 							 unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	struct __prci_wrpll_data *pwd = pc->pwd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	return wrpll_calc_output_rate(&pwd->c, parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) static long sifive_fu540_prci_wrpll_round_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 					       unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 					       unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	struct __prci_wrpll_data *pwd = pc->pwd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	struct wrpll_cfg c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	memcpy(&c, &pwd->c, sizeof(c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	wrpll_configure_for_rate(&c, rate, *parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	return wrpll_calc_output_rate(&c, *parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int sifive_fu540_prci_wrpll_set_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 					    unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 					    unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	struct __prci_wrpll_data *pwd = pc->pwd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	struct __prci_data *pd = pc->pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (pwd->enable_bypass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		pwd->enable_bypass(pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	__prci_wrpll_write_cfg(pd, pwd, &pwd->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	udelay(wrpll_calc_max_lock_us(&pwd->c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if (pwd->disable_bypass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		pwd->disable_bypass(pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	.set_rate = sifive_fu540_prci_wrpll_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	.round_rate = sifive_fu540_prci_wrpll_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	.recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	.recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* TLCLKSEL clock integration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 							    unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	struct __prci_data *pd = pc->pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	u8 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	div = v ? 1 : 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	return div_u64(parent_rate, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	.recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)  * PRCI integration data for each WRPLL instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static struct __prci_wrpll_data __prci_corepll_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	.cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	.enable_bypass = __prci_coreclksel_use_hfclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	.disable_bypass = __prci_coreclksel_use_corepll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static struct __prci_wrpll_data __prci_ddrpll_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	.cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) static struct __prci_wrpll_data __prci_gemgxlpll_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	.cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)  * List of clock controls provided by the PRCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static struct __prci_clock __prci_init_clocks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	[PRCI_CLK_COREPLL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		.name = "corepll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		.parent_name = "hfclk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		.ops = &sifive_fu540_prci_wrpll_clk_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		.pwd = &__prci_corepll_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	[PRCI_CLK_DDRPLL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		.name = "ddrpll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 		.parent_name = "hfclk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		.ops = &sifive_fu540_prci_wrpll_ro_clk_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		.pwd = &__prci_ddrpll_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	[PRCI_CLK_GEMGXLPLL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		.name = "gemgxlpll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		.parent_name = "hfclk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		.ops = &sifive_fu540_prci_wrpll_clk_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		.pwd = &__prci_gemgxlpll_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	[PRCI_CLK_TLCLK] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		.name = "tlclk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		.parent_name = "corepll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 		.ops = &sifive_fu540_prci_tlclksel_clk_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  * __prci_register_clocks() - register clock controls in the PRCI with Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  * @dev: Linux struct device *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)  * Register the list of clock controls described in __prci_init_plls[] with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)  * the Linux clock framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)  * Return: 0 upon success or a negative error code upon failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) static int __prci_register_clocks(struct device *dev, struct __prci_data *pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	struct clk_init_data init = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	struct __prci_clock *pic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	int parent_count, i, r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	parent_count = of_clk_get_parent_count(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		dev_err(dev, "expected only two parent clocks, found %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 			parent_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	/* Register PLLs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	for (i = 0; i < ARRAY_SIZE(__prci_init_clocks); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		pic = &__prci_init_clocks[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		init.name = pic->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		init.parent_names = &pic->parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		init.ops = pic->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		pic->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		pic->pd = pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		if (pic->pwd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 			__prci_wrpll_read_cfg(pd, pic->pwd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		r = devm_clk_hw_register(dev, &pic->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 			dev_warn(dev, "Failed to register clock %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 				 init.name, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 			return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 			dev_warn(dev, "Failed to register clkdev for %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 				 init.name, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		pd->hw_clks.hws[i] = &pic->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	pd->hw_clks.num = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 					&pd->hw_clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		dev_err(dev, "could not add hw_provider: %d\n", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 		return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)  * Linux device model integration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)  * See the Linux device model documentation for more information about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)  * these functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int sifive_fu540_prci_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	struct __prci_data *pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	pd = devm_kzalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			  struct_size(pd, hw_clks.hws,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 				      ARRAY_SIZE(__prci_init_clocks)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 			  GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	if (!pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	pd->va = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	if (IS_ERR(pd->va))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		return PTR_ERR(pd->va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 	r = __prci_register_clocks(dev, pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		dev_err(dev, "could not register clocks: %d\n", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 		return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	dev_dbg(dev, "SiFive FU540 PRCI probed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) static const struct of_device_id sifive_fu540_prci_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	{ .compatible = "sifive,fu540-c000-prci", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) MODULE_DEVICE_TABLE(of, sifive_fu540_prci_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static struct platform_driver sifive_fu540_prci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	.driver	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 		.name = "sifive-fu540-prci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		.of_match_table = sifive_fu540_prci_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	.probe = sifive_fu540_prci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static int __init sifive_fu540_prci_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	return platform_driver_register(&sifive_fu540_prci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) core_initcall(sifive_fu540_prci_init);