source: rtems-libbsd/freebsd/sys/arm/ti/ti_prcm.c @ bd3c01a

55-freebsd-126-freebsd-12
Last change on this file since bd3c01a was bd3c01a, checked in by Sichen Zhao <1473996754@…>, on 07/13/17 at 02:24:04

Import am335x usb driver file from FreeBSD.

  • Property mode set to 100644
File size: 10.0 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*
4 * Copyright (c) 2010
5 *      Ben Gray <ben.r.gray@gmail.com>.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *      This product includes software developed by Ben Gray.
19 * 4. The name of the company nor the name of the author may be used to
20 *    endorse or promote products derived from this software without specific
21 *    prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/**
36 * Power, Reset and Clock Management Module
37 *
38 * This is a very simple driver wrapper around the PRCM set of registers in
39 * the OMAP3 chip. It allows you to turn on and off things like the functional
40 * and interface clocks to the various on-chip modules.
41 *
42 */
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD$");
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/module.h>
50#include <sys/bus.h>
51#include <rtems/bsd/sys/resource.h>
52#include <sys/rman.h>
53#include <sys/lock.h>
54#include <sys/mutex.h>
55
56#include <machine/bus.h>
57#include <machine/resource.h>
58#include <machine/intr.h>
59
60#include <arm/ti/ti_cpuid.h>
61#include <arm/ti/ti_prcm.h>
62
63/**
64 *      ti_*_clk_devmap - Array of clock devices, should be defined one per SoC
65 *
66 *      This array is typically defined in one of the targeted *_prcm_clk.c
67 *      files and is specific to the given SoC platform.  Each entry in the array
68 *      corresponds to an individual clock device.
69 */
70extern struct ti_clock_dev ti_omap4_clk_devmap[];
71extern struct ti_clock_dev ti_am335x_clk_devmap[];
72
73/**
74 *      ti_prcm_clk_dev - returns a pointer to the clock device with given id
75 *      @clk: the ID of the clock device to get
76 *
77 *      Simply iterates through the clk_devmap global array and returns a pointer
78 *      to the clock device if found.
79 *
80 *      LOCKING:
81 *      None
82 *
83 *      RETURNS:
84 *      The pointer to the clock device on success, on failure NULL is returned.
85 */
86static struct ti_clock_dev *
87ti_prcm_clk_dev(clk_ident_t clk)
88{
89        struct ti_clock_dev *clk_dev;
90       
91        /* Find the clock within the devmap - it's a bit inefficent having a for
92         * loop for this, but this function should only called when a driver is
93         * being activated so IMHO not a big issue.
94         */
95        clk_dev = NULL;
96        switch(ti_chip()) {
97#ifdef SOC_OMAP4
98        case CHIP_OMAP_4:
99                clk_dev = &(ti_omap4_clk_devmap[0]);
100                break;
101#endif
102#ifdef SOC_TI_AM335X
103        case CHIP_AM335X:
104                clk_dev = &(ti_am335x_clk_devmap[0]);
105                break;
106#endif
107        }
108        if (clk_dev == NULL)
109                panic("No clock devmap found");
110        while (clk_dev->id != INVALID_CLK_IDENT) {
111                if (clk_dev->id == clk) {
112                        return (clk_dev);
113                }
114                clk_dev++;
115        }
116
117        /* Sanity check we managed to find the clock */
118        printf("ti_prcm: Failed to find clock device (%d)\n", clk);
119        return (NULL);
120}
121
122/**
123 *      ti_prcm_clk_valid - enables a clock for a particular module
124 *      @clk: identifier for the module to enable, see ti_prcm.h for a list
125 *            of possible modules.
126 *               Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
127 *     
128 *      This function can enable either a functional or interface clock.
129 *
130 *      The real work done to enable the clock is really done in the callback
131 *      function associated with the clock, this function is simply a wrapper
132 *      around that.
133 *
134 *      LOCKING:
135 *      Internally locks the driver context.
136 *
137 *      RETURNS:
138 *      Returns 0 on success or positive error code on failure.
139 */
140int
141ti_prcm_clk_valid(clk_ident_t clk)
142{
143        int ret = 0;
144
145        if (ti_prcm_clk_dev(clk) == NULL)
146                ret = EINVAL;
147       
148        return (ret);
149}
150
151
152/**
153 *      ti_prcm_clk_enable - enables a clock for a particular module
154 *      @clk: identifier for the module to enable, see ti_prcm.h for a list
155 *            of possible modules.
156 *               Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
157 *     
158 *      This function can enable either a functional or interface clock.
159 *
160 *      The real work done to enable the clock is really done in the callback
161 *      function associated with the clock, this function is simply a wrapper
162 *      around that.
163 *
164 *      LOCKING:
165 *      Internally locks the driver context.
166 *
167 *      RETURNS:
168 *      Returns 0 on success or positive error code on failure.
169 */
170int
171ti_prcm_clk_enable(clk_ident_t clk)
172{
173        struct ti_clock_dev *clk_dev;
174        int ret;
175
176        /* Find the clock within the devmap - it's a bit inefficent having a for
177         * loop for this, but this function should only called when a driver is
178         * being activated so IMHO not a big issue.
179         */
180        clk_dev = ti_prcm_clk_dev(clk);
181
182        /* Sanity check we managed to find the clock */
183        if (clk_dev == NULL)
184                return (EINVAL);
185
186        /* Activate the clock */
187        if (clk_dev->clk_activate)
188                ret = clk_dev->clk_activate(clk_dev);
189        else
190                ret = EINVAL;
191
192        return (ret);
193}
194
195
196/**
197 *      ti_prcm_clk_disable - disables a clock for a particular module
198 *      @clk: identifier for the module to enable, see ti_prcm.h for a list
199 *            of possible modules.
200 *               Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
201 *     
202 *      This function can enable either a functional or interface clock.
203 *
204 *      The real work done to enable the clock is really done in the callback
205 *      function associated with the clock, this function is simply a wrapper
206 *      around that.
207 *
208 *      LOCKING:
209 *      Internally locks the driver context.
210 *
211 *      RETURNS:
212 *      Returns 0 on success or positive error code on failure.
213 */
214int
215ti_prcm_clk_disable(clk_ident_t clk)
216{
217        struct ti_clock_dev *clk_dev;
218        int ret;
219
220        /* Find the clock within the devmap - it's a bit inefficent having a for
221         * loop for this, but this function should only called when a driver is
222         * being activated so IMHO not a big issue.
223         */
224        clk_dev = ti_prcm_clk_dev(clk);
225
226        /* Sanity check we managed to find the clock */
227        if (clk_dev == NULL)
228                return (EINVAL);
229
230        /* Activate the clock */
231        if (clk_dev->clk_deactivate)
232                ret = clk_dev->clk_deactivate(clk_dev);
233        else
234                ret = EINVAL;
235       
236        return (ret);
237}
238
239/**
240 *      ti_prcm_clk_set_source - sets the source
241 *      @clk: identifier for the module to enable, see ti_prcm.h for a list
242 *            of possible modules.
243 *               Example: OMAP3_MODULE_MMC1_ICLK or OMAP3_MODULE_GPTIMER10_FCLK.
244 *     
245 *      This function can enable either a functional or interface clock.
246 *
247 *      The real work done to enable the clock is really done in the callback
248 *      function associated with the clock, this function is simply a wrapper
249 *      around that.
250 *
251 *      LOCKING:
252 *      Internally locks the driver context.
253 *
254 *      RETURNS:
255 *      Returns 0 on success or positive error code on failure.
256 */
257int
258ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc)
259{
260        struct ti_clock_dev *clk_dev;
261        int ret;
262
263        /* Find the clock within the devmap - it's a bit inefficent having a for
264         * loop for this, but this function should only called when a driver is
265         * being activated so IMHO not a big issue.
266         */
267        clk_dev = ti_prcm_clk_dev(clk);
268
269        /* Sanity check we managed to find the clock */
270        if (clk_dev == NULL)
271                return (EINVAL);
272
273        /* Activate the clock */
274        if (clk_dev->clk_set_source)
275                ret = clk_dev->clk_set_source(clk_dev, clksrc);
276        else
277                ret = EINVAL;
278
279        return (ret);
280}
281
282
283/**
284 *      ti_prcm_clk_get_source_freq - gets the source clock frequency
285 *      @clk: identifier for the module to enable, see ti_prcm.h for a list
286 *            of possible modules.
287 *      @freq: pointer to an integer that upon return will contain the src freq
288 *
289 *      This function returns the frequency of the source clock.
290 *
291 *      The real work done to enable the clock is really done in the callback
292 *      function associated with the clock, this function is simply a wrapper
293 *      around that.
294 *
295 *      LOCKING:
296 *      Internally locks the driver context.
297 *
298 *      RETURNS:
299 *      Returns 0 on success or positive error code on failure.
300 */
301int
302ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq)
303{
304        struct ti_clock_dev *clk_dev;
305        int ret;
306
307        /* Find the clock within the devmap - it's a bit inefficent having a for
308         * loop for this, but this function should only called when a driver is
309         * being activated so IMHO not a big issue.
310         */
311        clk_dev = ti_prcm_clk_dev(clk);
312
313        /* Sanity check we managed to find the clock */
314        if (clk_dev == NULL)
315                return (EINVAL);
316
317        /* Get the source frequency of the clock */
318        if (clk_dev->clk_get_source_freq)
319                ret = clk_dev->clk_get_source_freq(clk_dev, freq);
320        else
321                ret = EINVAL;
322
323        return (ret);
324}
325
326/**
327 *      ti_prcm_clk_set_source_freq - sets the source clock frequency as close to freq as possible
328 *      @clk: identifier for the module to enable, see ti_prcm.h for a list
329 *            of possible modules.
330 *      @freq: requested freq
331 *
332 *      LOCKING:
333 *      Internally locks the driver context.
334 *
335 *      RETURNS:
336 *      Returns 0 on success or positive error code on failure.
337 */
338int
339ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq)
340{
341        struct ti_clock_dev *clk_dev;
342        int ret;
343
344        clk_dev = ti_prcm_clk_dev(clk);
345
346        /* Sanity check we managed to find the clock */
347        if (clk_dev == NULL)
348                return (EINVAL);
349
350        /* Get the source frequency of the clock */
351        if (clk_dev->clk_set_source_freq)
352                ret = clk_dev->clk_set_source_freq(clk_dev, freq);
353        else
354                ret = EINVAL;
355
356        return (ret);
357}
Note: See TracBrowser for help on using the repository browser.