^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * MOXA ART SoCs clock driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2013 Jonas Jensen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Jonas Jensen <jonas.jensen@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.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/io.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/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static void __init moxart_of_pll_clk_init(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct clk *ref_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned int mul;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const char *name = node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) of_property_read_string(node, "clock-output-names", &name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) parent_name = of_clk_get_parent_name(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) pr_err("%pOF: of_iomap failed\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return;
^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) mul = readl(base + 0x30) >> 3 & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) iounmap(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ref_clk = of_clk_get(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (IS_ERR(ref_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) pr_err("%pOF: of_clk_get failed\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (IS_ERR(hw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) pr_err("%pOF: failed to register clock\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) clk_hw_register_clkdev(hw, NULL, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) moxart_of_pll_clk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void __init moxart_of_apb_clk_init(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct clk *pll_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int div, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int div_idx[] = { 2, 3, 4, 6, 8};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) const char *name = node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const char *parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) of_property_read_string(node, "clock-output-names", &name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) parent_name = of_clk_get_parent_name(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pr_err("%pOF: of_iomap failed\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) val = readl(base + 0xc) >> 4 & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) iounmap(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (val > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) div = div_idx[val] * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pll_clk = of_clk_get(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (IS_ERR(pll_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pr_err("%pOF: of_clk_get failed\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (IS_ERR(hw)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) pr_err("%pOF: failed to register clock\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) clk_hw_register_clkdev(hw, NULL, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) CLK_OF_DECLARE(moxart_apb_clock, "moxa,moxart-apb-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) moxart_of_apb_clk_init);