clk-a10-pll2.c (5280B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright 2013 Emilio López 4 * Emilio López <emilio@elopez.com.ar> 5 * 6 * Copyright 2015 Maxime Ripard 7 * Maxime Ripard <maxime.ripard@free-electrons.com> 8 */ 9 10#include <linux/clk-provider.h> 11#include <linux/io.h> 12#include <linux/of.h> 13#include <linux/of_address.h> 14#include <linux/slab.h> 15 16#include <dt-bindings/clock/sun4i-a10-pll2.h> 17 18#define SUN4I_PLL2_ENABLE 31 19 20#define SUN4I_PLL2_PRE_DIV_SHIFT 0 21#define SUN4I_PLL2_PRE_DIV_WIDTH 5 22#define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0) 23 24#define SUN4I_PLL2_N_SHIFT 8 25#define SUN4I_PLL2_N_WIDTH 7 26#define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0) 27 28#define SUN4I_PLL2_POST_DIV_SHIFT 26 29#define SUN4I_PLL2_POST_DIV_WIDTH 4 30#define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0) 31 32#define SUN4I_PLL2_POST_DIV_VALUE 4 33 34#define SUN4I_PLL2_OUTPUTS 4 35 36static DEFINE_SPINLOCK(sun4i_a10_pll2_lock); 37 38static void __init sun4i_pll2_setup(struct device_node *node, 39 int post_div_offset) 40{ 41 const char *clk_name = node->name, *parent; 42 struct clk **clks, *base_clk, *prediv_clk; 43 struct clk_onecell_data *clk_data; 44 struct clk_multiplier *mult; 45 struct clk_gate *gate; 46 void __iomem *reg; 47 u32 val; 48 49 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 50 if (IS_ERR(reg)) 51 return; 52 53 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); 54 if (!clk_data) 55 goto err_unmap; 56 57 clks = kcalloc(SUN4I_PLL2_OUTPUTS, sizeof(struct clk *), GFP_KERNEL); 58 if (!clks) 59 goto err_free_data; 60 61 parent = of_clk_get_parent_name(node, 0); 62 prediv_clk = clk_register_divider(NULL, "pll2-prediv", 63 parent, 0, reg, 64 SUN4I_PLL2_PRE_DIV_SHIFT, 65 SUN4I_PLL2_PRE_DIV_WIDTH, 66 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, 67 &sun4i_a10_pll2_lock); 68 if (IS_ERR(prediv_clk)) { 69 pr_err("Couldn't register the prediv clock\n"); 70 goto err_free_array; 71 } 72 73 /* Setup the gate part of the PLL2 */ 74 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); 75 if (!gate) 76 goto err_unregister_prediv; 77 78 gate->reg = reg; 79 gate->bit_idx = SUN4I_PLL2_ENABLE; 80 gate->lock = &sun4i_a10_pll2_lock; 81 82 /* Setup the multiplier part of the PLL2 */ 83 mult = kzalloc(sizeof(struct clk_multiplier), GFP_KERNEL); 84 if (!mult) 85 goto err_free_gate; 86 87 mult->reg = reg; 88 mult->shift = SUN4I_PLL2_N_SHIFT; 89 mult->width = 7; 90 mult->flags = CLK_MULTIPLIER_ZERO_BYPASS | 91 CLK_MULTIPLIER_ROUND_CLOSEST; 92 mult->lock = &sun4i_a10_pll2_lock; 93 94 parent = __clk_get_name(prediv_clk); 95 base_clk = clk_register_composite(NULL, "pll2-base", 96 &parent, 1, 97 NULL, NULL, 98 &mult->hw, &clk_multiplier_ops, 99 &gate->hw, &clk_gate_ops, 100 CLK_SET_RATE_PARENT); 101 if (IS_ERR(base_clk)) { 102 pr_err("Couldn't register the base multiplier clock\n"); 103 goto err_free_multiplier; 104 } 105 106 parent = __clk_get_name(base_clk); 107 108 /* 109 * PLL2-1x 110 * 111 * This is supposed to have a post divider, but we won't need 112 * to use it, we just need to initialise it to 4, and use a 113 * fixed divider. 114 */ 115 val = readl(reg); 116 val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT); 117 val |= (SUN4I_PLL2_POST_DIV_VALUE - post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT; 118 writel(val, reg); 119 120 of_property_read_string_index(node, "clock-output-names", 121 SUN4I_A10_PLL2_1X, &clk_name); 122 clks[SUN4I_A10_PLL2_1X] = clk_register_fixed_factor(NULL, clk_name, 123 parent, 124 CLK_SET_RATE_PARENT, 125 1, 126 SUN4I_PLL2_POST_DIV_VALUE); 127 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_1X])); 128 129 /* 130 * PLL2-2x 131 * 132 * This clock doesn't use the post divider, and really is just 133 * a fixed divider from the PLL2 base clock. 134 */ 135 of_property_read_string_index(node, "clock-output-names", 136 SUN4I_A10_PLL2_2X, &clk_name); 137 clks[SUN4I_A10_PLL2_2X] = clk_register_fixed_factor(NULL, clk_name, 138 parent, 139 CLK_SET_RATE_PARENT, 140 1, 2); 141 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_2X])); 142 143 /* PLL2-4x */ 144 of_property_read_string_index(node, "clock-output-names", 145 SUN4I_A10_PLL2_4X, &clk_name); 146 clks[SUN4I_A10_PLL2_4X] = clk_register_fixed_factor(NULL, clk_name, 147 parent, 148 CLK_SET_RATE_PARENT, 149 1, 1); 150 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_4X])); 151 152 /* PLL2-8x */ 153 of_property_read_string_index(node, "clock-output-names", 154 SUN4I_A10_PLL2_8X, &clk_name); 155 clks[SUN4I_A10_PLL2_8X] = clk_register_fixed_factor(NULL, clk_name, 156 parent, 157 CLK_SET_RATE_PARENT, 158 2, 1); 159 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_8X])); 160 161 clk_data->clks = clks; 162 clk_data->clk_num = SUN4I_PLL2_OUTPUTS; 163 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 164 165 return; 166 167err_free_multiplier: 168 kfree(mult); 169err_free_gate: 170 kfree(gate); 171err_unregister_prediv: 172 clk_unregister_divider(prediv_clk); 173err_free_array: 174 kfree(clks); 175err_free_data: 176 kfree(clk_data); 177err_unmap: 178 iounmap(reg); 179} 180 181static void __init sun4i_a10_pll2_setup(struct device_node *node) 182{ 183 sun4i_pll2_setup(node, 0); 184} 185 186CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk", 187 sun4i_a10_pll2_setup); 188 189static void __init sun5i_a13_pll2_setup(struct device_node *node) 190{ 191 sun4i_pll2_setup(node, 1); 192} 193 194CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk", 195 sun5i_a13_pll2_setup);