blob: 9fcf30fd2e48b0265a5ff651f5e2da4e77673474 [file] [log] [blame]
Lukasz Majewski1d7993d2019-06-24 15:50:45 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 DENX Software Engineering
4 * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
5 *
6 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
7 */
8#include <common.h>
Patrick Delaunay572c4462021-11-19 15:12:06 +01009#include <clk.h>
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020010#include <clk-uclass.h>
Patrick Delaunay572c4462021-11-19 15:12:06 +010011#include <div64.h>
12#include <malloc.h>
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020013#include <dm/device.h>
Simon Glass61b29b82020-02-03 07:36:15 -070014#include <dm/devres.h>
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020015#include <linux/clk-provider.h>
Simon Glass61b29b82020-02-03 07:36:15 -070016#include <linux/err.h>
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020017
Patrick Delaunay572c4462021-11-19 15:12:06 +010018#include "clk.h"
19
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020020#define UBOOT_DM_CLK_IMX_FIXED_FACTOR "ccf_clk_fixed_factor"
21
22static ulong clk_factor_recalc_rate(struct clk *clk)
23{
Sean Anderson78ce0bd2020-06-24 06:41:06 -040024 struct clk_fixed_factor *fix = to_clk_fixed_factor(clk);
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020025 unsigned long parent_rate = clk_get_parent_rate(clk);
26 unsigned long long int rate;
27
28 rate = (unsigned long long int)parent_rate * fix->mult;
29 do_div(rate, fix->div);
30 return (ulong)rate;
31}
32
33const struct clk_ops ccf_clk_fixed_factor_ops = {
34 .get_rate = clk_factor_recalc_rate,
35};
36
37struct clk *clk_hw_register_fixed_factor(struct device *dev,
38 const char *name, const char *parent_name, unsigned long flags,
39 unsigned int mult, unsigned int div)
40{
41 struct clk_fixed_factor *fix;
42 struct clk *clk;
43 int ret;
44
45 fix = kzalloc(sizeof(*fix), GFP_KERNEL);
46 if (!fix)
47 return ERR_PTR(-ENOMEM);
48
49 /* struct clk_fixed_factor assignments */
50 fix->mult = mult;
51 fix->div = div;
52 clk = &fix->clk;
Dario Binacchi16bdc852020-04-13 14:36:27 +020053 clk->flags = flags;
Lukasz Majewski1d7993d2019-06-24 15:50:45 +020054
55 ret = clk_register(clk, UBOOT_DM_CLK_IMX_FIXED_FACTOR, name,
56 parent_name);
57 if (ret) {
58 kfree(fix);
59 return ERR_PTR(ret);
60 }
61
62 return clk;
63}
64
65struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
66 const char *parent_name, unsigned long flags,
67 unsigned int mult, unsigned int div)
68{
69 struct clk *clk;
70
71 clk = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult,
72 div);
73 if (IS_ERR(clk))
74 return ERR_CAST(clk);
75 return clk;
76}
77
78U_BOOT_DRIVER(imx_clk_fixed_factor) = {
79 .name = UBOOT_DM_CLK_IMX_FIXED_FACTOR,
80 .id = UCLASS_CLK,
81 .ops = &ccf_clk_fixed_factor_ops,
82 .flags = DM_FLAG_PRE_RELOC,
83};