]> Git Repo - u-boot.git/blame - drivers/clk/clk_vexpress_osc.c
arm64: configs: Remove SYS_BOOTM_LEN for TI devices
[u-boot.git] / drivers / clk / clk_vexpress_osc.c
CommitLineData
a71e907c
LD
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Arm Ltd
4 * Author: Liviu Dudau <[email protected]>
5 *
6 */
7#define DEBUG
a71e907c
LD
8#include <clk-uclass.h>
9#include <dm.h>
f7ae49fc 10#include <log.h>
336d4615 11#include <dm/device_compat.h>
a71e907c
LD
12#include <dm/lists.h>
13#include <errno.h>
14#include <misc.h>
cd93d625 15#include <linux/bitops.h>
a71e907c
LD
16
17#define CLK_FUNCTION BIT(20)
18
19struct vexpress_osc_clk_priv {
20 u8 osc;
21 ulong rate_min;
22 ulong rate_max;
23};
24
25static ulong vexpress_osc_clk_get_rate(struct clk *clk)
26{
27 int err;
28 u32 data;
29 struct udevice *vexpress_cfg = dev_get_parent(clk->dev);
30 struct vexpress_osc_clk_priv *priv = dev_get_priv(clk->dev);
31
32 data = CLK_FUNCTION | priv->osc;
33 err = misc_read(vexpress_cfg, 0, &data, sizeof(data));
8729b1ae 34 if (err < 0)
a71e907c
LD
35 return err;
36
37 return data;
38}
39
371dc068 40#ifndef CONFIG_XPL_BUILD
a71e907c
LD
41static ulong vexpress_osc_clk_set_rate(struct clk *clk, ulong rate)
42{
43 int err;
44 u32 buffer[2];
45 struct udevice *vexpress_cfg = dev_get_parent(clk->dev);
46 struct vexpress_osc_clk_priv *priv = dev_get_priv(clk->dev);
47
48 if (rate < priv->rate_min || rate > priv->rate_max)
49 return -EINVAL;
50
51 /*
52 * we are sending the parent the info about the oscillator
53 * and the value we want to set
54 */
55 buffer[0] = CLK_FUNCTION | priv->osc;
56 buffer[1] = rate;
57 err = misc_write(vexpress_cfg, 0, buffer, 2 * sizeof(u32));
8729b1ae 58 if (err < 0)
a71e907c
LD
59 return err;
60
61 return rate;
62}
63#endif
64
65static struct clk_ops vexpress_osc_clk_ops = {
66 .get_rate = vexpress_osc_clk_get_rate,
371dc068 67#ifndef CONFIG_XPL_BUILD
a71e907c
LD
68 .set_rate = vexpress_osc_clk_set_rate,
69#endif
70};
71
72static int vexpress_osc_clk_probe(struct udevice *dev)
73{
74 struct vexpress_osc_clk_priv *priv = dev_get_priv(dev);
75 u32 values[2];
76 int err;
77
78 err = dev_read_u32_array(dev, "freq-range", values, 2);
79 if (err)
80 return err;
81 priv->rate_min = values[0];
82 priv->rate_max = values[1];
83
84 err = dev_read_u32_array(dev, "arm,vexpress-sysreg,func", values, 2);
85 if (err)
86 return err;
87
88 if (values[0] != 1) {
89 dev_err(dev, "Invalid VExpress function for clock, must be '1'");
90 return -EINVAL;
91 }
92 priv->osc = values[1];
93 debug("clk \"%s%d\", min freq %luHz, max freq %luHz\n", dev->name,
94 priv->osc, priv->rate_min, priv->rate_max);
95
96 return 0;
97}
98
99static const struct udevice_id vexpress_osc_clk_ids[] = {
100 { .compatible = "arm,vexpress-osc", },
101 {}
102};
103
104U_BOOT_DRIVER(vexpress_osc_clk) = {
105 .name = "vexpress_osc_clk",
106 .id = UCLASS_CLK,
107 .of_match = vexpress_osc_clk_ids,
108 .ops = &vexpress_osc_clk_ops,
41575d8e 109 .priv_auto = sizeof(struct vexpress_osc_clk_priv),
a71e907c
LD
110 .probe = vexpress_osc_clk_probe,
111};
This page took 0.124916 seconds and 4 git commands to generate.