^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2011-2012 Calxeda, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2012-2013 Altera Corporation <www.altera.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based from clk-highbank.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u32 div, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (socfpgaclk->fixed_div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) div = socfpgaclk->fixed_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (socfpgaclk->div_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) val &= GENMASK(socfpgaclk->width - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) parent_rate /= (val + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return parent_rate / div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 clk_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) clk_src = readl(clk_mgr_base_addr + CLKMGR_DBCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return clk_src & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static const struct clk_ops periclk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .recalc_rate = clk_periclk_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .get_parent = clk_periclk_get_parent,
^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 __init void __socfpga_periph_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) const struct clk_ops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct socfpga_periph_clk *periph_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const char *clk_name = node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) const char *parent_name[SOCFPGA_MAX_PARENTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u32 fixed_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 div_reg[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) of_property_read_u32(node, "reg", ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (WARN_ON(!periph_clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) periph_clk->hw.reg = clk_mgr_base_addr + reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) periph_clk->div_reg = clk_mgr_base_addr + div_reg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) periph_clk->shift = div_reg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) periph_clk->width = div_reg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) periph_clk->div_reg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) periph_clk->fixed_div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) periph_clk->fixed_div = fixed_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) of_property_read_string(node, "clock-output-names", &clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) init.name = clk_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) init.ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) init.num_parents = of_clk_parent_fill(node, parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) SOCFPGA_MAX_PARENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) init.parent_names = parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) periph_clk->hw.hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) clk = clk_register(NULL, &periph_clk->hw.hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (WARN_ON(IS_ERR(clk))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) kfree(periph_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) void __init socfpga_periph_init(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) __socfpga_periph_init(node, &periclk_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }