1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2019 Daniel Palmer <daniel@thingy.jp> |
4 | */ |
5 | |
6 | #include <linux/clk-provider.h> |
7 | #include <linux/device.h> |
8 | #include <linux/kernel.h> |
9 | #include <linux/of_address.h> |
10 | #include <linux/platform_device.h> |
11 | |
12 | /* |
13 | * This IP is not documented outside of the messy vendor driver. |
14 | * Below is what we think the registers look like based on looking at |
15 | * the vendor code and poking at the hardware: |
16 | * |
17 | * 0x140 -- LPF low. Seems to store one half of the clock transition |
18 | * 0x144 / |
19 | * 0x148 -- LPF high. Seems to store one half of the clock transition |
20 | * 0x14c / |
21 | * 0x150 -- vendor code says "toggle lpf enable" |
22 | * 0x154 -- mu? |
23 | * 0x15c -- lpf_update_count? |
24 | * 0x160 -- vendor code says "switch to LPF". Clock source config? Register bank? |
25 | * 0x164 -- vendor code says "from low to high" which seems to mean transition from LPF low to |
26 | * LPF high. |
27 | * 0x174 -- Seems to be the PLL lock status bit |
28 | * 0x180 -- Seems to be the current frequency, this might need to be populated by software? |
29 | * 0x184 / The vendor driver uses these to set the initial value of LPF low |
30 | * |
31 | * Frequency seems to be calculated like this: |
32 | * (parent clock (432mhz) / register_magic_value) * 16 * 524288 |
33 | * Only the lower 24 bits of the resulting value will be used. In addition, the |
34 | * PLL doesn't seem to be able to lock on frequencies lower than 220 MHz, as |
35 | * divisor 0xfb586f (220 MHz) works but 0xfb7fff locks up. |
36 | * |
37 | * Vendor values: |
38 | * frequency - register value |
39 | * |
40 | * 400000000 - 0x0067AE14 |
41 | * 600000000 - 0x00451EB8, |
42 | * 800000000 - 0x0033D70A, |
43 | * 1000000000 - 0x002978d4, |
44 | */ |
45 | |
46 | #define REG_LPF_LOW_L 0x140 |
47 | #define REG_LPF_LOW_H 0x144 |
48 | #define REG_LPF_HIGH_BOTTOM 0x148 |
49 | #define REG_LPF_HIGH_TOP 0x14c |
50 | #define REG_LPF_TOGGLE 0x150 |
51 | #define REG_LPF_MYSTERYTWO 0x154 |
52 | #define REG_LPF_UPDATE_COUNT 0x15c |
53 | #define REG_LPF_MYSTERYONE 0x160 |
54 | #define REG_LPF_TRANSITIONCTRL 0x164 |
55 | #define REG_LPF_LOCK 0x174 |
56 | #define REG_CURRENT 0x180 |
57 | |
58 | #define LPF_LOCK_TIMEOUT 100000000 |
59 | |
60 | #define MULTIPLIER_1 16 |
61 | #define MULTIPLIER_2 524288 |
62 | #define MULTIPLIER (MULTIPLIER_1 * MULTIPLIER_2) |
63 | |
64 | struct msc313_cpupll { |
65 | void __iomem *base; |
66 | struct clk_hw clk_hw; |
67 | }; |
68 | |
69 | #define to_cpupll(_hw) container_of(_hw, struct msc313_cpupll, clk_hw) |
70 | |
71 | static u32 msc313_cpupll_reg_read32(struct msc313_cpupll *cpupll, unsigned int reg) |
72 | { |
73 | u32 value; |
74 | |
75 | value = ioread16(cpupll->base + reg + 4) << 16; |
76 | value |= ioread16(cpupll->base + reg); |
77 | |
78 | return value; |
79 | } |
80 | |
81 | static void msc313_cpupll_reg_write32(struct msc313_cpupll *cpupll, unsigned int reg, u32 value) |
82 | { |
83 | u16 l = value & 0xffff, h = (value >> 16) & 0xffff; |
84 | |
85 | iowrite16(l, cpupll->base + reg); |
86 | iowrite16(h, cpupll->base + reg + 4); |
87 | } |
88 | |
89 | static void msc313_cpupll_setfreq(struct msc313_cpupll *cpupll, u32 regvalue) |
90 | { |
91 | ktime_t timeout; |
92 | |
93 | msc313_cpupll_reg_write32(cpupll, REG_LPF_HIGH_BOTTOM, value: regvalue); |
94 | |
95 | iowrite16(0x1, cpupll->base + REG_LPF_MYSTERYONE); |
96 | iowrite16(0x6, cpupll->base + REG_LPF_MYSTERYTWO); |
97 | iowrite16(0x8, cpupll->base + REG_LPF_UPDATE_COUNT); |
98 | iowrite16(BIT(12), cpupll->base + REG_LPF_TRANSITIONCTRL); |
99 | |
100 | iowrite16(0, cpupll->base + REG_LPF_TOGGLE); |
101 | iowrite16(1, cpupll->base + REG_LPF_TOGGLE); |
102 | |
103 | timeout = ktime_add_ns(ktime_get(), LPF_LOCK_TIMEOUT); |
104 | while (!(ioread16(cpupll->base + REG_LPF_LOCK))) { |
105 | if (ktime_after(cmp1: ktime_get(), cmp2: timeout)) { |
106 | pr_err("timeout waiting for LPF_LOCK\n" ); |
107 | return; |
108 | } |
109 | cpu_relax(); |
110 | } |
111 | |
112 | iowrite16(0, cpupll->base + REG_LPF_TOGGLE); |
113 | |
114 | msc313_cpupll_reg_write32(cpupll, REG_LPF_LOW_L, value: regvalue); |
115 | } |
116 | |
117 | static unsigned long msc313_cpupll_frequencyforreg(u32 reg, unsigned long parent_rate) |
118 | { |
119 | unsigned long long prescaled = ((unsigned long long)parent_rate) * MULTIPLIER; |
120 | |
121 | if (prescaled == 0 || reg == 0) |
122 | return 0; |
123 | return DIV_ROUND_DOWN_ULL(prescaled, reg); |
124 | } |
125 | |
126 | static u32 msc313_cpupll_regforfrequecy(unsigned long rate, unsigned long parent_rate) |
127 | { |
128 | unsigned long long prescaled = ((unsigned long long)parent_rate) * MULTIPLIER; |
129 | |
130 | if (prescaled == 0 || rate == 0) |
131 | return 0; |
132 | return DIV_ROUND_UP_ULL(prescaled, rate); |
133 | } |
134 | |
135 | static unsigned long msc313_cpupll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
136 | { |
137 | struct msc313_cpupll *cpupll = to_cpupll(hw); |
138 | |
139 | return msc313_cpupll_frequencyforreg(reg: msc313_cpupll_reg_read32(cpupll, REG_LPF_LOW_L), |
140 | parent_rate); |
141 | } |
142 | |
143 | static long msc313_cpupll_round_rate(struct clk_hw *hw, unsigned long rate, |
144 | unsigned long *parent_rate) |
145 | { |
146 | u32 reg = msc313_cpupll_regforfrequecy(rate, parent_rate: *parent_rate); |
147 | long rounded = msc313_cpupll_frequencyforreg(reg, parent_rate: *parent_rate); |
148 | |
149 | /* |
150 | * This is my poor attempt at making sure the resulting |
151 | * rate doesn't overshoot the requested rate. |
152 | */ |
153 | for (; rounded >= rate && reg > 0; reg--) |
154 | rounded = msc313_cpupll_frequencyforreg(reg, parent_rate: *parent_rate); |
155 | |
156 | return rounded; |
157 | } |
158 | |
159 | static int msc313_cpupll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) |
160 | { |
161 | struct msc313_cpupll *cpupll = to_cpupll(hw); |
162 | u32 reg = msc313_cpupll_regforfrequecy(rate, parent_rate); |
163 | |
164 | msc313_cpupll_setfreq(cpupll, regvalue: reg); |
165 | |
166 | return 0; |
167 | } |
168 | |
169 | static const struct clk_ops msc313_cpupll_ops = { |
170 | .recalc_rate = msc313_cpupll_recalc_rate, |
171 | .round_rate = msc313_cpupll_round_rate, |
172 | .set_rate = msc313_cpupll_set_rate, |
173 | }; |
174 | |
175 | static const struct of_device_id msc313_cpupll_of_match[] = { |
176 | { .compatible = "mstar,msc313-cpupll" }, |
177 | {} |
178 | }; |
179 | |
180 | static int msc313_cpupll_probe(struct platform_device *pdev) |
181 | { |
182 | struct clk_init_data clk_init = {}; |
183 | struct clk_parent_data cpupll_parent = { .index = 0 }; |
184 | struct device *dev = &pdev->dev; |
185 | struct msc313_cpupll *cpupll; |
186 | int ret; |
187 | |
188 | cpupll = devm_kzalloc(dev: &pdev->dev, size: sizeof(*cpupll), GFP_KERNEL); |
189 | if (!cpupll) |
190 | return -ENOMEM; |
191 | |
192 | cpupll->base = devm_platform_ioremap_resource(pdev, index: 0); |
193 | if (IS_ERR(ptr: cpupll->base)) |
194 | return PTR_ERR(ptr: cpupll->base); |
195 | |
196 | /* LPF might not contain the current frequency so fix that up */ |
197 | msc313_cpupll_reg_write32(cpupll, REG_LPF_LOW_L, |
198 | value: msc313_cpupll_reg_read32(cpupll, REG_CURRENT)); |
199 | |
200 | clk_init.name = dev_name(dev); |
201 | clk_init.ops = &msc313_cpupll_ops; |
202 | clk_init.parent_data = &cpupll_parent; |
203 | clk_init.num_parents = 1; |
204 | cpupll->clk_hw.init = &clk_init; |
205 | |
206 | ret = devm_clk_hw_register(dev, hw: &cpupll->clk_hw); |
207 | if (ret) |
208 | return ret; |
209 | |
210 | return devm_of_clk_add_hw_provider(dev: &pdev->dev, get: of_clk_hw_simple_get, data: &cpupll->clk_hw); |
211 | } |
212 | |
213 | static struct platform_driver msc313_cpupll_driver = { |
214 | .driver = { |
215 | .name = "mstar-msc313-cpupll" , |
216 | .of_match_table = msc313_cpupll_of_match, |
217 | }, |
218 | .probe = msc313_cpupll_probe, |
219 | }; |
220 | builtin_platform_driver(msc313_cpupll_driver); |
221 | |