Merge tag 'gfs2-for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux...
[linux-2.6-microblaze.git] / drivers / clk / xilinx / xlnx_vcu.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Xilinx VCU Init
4  *
5  * Copyright (C) 2016 - 2017 Xilinx, Inc.
6  *
7  * Contacts   Dhaval Shah <dshah@xilinx.com>
8  */
9 #include <linux/bitfield.h>
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/device.h>
13 #include <linux/errno.h>
14 #include <linux/io.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/mfd/syscon/xlnx-vcu.h>
17 #include <linux/module.h>
18 #include <linux/of_platform.h>
19 #include <linux/platform_device.h>
20 #include <linux/regmap.h>
21
22 #include <dt-bindings/clock/xlnx-vcu.h>
23
24 #define VCU_PLL_CTRL                    0x24
25 #define VCU_PLL_CTRL_RESET              BIT(0)
26 #define VCU_PLL_CTRL_POR_IN             BIT(1)
27 #define VCU_PLL_CTRL_PWR_POR            BIT(2)
28 #define VCU_PLL_CTRL_BYPASS             BIT(3)
29 #define VCU_PLL_CTRL_FBDIV              GENMASK(14, 8)
30 #define VCU_PLL_CTRL_CLKOUTDIV          GENMASK(18, 16)
31
32 #define VCU_PLL_CFG                     0x28
33 #define VCU_PLL_CFG_RES                 GENMASK(3, 0)
34 #define VCU_PLL_CFG_CP                  GENMASK(8, 5)
35 #define VCU_PLL_CFG_LFHF                GENMASK(12, 10)
36 #define VCU_PLL_CFG_LOCK_CNT            GENMASK(22, 13)
37 #define VCU_PLL_CFG_LOCK_DLY            GENMASK(31, 25)
38 #define VCU_ENC_CORE_CTRL               0x30
39 #define VCU_ENC_MCU_CTRL                0x34
40 #define VCU_DEC_CORE_CTRL               0x38
41 #define VCU_DEC_MCU_CTRL                0x3c
42 #define VCU_PLL_STATUS                  0x60
43 #define VCU_PLL_STATUS_LOCK_STATUS      BIT(0)
44
45 #define MHZ                             1000000
46 #define FVCO_MIN                        (1500U * MHZ)
47 #define FVCO_MAX                        (3000U * MHZ)
48
49 /**
50  * struct xvcu_device - Xilinx VCU init device structure
51  * @dev: Platform device
52  * @pll_ref: pll ref clock source
53  * @aclk: axi clock source
54  * @logicore_reg_ba: logicore reg base address
55  * @vcu_slcr_ba: vcu_slcr Register base address
56  * @pll: handle for the VCU PLL
57  * @pll_post: handle for the VCU PLL post divider
58  * @clk_data: clocks provided by the vcu clock provider
59  */
60 struct xvcu_device {
61         struct device *dev;
62         struct clk *pll_ref;
63         struct clk *aclk;
64         struct regmap *logicore_reg_ba;
65         void __iomem *vcu_slcr_ba;
66         struct clk_hw *pll;
67         struct clk_hw *pll_post;
68         struct clk_hw_onecell_data *clk_data;
69 };
70
71 static struct regmap_config vcu_settings_regmap_config = {
72         .name = "regmap",
73         .reg_bits = 32,
74         .val_bits = 32,
75         .reg_stride = 4,
76         .max_register = 0xfff,
77         .cache_type = REGCACHE_NONE,
78 };
79
80 /**
81  * struct xvcu_pll_cfg - Helper data
82  * @fbdiv: The integer portion of the feedback divider to the PLL
83  * @cp: PLL charge pump control
84  * @res: PLL loop filter resistor control
85  * @lfhf: PLL loop filter high frequency capacitor control
86  * @lock_dly: Lock circuit configuration settings for lock windowsize
87  * @lock_cnt: Lock circuit counter setting
88  */
89 struct xvcu_pll_cfg {
90         u32 fbdiv;
91         u32 cp;
92         u32 res;
93         u32 lfhf;
94         u32 lock_dly;
95         u32 lock_cnt;
96 };
97
98 static const struct xvcu_pll_cfg xvcu_pll_cfg[] = {
99         { 25, 3, 10, 3, 63, 1000 },
100         { 26, 3, 10, 3, 63, 1000 },
101         { 27, 4, 6, 3, 63, 1000 },
102         { 28, 4, 6, 3, 63, 1000 },
103         { 29, 4, 6, 3, 63, 1000 },
104         { 30, 4, 6, 3, 63, 1000 },
105         { 31, 6, 1, 3, 63, 1000 },
106         { 32, 6, 1, 3, 63, 1000 },
107         { 33, 4, 10, 3, 63, 1000 },
108         { 34, 5, 6, 3, 63, 1000 },
109         { 35, 5, 6, 3, 63, 1000 },
110         { 36, 5, 6, 3, 63, 1000 },
111         { 37, 5, 6, 3, 63, 1000 },
112         { 38, 5, 6, 3, 63, 975 },
113         { 39, 3, 12, 3, 63, 950 },
114         { 40, 3, 12, 3, 63, 925 },
115         { 41, 3, 12, 3, 63, 900 },
116         { 42, 3, 12, 3, 63, 875 },
117         { 43, 3, 12, 3, 63, 850 },
118         { 44, 3, 12, 3, 63, 850 },
119         { 45, 3, 12, 3, 63, 825 },
120         { 46, 3, 12, 3, 63, 800 },
121         { 47, 3, 12, 3, 63, 775 },
122         { 48, 3, 12, 3, 63, 775 },
123         { 49, 3, 12, 3, 63, 750 },
124         { 50, 3, 12, 3, 63, 750 },
125         { 51, 3, 2, 3, 63, 725 },
126         { 52, 3, 2, 3, 63, 700 },
127         { 53, 3, 2, 3, 63, 700 },
128         { 54, 3, 2, 3, 63, 675 },
129         { 55, 3, 2, 3, 63, 675 },
130         { 56, 3, 2, 3, 63, 650 },
131         { 57, 3, 2, 3, 63, 650 },
132         { 58, 3, 2, 3, 63, 625 },
133         { 59, 3, 2, 3, 63, 625 },
134         { 60, 3, 2, 3, 63, 625 },
135         { 61, 3, 2, 3, 63, 600 },
136         { 62, 3, 2, 3, 63, 600 },
137         { 63, 3, 2, 3, 63, 600 },
138         { 64, 3, 2, 3, 63, 600 },
139         { 65, 3, 2, 3, 63, 600 },
140         { 66, 3, 2, 3, 63, 600 },
141         { 67, 3, 2, 3, 63, 600 },
142         { 68, 3, 2, 3, 63, 600 },
143         { 69, 3, 2, 3, 63, 600 },
144         { 70, 3, 2, 3, 63, 600 },
145         { 71, 3, 2, 3, 63, 600 },
146         { 72, 3, 2, 3, 63, 600 },
147         { 73, 3, 2, 3, 63, 600 },
148         { 74, 3, 2, 3, 63, 600 },
149         { 75, 3, 2, 3, 63, 600 },
150         { 76, 3, 2, 3, 63, 600 },
151         { 77, 3, 2, 3, 63, 600 },
152         { 78, 3, 2, 3, 63, 600 },
153         { 79, 3, 2, 3, 63, 600 },
154         { 80, 3, 2, 3, 63, 600 },
155         { 81, 3, 2, 3, 63, 600 },
156         { 82, 3, 2, 3, 63, 600 },
157         { 83, 4, 2, 3, 63, 600 },
158         { 84, 4, 2, 3, 63, 600 },
159         { 85, 4, 2, 3, 63, 600 },
160         { 86, 4, 2, 3, 63, 600 },
161         { 87, 4, 2, 3, 63, 600 },
162         { 88, 4, 2, 3, 63, 600 },
163         { 89, 4, 2, 3, 63, 600 },
164         { 90, 4, 2, 3, 63, 600 },
165         { 91, 4, 2, 3, 63, 600 },
166         { 92, 4, 2, 3, 63, 600 },
167         { 93, 4, 2, 3, 63, 600 },
168         { 94, 4, 2, 3, 63, 600 },
169         { 95, 4, 2, 3, 63, 600 },
170         { 96, 4, 2, 3, 63, 600 },
171         { 97, 4, 2, 3, 63, 600 },
172         { 98, 4, 2, 3, 63, 600 },
173         { 99, 4, 2, 3, 63, 600 },
174         { 100, 4, 2, 3, 63, 600 },
175         { 101, 4, 2, 3, 63, 600 },
176         { 102, 4, 2, 3, 63, 600 },
177         { 103, 5, 2, 3, 63, 600 },
178         { 104, 5, 2, 3, 63, 600 },
179         { 105, 5, 2, 3, 63, 600 },
180         { 106, 5, 2, 3, 63, 600 },
181         { 107, 3, 4, 3, 63, 600 },
182         { 108, 3, 4, 3, 63, 600 },
183         { 109, 3, 4, 3, 63, 600 },
184         { 110, 3, 4, 3, 63, 600 },
185         { 111, 3, 4, 3, 63, 600 },
186         { 112, 3, 4, 3, 63, 600 },
187         { 113, 3, 4, 3, 63, 600 },
188         { 114, 3, 4, 3, 63, 600 },
189         { 115, 3, 4, 3, 63, 600 },
190         { 116, 3, 4, 3, 63, 600 },
191         { 117, 3, 4, 3, 63, 600 },
192         { 118, 3, 4, 3, 63, 600 },
193         { 119, 3, 4, 3, 63, 600 },
194         { 120, 3, 4, 3, 63, 600 },
195         { 121, 3, 4, 3, 63, 600 },
196         { 122, 3, 4, 3, 63, 600 },
197         { 123, 3, 4, 3, 63, 600 },
198         { 124, 3, 4, 3, 63, 600 },
199         { 125, 3, 4, 3, 63, 600 },
200 };
201
202 /**
203  * xvcu_read - Read from the VCU register space
204  * @iomem:      vcu reg space base address
205  * @offset:     vcu reg offset from base
206  *
207  * Return:      Returns 32bit value from VCU register specified
208  *
209  */
210 static inline u32 xvcu_read(void __iomem *iomem, u32 offset)
211 {
212         return ioread32(iomem + offset);
213 }
214
215 /**
216  * xvcu_write - Write to the VCU register space
217  * @iomem:      vcu reg space base address
218  * @offset:     vcu reg offset from base
219  * @value:      Value to write
220  */
221 static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value)
222 {
223         iowrite32(value, iomem + offset);
224 }
225
226 #define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw)
227
228 struct vcu_pll {
229         struct clk_hw hw;
230         void __iomem *reg_base;
231         unsigned long fvco_min;
232         unsigned long fvco_max;
233 };
234
235 static int xvcu_pll_wait_for_lock(struct vcu_pll *pll)
236 {
237         void __iomem *base = pll->reg_base;
238         unsigned long timeout;
239         u32 lock_status;
240
241         timeout = jiffies + msecs_to_jiffies(2000);
242         do {
243                 lock_status = xvcu_read(base, VCU_PLL_STATUS);
244                 if (lock_status & VCU_PLL_STATUS_LOCK_STATUS)
245                         return 0;
246         } while (!time_after(jiffies, timeout));
247
248         return -ETIMEDOUT;
249 }
250
251 static struct clk_hw *xvcu_register_pll_post(struct device *dev,
252                                              const char *name,
253                                              const struct clk_hw *parent_hw,
254                                              void __iomem *reg_base)
255 {
256         u32 div;
257         u32 vcu_pll_ctrl;
258
259         /*
260          * The output divider of the PLL must be set to 1/2 to meet the
261          * timing in the design.
262          */
263         vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL);
264         div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl);
265         if (div != 1)
266                 return ERR_PTR(-EINVAL);
267
268         return clk_hw_register_fixed_factor(dev, "vcu_pll_post",
269                                             clk_hw_get_name(parent_hw),
270                                             CLK_SET_RATE_PARENT, 1, 2);
271 }
272
273 static const struct xvcu_pll_cfg *xvcu_find_cfg(int div)
274 {
275         const struct xvcu_pll_cfg *cfg = NULL;
276         unsigned int i;
277
278         for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++)
279                 if (xvcu_pll_cfg[i].fbdiv == div)
280                         cfg = &xvcu_pll_cfg[i];
281
282         return cfg;
283 }
284
285 static int xvcu_pll_set_div(struct vcu_pll *pll, int div)
286 {
287         void __iomem *base = pll->reg_base;
288         const struct xvcu_pll_cfg *cfg = NULL;
289         u32 vcu_pll_ctrl;
290         u32 cfg_val;
291
292         cfg = xvcu_find_cfg(div);
293         if (!cfg)
294                 return -EINVAL;
295
296         vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
297         vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV;
298         vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv);
299         xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
300
301         cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) |
302                   FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) |
303                   FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) |
304                   FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) |
305                   FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly);
306         xvcu_write(base, VCU_PLL_CFG, cfg_val);
307
308         return 0;
309 }
310
311 static long xvcu_pll_round_rate(struct clk_hw *hw,
312                                 unsigned long rate, unsigned long *parent_rate)
313 {
314         struct vcu_pll *pll = to_vcu_pll(hw);
315         unsigned int feedback_div;
316
317         rate = clamp_t(unsigned long, rate, pll->fvco_min, pll->fvco_max);
318
319         feedback_div = DIV_ROUND_CLOSEST_ULL(rate, *parent_rate);
320         feedback_div = clamp_t(unsigned int, feedback_div, 25, 125);
321
322         return *parent_rate * feedback_div;
323 }
324
325 static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw,
326                                           unsigned long parent_rate)
327 {
328         struct vcu_pll *pll = to_vcu_pll(hw);
329         void __iomem *base = pll->reg_base;
330         unsigned int div;
331         u32 vcu_pll_ctrl;
332
333         vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
334         div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl);
335
336         return div * parent_rate;
337 }
338
339 static int xvcu_pll_set_rate(struct clk_hw *hw,
340                              unsigned long rate, unsigned long parent_rate)
341 {
342         struct vcu_pll *pll = to_vcu_pll(hw);
343
344         return xvcu_pll_set_div(pll, rate / parent_rate);
345 }
346
347 static int xvcu_pll_enable(struct clk_hw *hw)
348 {
349         struct vcu_pll *pll = to_vcu_pll(hw);
350         void __iomem *base = pll->reg_base;
351         u32 vcu_pll_ctrl;
352         int ret;
353
354         vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
355         vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS;
356         xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
357
358         vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
359         vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN;
360         vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR;
361         vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET;
362         xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
363
364         ret = xvcu_pll_wait_for_lock(pll);
365         if (ret) {
366                 pr_err("VCU PLL is not locked\n");
367                 goto err;
368         }
369
370         vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
371         vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS;
372         xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
373
374 err:
375         return ret;
376 }
377
378 static void xvcu_pll_disable(struct clk_hw *hw)
379 {
380         struct vcu_pll *pll = to_vcu_pll(hw);
381         void __iomem *base = pll->reg_base;
382         u32 vcu_pll_ctrl;
383
384         vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL);
385         vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN;
386         vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR;
387         vcu_pll_ctrl |= VCU_PLL_CTRL_RESET;
388         xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl);
389 }
390
391 static const struct clk_ops vcu_pll_ops = {
392         .enable = xvcu_pll_enable,
393         .disable = xvcu_pll_disable,
394         .round_rate = xvcu_pll_round_rate,
395         .recalc_rate = xvcu_pll_recalc_rate,
396         .set_rate = xvcu_pll_set_rate,
397 };
398
399 static struct clk_hw *xvcu_register_pll(struct device *dev,
400                                         void __iomem *reg_base,
401                                         const char *name, const char *parent,
402                                         unsigned long flags)
403 {
404         struct vcu_pll *pll;
405         struct clk_hw *hw;
406         struct clk_init_data init;
407         int ret;
408
409         init.name = name;
410         init.parent_names = &parent;
411         init.ops = &vcu_pll_ops;
412         init.num_parents = 1;
413         init.flags = flags;
414
415         pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL);
416         if (!pll)
417                 return ERR_PTR(-ENOMEM);
418
419         pll->hw.init = &init;
420         pll->reg_base = reg_base;
421         pll->fvco_min = FVCO_MIN;
422         pll->fvco_max = FVCO_MAX;
423
424         hw = &pll->hw;
425         ret = devm_clk_hw_register(dev, hw);
426         if (ret)
427                 return ERR_PTR(ret);
428
429         clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max);
430
431         return hw;
432 }
433
434 static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev,
435                                                 const char *name,
436                                                 const struct clk_parent_data *parent_data,
437                                                 u8 num_parents,
438                                                 void __iomem *reg)
439 {
440         u8 mux_flags = CLK_MUX_ROUND_CLOSEST;
441         u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO |
442                            CLK_DIVIDER_ROUND_CLOSEST;
443         struct clk_hw *mux = NULL;
444         struct clk_hw *divider = NULL;
445         struct clk_hw *gate = NULL;
446         char *name_mux;
447         char *name_div;
448         int err;
449         /* Protect register shared by clocks */
450         spinlock_t *lock;
451
452         lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL);
453         if (!lock)
454                 return ERR_PTR(-ENOMEM);
455         spin_lock_init(lock);
456
457         name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux");
458         if (!name_mux)
459                 return ERR_PTR(-ENOMEM);
460         mux = clk_hw_register_mux_parent_data(dev, name_mux,
461                                               parent_data, num_parents,
462                                               CLK_SET_RATE_PARENT,
463                                               reg, 0, 1, mux_flags, lock);
464         if (IS_ERR(mux))
465                 return mux;
466
467         name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div");
468         if (!name_div) {
469                 err = -ENOMEM;
470                 goto unregister_mux;
471         }
472         divider = clk_hw_register_divider_parent_hw(dev, name_div, mux,
473                                                     CLK_SET_RATE_PARENT,
474                                                     reg, 4, 6, divider_flags,
475                                                     lock);
476         if (IS_ERR(divider)) {
477                 err = PTR_ERR(divider);
478                 goto unregister_mux;
479         }
480
481         gate = clk_hw_register_gate_parent_hw(dev, name, divider,
482                                               CLK_SET_RATE_PARENT, reg, 12, 0,
483                                               lock);
484         if (IS_ERR(gate)) {
485                 err = PTR_ERR(gate);
486                 goto unregister_divider;
487         }
488
489         return gate;
490
491 unregister_divider:
492         clk_hw_unregister_divider(divider);
493 unregister_mux:
494         clk_hw_unregister_mux(mux);
495
496         return ERR_PTR(err);
497 }
498
499 static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw)
500 {
501         struct clk_hw *gate = hw;
502         struct clk_hw *divider;
503         struct clk_hw *mux;
504
505         if (!gate)
506                 return;
507
508         divider = clk_hw_get_parent(gate);
509         clk_hw_unregister_gate(gate);
510         if (!divider)
511                 return;
512
513         mux = clk_hw_get_parent(divider);
514         clk_hw_unregister_mux(mux);
515         if (!divider)
516                 return;
517
518         clk_hw_unregister_divider(divider);
519 }
520
521 static int xvcu_register_clock_provider(struct xvcu_device *xvcu)
522 {
523         struct device *dev = xvcu->dev;
524         struct clk_parent_data parent_data[2] = { 0 };
525         struct clk_hw_onecell_data *data;
526         struct clk_hw **hws;
527         struct clk_hw *hw;
528         void __iomem *reg_base = xvcu->vcu_slcr_ba;
529
530         data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL);
531         if (!data)
532                 return -ENOMEM;
533         data->num = CLK_XVCU_NUM_CLOCKS;
534         hws = data->hws;
535
536         xvcu->clk_data = data;
537
538         hw = xvcu_register_pll(dev, reg_base,
539                                "vcu_pll", __clk_get_name(xvcu->pll_ref),
540                                CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE);
541         if (IS_ERR(hw))
542                 return PTR_ERR(hw);
543         xvcu->pll = hw;
544
545         hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base);
546         if (IS_ERR(hw))
547                 return PTR_ERR(hw);
548         xvcu->pll_post = hw;
549
550         parent_data[0].fw_name = "pll_ref";
551         parent_data[1].hw = xvcu->pll_post;
552
553         hws[CLK_XVCU_ENC_CORE] =
554                 xvcu_clk_hw_register_leaf(dev, "venc_core_clk",
555                                           parent_data,
556                                           ARRAY_SIZE(parent_data),
557                                           reg_base + VCU_ENC_CORE_CTRL);
558         hws[CLK_XVCU_ENC_MCU] =
559                 xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk",
560                                           parent_data,
561                                           ARRAY_SIZE(parent_data),
562                                           reg_base + VCU_ENC_MCU_CTRL);
563         hws[CLK_XVCU_DEC_CORE] =
564                 xvcu_clk_hw_register_leaf(dev, "vdec_core_clk",
565                                           parent_data,
566                                           ARRAY_SIZE(parent_data),
567                                           reg_base + VCU_DEC_CORE_CTRL);
568         hws[CLK_XVCU_DEC_MCU] =
569                 xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk",
570                                           parent_data,
571                                           ARRAY_SIZE(parent_data),
572                                           reg_base + VCU_DEC_MCU_CTRL);
573
574         return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data);
575 }
576
577 static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu)
578 {
579         struct clk_hw_onecell_data *data = xvcu->clk_data;
580         struct clk_hw **hws = data->hws;
581
582         if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU]))
583                 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]);
584         if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE]))
585                 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]);
586         if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU]))
587                 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]);
588         if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE]))
589                 xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]);
590
591         clk_hw_unregister_fixed_factor(xvcu->pll_post);
592 }
593
594 /**
595  * xvcu_probe - Probe existence of the logicoreIP
596  *                      and initialize PLL
597  *
598  * @pdev:       Pointer to the platform_device structure
599  *
600  * Return:      Returns 0 on success
601  *              Negative error code otherwise
602  */
603 static int xvcu_probe(struct platform_device *pdev)
604 {
605         struct resource *res;
606         struct xvcu_device *xvcu;
607         void __iomem *regs;
608         int ret;
609
610         xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL);
611         if (!xvcu)
612                 return -ENOMEM;
613
614         xvcu->dev = &pdev->dev;
615         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr");
616         if (!res) {
617                 dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n");
618                 return -ENODEV;
619         }
620
621         xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start,
622                                          resource_size(res));
623         if (!xvcu->vcu_slcr_ba) {
624                 dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n");
625                 return -ENOMEM;
626         }
627
628         xvcu->logicore_reg_ba =
629                 syscon_regmap_lookup_by_compatible("xlnx,vcu-settings");
630         if (IS_ERR(xvcu->logicore_reg_ba)) {
631                 dev_info(&pdev->dev,
632                          "could not find xlnx,vcu-settings: trying direct register access\n");
633
634                 res = platform_get_resource_byname(pdev,
635                                                    IORESOURCE_MEM, "logicore");
636                 if (!res) {
637                         dev_err(&pdev->dev, "get logicore memory resource failed.\n");
638                         return -ENODEV;
639                 }
640
641                 regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
642                 if (!regs) {
643                         dev_err(&pdev->dev, "logicore register mapping failed.\n");
644                         return -ENOMEM;
645                 }
646
647                 xvcu->logicore_reg_ba =
648                         devm_regmap_init_mmio(&pdev->dev, regs,
649                                               &vcu_settings_regmap_config);
650                 if (IS_ERR(xvcu->logicore_reg_ba)) {
651                         dev_err(&pdev->dev, "failed to init regmap\n");
652                         return PTR_ERR(xvcu->logicore_reg_ba);
653                 }
654         }
655
656         xvcu->aclk = devm_clk_get(&pdev->dev, "aclk");
657         if (IS_ERR(xvcu->aclk)) {
658                 dev_err(&pdev->dev, "Could not get aclk clock\n");
659                 return PTR_ERR(xvcu->aclk);
660         }
661
662         xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
663         if (IS_ERR(xvcu->pll_ref)) {
664                 dev_err(&pdev->dev, "Could not get pll_ref clock\n");
665                 return PTR_ERR(xvcu->pll_ref);
666         }
667
668         ret = clk_prepare_enable(xvcu->aclk);
669         if (ret) {
670                 dev_err(&pdev->dev, "aclk clock enable failed\n");
671                 return ret;
672         }
673
674         /*
675          * Do the Gasket isolation and put the VCU out of reset
676          * Bit 0 : Gasket isolation
677          * Bit 1 : put VCU out of reset
678          */
679         regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE);
680
681         ret = xvcu_register_clock_provider(xvcu);
682         if (ret) {
683                 dev_err(&pdev->dev, "failed to register clock provider\n");
684                 goto error_clk_provider;
685         }
686
687         dev_set_drvdata(&pdev->dev, xvcu);
688
689         return 0;
690
691 error_clk_provider:
692         xvcu_unregister_clock_provider(xvcu);
693         clk_disable_unprepare(xvcu->aclk);
694         return ret;
695 }
696
697 /**
698  * xvcu_remove - Insert gasket isolation
699  *                      and disable the clock
700  * @pdev:       Pointer to the platform_device structure
701  *
702  * Return:      Returns 0 on success
703  *              Negative error code otherwise
704  */
705 static int xvcu_remove(struct platform_device *pdev)
706 {
707         struct xvcu_device *xvcu;
708
709         xvcu = platform_get_drvdata(pdev);
710         if (!xvcu)
711                 return -ENODEV;
712
713         xvcu_unregister_clock_provider(xvcu);
714
715         /* Add the Gasket isolation and put the VCU in reset. */
716         regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0);
717
718         clk_disable_unprepare(xvcu->aclk);
719
720         return 0;
721 }
722
723 static const struct of_device_id xvcu_of_id_table[] = {
724         { .compatible = "xlnx,vcu" },
725         { .compatible = "xlnx,vcu-logicoreip-1.0" },
726         { }
727 };
728 MODULE_DEVICE_TABLE(of, xvcu_of_id_table);
729
730 static struct platform_driver xvcu_driver = {
731         .driver = {
732                 .name           = "xilinx-vcu",
733                 .of_match_table = xvcu_of_id_table,
734         },
735         .probe                  = xvcu_probe,
736         .remove                 = xvcu_remove,
737 };
738
739 module_platform_driver(xvcu_driver);
740
741 MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>");
742 MODULE_DESCRIPTION("Xilinx VCU init Driver");
743 MODULE_LICENSE("GPL v2");