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