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-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Nomadik clock implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2013 ST-Ericsson AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Author: Linus Walleij <linus.walleij@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * The Nomadik clock tree is described in the STN8815A12 DB V4.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * reference manual for the chip, page 94 ff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * Clock IDs are in the STn8815 Reference Manual table 3, page 27.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define SRC_CR			0x00U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define SRC_CR_T0_ENSEL		BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define SRC_CR_T1_ENSEL		BIT(17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define SRC_CR_T2_ENSEL		BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define SRC_CR_T3_ENSEL		BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define SRC_CR_T4_ENSEL		BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define SRC_CR_T5_ENSEL		BIT(25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define SRC_CR_T6_ENSEL		BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define SRC_CR_T7_ENSEL		BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define SRC_XTALCR		0x0CU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define SRC_XTALCR_XTALTIMEN	BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define SRC_XTALCR_SXTALDIS	BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define SRC_XTALCR_MXTALSTAT	BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define SRC_XTALCR_MXTALEN	BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define SRC_XTALCR_MXTALOVER	BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define SRC_PLLCR		0x10U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define SRC_PLLCR_PLLTIMEN	BIT(29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define SRC_PLLCR_PLL2EN	BIT(28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define SRC_PLLCR_PLL1STAT	BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define SRC_PLLCR_PLL1EN	BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define SRC_PLLCR_PLL1OVER	BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define SRC_PLLFR		0x14U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define SRC_PCKEN0		0x24U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define SRC_PCKDIS0		0x28U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define SRC_PCKENSR0		0x2CU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) #define SRC_PCKSR0		0x30U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define SRC_PCKEN1		0x34U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define SRC_PCKDIS1		0x38U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define SRC_PCKENSR1		0x3CU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define SRC_PCKSR1		0x40U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) /* Lock protecting the SRC_CR register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) static DEFINE_SPINLOCK(src_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) /* Base address of the SRC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static void __iomem *src_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static int nomadik_clk_reboot_handler(struct notifier_block *this,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 				unsigned long code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	/* The main chrystal need to be enabled for reboot to work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	val = readl(src_base + SRC_XTALCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	val &= ~SRC_XTALCR_MXTALOVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	val |= SRC_XTALCR_MXTALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	pr_crit("force-enabling MXTALO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	writel(val, src_base + SRC_XTALCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static struct notifier_block nomadik_clk_reboot_notifier = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	.notifier_call = nomadik_clk_reboot_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) static const struct of_device_id nomadik_src_match[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	{ .compatible = "stericsson,nomadik-src" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	{ /* sentinel */ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static void __init nomadik_src_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	np = of_find_matching_node(NULL, nomadik_src_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (!np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		pr_crit("no matching node for SRC, aborting clock init\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	src_base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (!src_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		pr_err("%s: must have src parent node with REGS (%pOFn)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		       __func__, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	/* Set all timers to use the 2.4 MHz TIMCLK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	val = readl(src_base + SRC_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	val |= SRC_CR_T0_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	val |= SRC_CR_T1_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	val |= SRC_CR_T2_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	val |= SRC_CR_T3_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	val |= SRC_CR_T4_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	val |= SRC_CR_T5_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	val |= SRC_CR_T6_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	val |= SRC_CR_T7_ENSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	writel(val, src_base + SRC_CR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	val = readl(src_base + SRC_XTALCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	pr_info("SXTALO is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		(val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	pr_info("MXTAL is %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		(val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (of_property_read_bool(np, "disable-sxtalo")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		/* The machine uses an external oscillator circuit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		val |= SRC_XTALCR_SXTALDIS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		pr_info("disabling SXTALO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (of_property_read_bool(np, "disable-mxtalo")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		/* Disable this too: also run by external oscillator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		val |= SRC_XTALCR_MXTALOVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		val &= ~SRC_XTALCR_MXTALEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		pr_info("disabling MXTALO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	writel(val, src_base + SRC_XTALCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	register_reboot_notifier(&nomadik_clk_reboot_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^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)  * struct clk_pll1 - Nomadik PLL1 clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  * @hw: corresponding clock hardware entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * @id: PLL instance: 1 or 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct clk_pll {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * struct clk_src - Nomadik src clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  * @hw: corresponding clock hardware entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  * @id: the clock ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  * @group1: true if the clock is in group1, else it is in group0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * @clkbit: bit 0...31 corresponding to the clock in each clock register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct clk_src {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	bool group1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	u32 clkbit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define to_pll(_hw) container_of(_hw, struct clk_pll, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define to_src(_hw) container_of(_hw, struct clk_src, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int pll_clk_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	struct clk_pll *pll = to_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	spin_lock(&src_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	val = readl(src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (pll->id == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		if (val & SRC_PLLCR_PLL1OVER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			val |= SRC_PLLCR_PLL1EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			writel(val, src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	} else if (pll->id == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		val |= SRC_PLLCR_PLL2EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		writel(val, src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	spin_unlock(&src_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static void pll_clk_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	struct clk_pll *pll = to_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	spin_lock(&src_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	val = readl(src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (pll->id == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		if (val & SRC_PLLCR_PLL1OVER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			val &= ~SRC_PLLCR_PLL1EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			writel(val, src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	} else if (pll->id == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		val &= ~SRC_PLLCR_PLL2EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		writel(val, src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	spin_unlock(&src_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int pll_clk_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	struct clk_pll *pll = to_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	val = readl(src_base + SRC_PLLCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	if (pll->id == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		if (val & SRC_PLLCR_PLL1OVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			return !!(val & SRC_PLLCR_PLL1EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	} else if (pll->id == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		return !!(val & SRC_PLLCR_PLL2EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	return 1;
^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) static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 					  unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	struct clk_pll *pll = to_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	val = readl(src_base + SRC_PLLFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (pll->id == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		u8 mul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		u8 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		mul = (val >> 8) & 0x3FU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		mul += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		div = val & 0x07U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		return (parent_rate * mul) >> div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	if (pll->id == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		u8 mul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		mul = (val >> 24) & 0x3FU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		mul += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		return (parent_rate * mul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	/* Unknown PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static const struct clk_ops pll_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	.enable = pll_clk_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	.disable = pll_clk_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	.is_enabled = pll_clk_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	.recalc_rate = pll_clk_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static struct clk_hw * __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) pll_clk_register(struct device *dev, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		 const char *parent_name, u32 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	struct clk_pll *pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (id != 1 && id != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		pr_err("%s: the Nomadik has only PLL 1 & 2\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (!pll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	init.ops = &pll_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	init.parent_names = (parent_name ? &parent_name : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	init.num_parents = (parent_name ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	pll->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	pll->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	pr_debug("register PLL1 clock \"%s\"\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	ret = clk_hw_register(dev, &pll->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		kfree(pll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	return &pll->hw;
^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)  * The Nomadik SRC clocks are gated, but not in the sense that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * you read-modify-write a register. Instead there are separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  * clock enable and clock disable registers. Writing a '1' bit in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  * the enable register for a certain clock ungates that clock without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  * affecting the other clocks. The disable register works the opposite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  * way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static int src_clk_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	struct clk_src *sclk = to_src(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	u32 enreg = sclk->group1 ? SRC_PCKEN1 : SRC_PCKEN0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	writel(sclk->clkbit, src_base + enreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	/* spin until enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	while (!(readl(src_base + sreg) & sclk->clkbit))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static void src_clk_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	struct clk_src *sclk = to_src(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	u32 disreg = sclk->group1 ? SRC_PCKDIS1 : SRC_PCKDIS0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	writel(sclk->clkbit, src_base + disreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	/* spin until disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	while (readl(src_base + sreg) & sclk->clkbit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int src_clk_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	struct clk_src *sclk = to_src(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	u32 val = readl(src_base + sreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	return !!(val & sclk->clkbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) src_clk_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		    unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	return parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) static const struct clk_ops src_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	.enable = src_clk_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	.disable = src_clk_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	.is_enabled = src_clk_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	.recalc_rate = src_clk_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static struct clk_hw * __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) src_clk_register(struct device *dev, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		 const char *parent_name, u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	struct clk_src *sclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	if (!sclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	init.ops = &src_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	/* Do not force-disable the static SDRAM controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	if (id == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		init.flags = CLK_IGNORE_UNUSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	init.parent_names = (parent_name ? &parent_name : NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	init.num_parents = (parent_name ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	sclk->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	sclk->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	sclk->group1 = (id > 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	sclk->clkbit = BIT(id & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		 name, id, sclk->group1, sclk->clkbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	ret = clk_hw_register(dev, &sclk->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		kfree(sclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	return &sclk->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static u32 src_pcksr0_boot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static u32 src_pcksr1_boot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static const char * const src_clk_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	"HCLKDMA0  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	"HCLKSMC   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	"HCLKSDRAM ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	"HCLKDMA1  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	"HCLKCLCD  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	"PCLKIRDA  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	"PCLKSSP   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	"PCLKUART0 ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	"PCLKSDI   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	"PCLKI2C0  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	"PCLKI2C1  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	"PCLKUART1 ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	"PCLMSP0   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	"HCLKUSB   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	"HCLKDIF   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	"HCLKSAA   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	"HCLKSVA   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	"PCLKHSI   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	"PCLKXTI   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	"PCLKUART2 ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	"PCLKMSP1  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	"PCLKMSP2  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	"PCLKOWM   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	"HCLKHPI   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	"PCLKSKE   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	"PCLKHSEM  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	"HCLK3D    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	"HCLKHASH  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 	"HCLKCRYP  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	"PCLKMSHC  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	"HCLKUSBM  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	"HCLKRNG   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	"RESERVED  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	"RESERVED  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	"RESERVED  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	"RESERVED  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	"CLDCLK    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	"IRDACLK   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	"SSPICLK   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	"UART0CLK  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	"SDICLK    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	"I2C0CLK   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	"I2C1CLK   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	"UART1CLK  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	"MSPCLK0   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	"USBCLK    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	"DIFCLK    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	"IPI2CCLK  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	"IPBMCCLK  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	"HSICLKRX  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	"HSICLKTX  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	"UART2CLK  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	"MSPCLK1   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	"MSPCLK2   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	"OWMCLK    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	"RESERVED  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	"SKECLK    ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	"RESERVED  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	"3DCLK     ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	"PCLKMSP3  ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	"MSPCLK3   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	"MSHCCLK   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	"USBMCLK   ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	"RNGCCLK   ",
^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 int nomadik_src_clk_debugfs_show(struct seq_file *s, void *what)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	u32 src_pcksr0 = readl(src_base + SRC_PCKSR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	u32 src_pcksr1 = readl(src_base + SRC_PCKSR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	seq_puts(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		u32 pckreq = (i < 0x20) ? src_pckensr0 : src_pckensr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		u32 mask = BIT(i & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		seq_printf(s, "%s  %s     %s     %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 			   src_clk_names[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 			   (pcksrb & mask) ? "on " : "off",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 			   (pcksr & mask) ? "on " : "off",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 			   (pckreq & mask) ? "on " : "off");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) DEFINE_SHOW_ATTRIBUTE(nomadik_src_clk_debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int __init nomadik_src_clk_init_debugfs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	/* Vital for multiplatform */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	if (!src_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 			    NULL, NULL, &nomadik_src_clk_debugfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) device_initcall(nomadik_src_clk_init_debugfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void __init of_nomadik_pll_setup(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	const char *clk_name = np->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	u32 pll_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	if (!src_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		nomadik_src_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	if (of_property_read_u32(np, "pll-id", &pll_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		pr_err("%s: PLL \"%s\" missing pll-id property\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 			__func__, clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	parent_name = of_clk_get_parent_name(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	hw = pll_clk_register(NULL, clk_name, parent_name, pll_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	if (!IS_ERR(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) CLK_OF_DECLARE(nomadik_pll_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	"st,nomadik-pll-clock", of_nomadik_pll_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) static void __init of_nomadik_hclk_setup(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	const char *clk_name = np->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	if (!src_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		nomadik_src_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	parent_name = of_clk_get_parent_name(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	 * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	hw = clk_hw_register_divider(NULL, clk_name, parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			   0, src_base + SRC_CR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			   13, 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 			   &src_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	if (!IS_ERR(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) CLK_OF_DECLARE(nomadik_hclk_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	"st,nomadik-hclk-clock", of_nomadik_hclk_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static void __init of_nomadik_src_clk_setup(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	const char *clk_name = np->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	u32 clk_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	if (!src_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		nomadik_src_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	if (of_property_read_u32(np, "clock-id", &clk_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			__func__, clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	parent_name = of_clk_get_parent_name(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	hw = src_clk_register(NULL, clk_name, parent_name, clk_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	if (!IS_ERR(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) CLK_OF_DECLARE(nomadik_src_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	"st,nomadik-src-clock", of_nomadik_src_clk_setup);