^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) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #define CLK_COUNT 4 /* cpu_clk, sys_clk, usb_clk, sdio_clk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) static struct clk *clks[CLK_COUNT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static struct clk_onecell_data clk_data = { clks, CLK_COUNT };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define SYSCLK_DIV 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define CPUCLK_DIV 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define DIV_BYPASS BIT(23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /*** CLKGEN_PLL ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define extract_pll_n(val) ((val >> 0) & ((1u << 7) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define extract_pll_k(val) ((val >> 13) & ((1u << 3) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define extract_pll_m(val) ((val >> 16) & ((1u << 3) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define extract_pll_isel(val) ((val >> 24) & ((1u << 3) - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static void __init make_pll(int idx, const char *parent, void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) char name[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) u32 val, mul, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) sprintf(name, "pll%d", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) val = readl(base + idx * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) mul = extract_pll_n(val) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) div = (extract_pll_m(val) + 1) << extract_pll_k(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) clk_register_fixed_factor(NULL, name, parent, 0, mul, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (extract_pll_isel(val) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) panic("%s: input not set to XTAL_IN\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void __init make_cd(int idx, void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) char name[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 val, mul, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) sprintf(name, "cd%d", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) val = readl(base + idx * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) mul = 1 << 27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) div = (2 << 27) + val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) clk_register_fixed_factor(NULL, name, "pll2", 0, mul, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (val > 0xf0000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) panic("%s: unsupported divider %x\n", name, val);
^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) static void __init tango4_clkgen_setup(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct clk **pp = clk_data.clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) void __iomem *base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const char *parent = of_clk_get_parent_name(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) panic("%pOFn: invalid address\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (readl(base + CPUCLK_DIV) & DIV_BYPASS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) panic("%pOFn: unsupported cpuclk setup\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (readl(base + SYSCLK_DIV) & DIV_BYPASS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) panic("%pOFn: unsupported sysclk setup\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) make_pll(0, parent, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) make_pll(1, parent, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) make_pll(2, parent, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) make_cd(2, base + 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) make_cd(6, base + 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pp[0] = clk_register_divider(NULL, "cpu_clk", "pll0", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) base + CPUCLK_DIV, 8, 8, CLK_DIVIDER_ONE_BASED, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pp[1] = clk_register_fixed_factor(NULL, "sys_clk", "pll1", 0, 1, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pp[2] = clk_register_fixed_factor(NULL, "usb_clk", "cd2", 0, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) panic("%pOFn: clk registration failed\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) panic("%pOFn: clk provider registration failed\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup);