^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);