blob: 5f9f0a0d0b7b675b5679ca1bbd74e2bb984b774b [file] [log] [blame]
Dario Binacchid1cb3f62020-12-30 00:06:29 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments sysc interconnect target driver
4 *
5 * Copyright (C) 2020 Dario Binacchi <dariobin@libero.it>
6 */
7
Dario Binacchid1cb3f62020-12-30 00:06:29 +01008#include <clk.h>
9#include <dm.h>
10#include <dm/device_compat.h>
11
12enum ti_sysc_clocks {
13 TI_SYSC_FCK,
14 TI_SYSC_ICK,
15 TI_SYSC_MAX_CLOCKS,
16};
17
18static const char *const clock_names[] = {"fck", "ick"};
19
20struct ti_sysc_priv {
21 int clocks_count;
22 struct clk clocks[TI_SYSC_MAX_CLOCKS];
23};
24
25static const struct udevice_id ti_sysc_ids[] = {
26 {.compatible = "ti,sysc-omap2"},
27 {.compatible = "ti,sysc-omap4"},
28 {.compatible = "ti,sysc-omap4-simple"},
29 {.compatible = "ti,sysc-omap3430-sr"},
30 {.compatible = "ti,sysc-omap3630-sr"},
31 {.compatible = "ti,sysc-omap4-sr"},
32 {.compatible = "ti,sysc-omap3-sham"},
33 {.compatible = "ti,sysc-omap-aes"},
34 {.compatible = "ti,sysc-mcasp"},
35 {.compatible = "ti,sysc-usb-host-fs"},
36 {}
37};
38
39static int ti_sysc_get_one_clock(struct udevice *dev, enum ti_sysc_clocks index)
40{
41 struct ti_sysc_priv *priv = dev_get_priv(dev);
42 const char *name;
43 int err;
44
45 switch (index) {
46 case TI_SYSC_FCK:
47 break;
48 case TI_SYSC_ICK:
49 break;
50 default:
51 return -EINVAL;
52 }
53
54 name = clock_names[index];
55
56 err = clk_get_by_name(dev, name, &priv->clocks[index]);
57 if (err) {
58 if (err == -ENODATA)
59 return 0;
60
61 dev_err(dev, "failed to get %s clock\n", name);
62 return err;
63 }
64
65 return 0;
66}
67
68static int ti_sysc_put_clocks(struct udevice *dev)
69{
70 struct ti_sysc_priv *priv = dev_get_priv(dev);
71 int err;
72
73 err = clk_release_all(priv->clocks, priv->clocks_count);
74 if (err)
75 dev_err(dev, "failed to release all clocks\n");
76
77 return err;
78}
79
80static int ti_sysc_get_clocks(struct udevice *dev)
81{
82 struct ti_sysc_priv *priv = dev_get_priv(dev);
83 int i, err;
84
85 for (i = 0; i < TI_SYSC_MAX_CLOCKS; i++) {
86 err = ti_sysc_get_one_clock(dev, i);
87 if (!err)
88 priv->clocks_count++;
89 else if (err != -ENOENT)
90 return err;
91 }
92
93 return 0;
94}
95
96static int ti_sysc_child_post_remove(struct udevice *dev)
97{
98 struct ti_sysc_priv *priv = dev_get_priv(dev->parent);
99 int i, err;
100
101 for (i = 0; i < priv->clocks_count; i++) {
102 err = clk_disable(&priv->clocks[i]);
103 if (err) {
104 dev_err(dev->parent, "failed to disable %s clock\n",
105 clock_names[i]);
106 return err;
107 }
108 }
109
110 return 0;
111}
112
113static int ti_sysc_child_pre_probe(struct udevice *dev)
114{
115 struct ti_sysc_priv *priv = dev_get_priv(dev->parent);
116 int i, err;
117
118 for (i = 0; i < priv->clocks_count; i++) {
119 err = clk_enable(&priv->clocks[i]);
120 if (err) {
121 dev_err(dev->parent, "failed to enable %s clock\n",
122 clock_names[i]);
123 return err;
124 }
125 }
126
127 return 0;
128}
129
130static int ti_sysc_remove(struct udevice *dev)
131{
132 return ti_sysc_put_clocks(dev);
133}
134
135static int ti_sysc_probe(struct udevice *dev)
136{
137 int err;
138
139 err = ti_sysc_get_clocks(dev);
140 if (err)
141 goto clocks_err;
142
143 return 0;
144
145clocks_err:
146 ti_sysc_put_clocks(dev);
147 return err;
148}
149
Dario Binacchid1cb3f62020-12-30 00:06:29 +0100150U_BOOT_DRIVER(ti_sysc) = {
151 .name = "ti_sysc",
152 .id = UCLASS_SIMPLE_BUS,
153 .of_match = ti_sysc_ids,
154 .probe = ti_sysc_probe,
155 .remove = ti_sysc_remove,
156 .child_pre_probe = ti_sysc_child_pre_probe,
157 .child_post_remove = ti_sysc_child_post_remove,
158 .priv_auto = sizeof(struct ti_sysc_priv)
159};