1e53470feSOleksandr Tymoshenko /*-
2af3dc4a7SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
3af3dc4a7SPedro F. Giffuni *
4e53470feSOleksandr Tymoshenko * Copyright (c) 2011
5e53470feSOleksandr Tymoshenko * Ben Gray <ben.r.gray@gmail.com>.
6e53470feSOleksandr Tymoshenko * All rights reserved.
7e53470feSOleksandr Tymoshenko *
8e53470feSOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without
9e53470feSOleksandr Tymoshenko * modification, are permitted provided that the following conditions
10e53470feSOleksandr Tymoshenko * are met:
11e53470feSOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright
12e53470feSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer.
13e53470feSOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright
14e53470feSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the
15e53470feSOleksandr Tymoshenko * documentation and/or other materials provided with the distribution.
16e53470feSOleksandr Tymoshenko * 3. The name of the company nor the name of the author may be used to
17e53470feSOleksandr Tymoshenko * endorse or promote products derived from this software without specific
18e53470feSOleksandr Tymoshenko * prior written permission.
19e53470feSOleksandr Tymoshenko *
20e53470feSOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
21e53470feSOleksandr Tymoshenko * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22e53470feSOleksandr Tymoshenko * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23e53470feSOleksandr Tymoshenko * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24e53470feSOleksandr Tymoshenko * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25e53470feSOleksandr Tymoshenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26e53470feSOleksandr Tymoshenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27e53470feSOleksandr Tymoshenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28e53470feSOleksandr Tymoshenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29e53470feSOleksandr Tymoshenko * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30e53470feSOleksandr Tymoshenko */
31e53470feSOleksandr Tymoshenko
32e53470feSOleksandr Tymoshenko #include <sys/param.h>
33e53470feSOleksandr Tymoshenko #include <sys/systm.h>
34e53470feSOleksandr Tymoshenko #include <sys/kernel.h>
35e53470feSOleksandr Tymoshenko #include <sys/module.h>
36e53470feSOleksandr Tymoshenko #include <sys/bus.h>
37e53470feSOleksandr Tymoshenko #include <sys/resource.h>
38e53470feSOleksandr Tymoshenko #include <sys/rman.h>
39e53470feSOleksandr Tymoshenko #include <sys/lock.h>
40e53470feSOleksandr Tymoshenko #include <sys/malloc.h>
41e53470feSOleksandr Tymoshenko
42e53470feSOleksandr Tymoshenko #include <machine/bus.h>
43e53470feSOleksandr Tymoshenko #include <machine/resource.h>
44e53470feSOleksandr Tymoshenko #include <machine/intr.h>
45e53470feSOleksandr Tymoshenko
46b24b2743SIan Lepore #include <arm/arm/mpcore_timervar.h>
47e53470feSOleksandr Tymoshenko #include <arm/ti/tivar.h>
48e53470feSOleksandr Tymoshenko #include <arm/ti/ti_prcm.h>
49e53470feSOleksandr Tymoshenko #include <arm/ti/omap4/omap4_reg.h>
50e53470feSOleksandr Tymoshenko
51e53470feSOleksandr Tymoshenko #include <dev/ofw/openfirm.h>
52e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h>
53e53470feSOleksandr Tymoshenko #include <dev/ofw/ofw_bus_subr.h>
54e53470feSOleksandr Tymoshenko
55e53470feSOleksandr Tymoshenko /*
56e53470feSOleksandr Tymoshenko * This file defines the clock configuration for the OMAP4xxx series of
57e53470feSOleksandr Tymoshenko * devices.
58e53470feSOleksandr Tymoshenko *
59e53470feSOleksandr Tymoshenko * How This is Suppose to Work
60e53470feSOleksandr Tymoshenko * ===========================
61e53470feSOleksandr Tymoshenko * - There is a top level omap_prcm module that defines all OMAP SoC drivers
62e53470feSOleksandr Tymoshenko * should use to enable/disable the system clocks regardless of the version
63e53470feSOleksandr Tymoshenko * of OMAP device they are running on. This top level PRCM module is just
64e53470feSOleksandr Tymoshenko * a thin shim to chip specific functions that perform the donkey work of
65e53470feSOleksandr Tymoshenko * configuring the clock - this file is the 'donkey' for OMAP44xx devices.
66e53470feSOleksandr Tymoshenko *
67e53470feSOleksandr Tymoshenko * - The key bit in this file is the omap_clk_devmap array, it's
68e53470feSOleksandr Tymoshenko * used by the omap_prcm driver to determine what clocks are valid and which
69e53470feSOleksandr Tymoshenko * functions to call to manipulate them.
70e53470feSOleksandr Tymoshenko *
71e53470feSOleksandr Tymoshenko * - In essence you just need to define some callbacks for each of the
72e53470feSOleksandr Tymoshenko * clocks and then you're done.
73e53470feSOleksandr Tymoshenko *
74e53470feSOleksandr Tymoshenko * - The other thing that is worth noting is that when the omap_prcm device
75e53470feSOleksandr Tymoshenko * is registered you typically pass in some memory ranges which are the
76e53470feSOleksandr Tymoshenko * SYS_MEMORY resources. These resources are in turn allocated using
77e53470feSOleksandr Tymoshenko * bus_allocate_resources(...) and the resource handles are passed to all
78e53470feSOleksandr Tymoshenko * individual clock callback handlers.
79e53470feSOleksandr Tymoshenko *
80e53470feSOleksandr Tymoshenko *
81e53470feSOleksandr Tymoshenko *
82e53470feSOleksandr Tymoshenko * OMAP4 devices are different from the previous OMAP3 devices in that there
83e53470feSOleksandr Tymoshenko * is no longer a separate functional and interface clock for each module,
84e53470feSOleksandr Tymoshenko * instead there is typically an interface clock that spans many modules.
85e53470feSOleksandr Tymoshenko */
86e53470feSOleksandr Tymoshenko
87e53470feSOleksandr Tymoshenko #define FREQ_96MHZ 96000000
88e53470feSOleksandr Tymoshenko #define FREQ_64MHZ 64000000
89e53470feSOleksandr Tymoshenko #define FREQ_48MHZ 48000000
90e53470feSOleksandr Tymoshenko #define FREQ_32KHZ 32000
91e53470feSOleksandr Tymoshenko
925b03aba6SOleksandr Tymoshenko #define PRM_INSTANCE 1
935b03aba6SOleksandr Tymoshenko #define CM1_INSTANCE 2
945b03aba6SOleksandr Tymoshenko #define CM2_INSTANCE 3
95e53470feSOleksandr Tymoshenko
96e53470feSOleksandr Tymoshenko /**
97e53470feSOleksandr Tymoshenko * Address offsets from the PRM memory region to the top level clock control
98e53470feSOleksandr Tymoshenko * registers.
99e53470feSOleksandr Tymoshenko */
100e53470feSOleksandr Tymoshenko #define CKGEN_PRM_OFFSET 0x00000100UL
101e53470feSOleksandr Tymoshenko #define MPU_PRM_OFFSET 0x00000300UL
102e53470feSOleksandr Tymoshenko #define DSP_PRM_OFFSET 0x00000400UL
103e53470feSOleksandr Tymoshenko #define ABE_PRM_OFFSET 0x00000500UL
104e53470feSOleksandr Tymoshenko #define ALWAYS_ON_PRM_OFFSET 0x00000600UL
105e53470feSOleksandr Tymoshenko #define CORE_PRM_OFFSET 0x00000700UL
106e53470feSOleksandr Tymoshenko #define IVAHD_PRM_OFFSET 0x00000F00UL
107e53470feSOleksandr Tymoshenko #define CAM_PRM_OFFSET 0x00001000UL
108e53470feSOleksandr Tymoshenko #define DSS_PRM_OFFSET 0x00001100UL
109e53470feSOleksandr Tymoshenko #define SGX_PRM_OFFSET 0x00001200UL
110e53470feSOleksandr Tymoshenko #define L3INIT_PRM_OFFSET 0x00001300UL
111e53470feSOleksandr Tymoshenko #define L4PER_PRM_OFFSET 0x00001400UL
112e53470feSOleksandr Tymoshenko #define WKUP_PRM_OFFSET 0x00001700UL
113e53470feSOleksandr Tymoshenko #define WKUP_CM_OFFSET 0x00001800UL
114e53470feSOleksandr Tymoshenko #define EMU_PRM_OFFSET 0x00001900UL
115e53470feSOleksandr Tymoshenko #define EMU_CM_OFFSET 0x00001A00UL
116e53470feSOleksandr Tymoshenko #define DEVICE_PRM_OFFSET 0x00001B00UL
117e53470feSOleksandr Tymoshenko #define INSTR_PRM_OFFSET 0x00001F00UL
118e53470feSOleksandr Tymoshenko
119e53470feSOleksandr Tymoshenko #define CM_ABE_DSS_SYS_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x0000UL)
120e53470feSOleksandr Tymoshenko #define CM_L4_WKUP_CLKSELL_OFFSET (CKGEN_PRM_OFFSET + 0x0008UL)
121e53470feSOleksandr Tymoshenko #define CM_ABE_PLL_REF_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x000CUL)
122e53470feSOleksandr Tymoshenko #define CM_SYS_CLKSEL_OFFSET (CKGEN_PRM_OFFSET + 0x0010UL)
123e53470feSOleksandr Tymoshenko
124e53470feSOleksandr Tymoshenko /**
125e53470feSOleksandr Tymoshenko * Address offsets from the CM1 memory region to the top level clock control
126e53470feSOleksandr Tymoshenko * registers.
127e53470feSOleksandr Tymoshenko */
128e53470feSOleksandr Tymoshenko #define CKGEN_CM1_OFFSET 0x00000100UL
129e53470feSOleksandr Tymoshenko #define MPU_CM1_OFFSET 0x00000300UL
130e53470feSOleksandr Tymoshenko #define DSP_CM1_OFFSET 0x00000400UL
131e53470feSOleksandr Tymoshenko #define ABE_CM1_OFFSET 0x00000500UL
132e53470feSOleksandr Tymoshenko #define RESTORE_CM1_OFFSET 0x00000E00UL
133e53470feSOleksandr Tymoshenko #define INSTR_CM1_OFFSET 0x00000F00UL
134e53470feSOleksandr Tymoshenko
135e53470feSOleksandr Tymoshenko #define CM_CLKSEL_DPLL_MPU (CKGEN_CM1_OFFSET + 0x006CUL)
136e53470feSOleksandr Tymoshenko
137e53470feSOleksandr Tymoshenko /**
138e53470feSOleksandr Tymoshenko * Address offsets from the CM2 memory region to the top level clock control
139e53470feSOleksandr Tymoshenko * registers.
140e53470feSOleksandr Tymoshenko */
141e53470feSOleksandr Tymoshenko #define INTRCONN_SOCKET_CM2_OFFSET 0x00000000UL
142e53470feSOleksandr Tymoshenko #define CKGEN_CM2_OFFSET 0x00000100UL
143e53470feSOleksandr Tymoshenko #define ALWAYS_ON_CM2_OFFSET 0x00000600UL
144e53470feSOleksandr Tymoshenko #define CORE_CM2_OFFSET 0x00000700UL
145e53470feSOleksandr Tymoshenko #define IVAHD_CM2_OFFSET 0x00000F00UL
146e53470feSOleksandr Tymoshenko #define CAM_CM2_OFFSET 0x00001000UL
147e53470feSOleksandr Tymoshenko #define DSS_CM2_OFFSET 0x00001100UL
148e53470feSOleksandr Tymoshenko #define SGX_CM2_OFFSET 0x00001200UL
149e53470feSOleksandr Tymoshenko #define L3INIT_CM2_OFFSET 0x00001300UL
150e53470feSOleksandr Tymoshenko #define L4PER_CM2_OFFSET 0x00001400UL
151e53470feSOleksandr Tymoshenko #define RESTORE_CM2_OFFSET 0x00001E00UL
152e53470feSOleksandr Tymoshenko #define INSTR_CM2_OFFSET 0x00001F00UL
153e53470feSOleksandr Tymoshenko
154e53470feSOleksandr Tymoshenko #define CLKCTRL_MODULEMODE_MASK 0x00000003UL
155e53470feSOleksandr Tymoshenko #define CLKCTRL_MODULEMODE_DISABLE 0x00000000UL
156e53470feSOleksandr Tymoshenko #define CLKCTRL_MODULEMODE_AUTO 0x00000001UL
157e53470feSOleksandr Tymoshenko #define CLKCTRL_MODULEMODE_ENABLE 0x00000001UL
158e53470feSOleksandr Tymoshenko
159e53470feSOleksandr Tymoshenko #define CLKCTRL_IDLEST_MASK 0x00030000UL
160e53470feSOleksandr Tymoshenko #define CLKCTRL_IDLEST_ENABLED 0x00000000UL
161e53470feSOleksandr Tymoshenko #define CLKCTRL_IDLEST_WAKING 0x00010000UL
162e53470feSOleksandr Tymoshenko #define CLKCTRL_IDLEST_IDLE 0x00020000UL
163e53470feSOleksandr Tymoshenko #define CLKCTRL_IDLEST_DISABLED 0x00030000UL
164e53470feSOleksandr Tymoshenko
1655b03aba6SOleksandr Tymoshenko static struct ofw_compat_data compat_data[] = {
1665b03aba6SOleksandr Tymoshenko {"ti,omap4-cm1", (uintptr_t)CM1_INSTANCE},
1675b03aba6SOleksandr Tymoshenko {"ti,omap4-cm2", (uintptr_t)CM2_INSTANCE},
1685b03aba6SOleksandr Tymoshenko {"ti,omap4-prm", (uintptr_t)PRM_INSTANCE},
1695b03aba6SOleksandr Tymoshenko {NULL, (uintptr_t)0},
170e53470feSOleksandr Tymoshenko };
171e53470feSOleksandr Tymoshenko
172e53470feSOleksandr Tymoshenko struct omap4_prcm_softc {
1735b03aba6SOleksandr Tymoshenko struct resource *sc_res;
1745b03aba6SOleksandr Tymoshenko int sc_rid;
1755b03aba6SOleksandr Tymoshenko int sc_instance;
17668301119SEmmanuel Vadot int attach_done;
177e53470feSOleksandr Tymoshenko };
178e53470feSOleksandr Tymoshenko
179e53470feSOleksandr Tymoshenko static int omap4_clk_generic_activate(struct ti_clock_dev *clkdev);
180e53470feSOleksandr Tymoshenko static int omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev);
181e53470feSOleksandr Tymoshenko static int omap4_clk_generic_accessible(struct ti_clock_dev *clkdev);
182e53470feSOleksandr Tymoshenko static int omap4_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
183e53470feSOleksandr Tymoshenko static int omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
184e53470feSOleksandr Tymoshenko
185e53470feSOleksandr Tymoshenko static int omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
186e53470feSOleksandr Tymoshenko static int omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
187e53470feSOleksandr Tymoshenko
188e53470feSOleksandr Tymoshenko static int omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
189e53470feSOleksandr Tymoshenko static int omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
190e53470feSOleksandr Tymoshenko
191e53470feSOleksandr Tymoshenko static int omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
192e53470feSOleksandr Tymoshenko static int omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev);
193e53470feSOleksandr Tymoshenko static int omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev);
194e53470feSOleksandr Tymoshenko static int omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev);
195e53470feSOleksandr Tymoshenko
196e53470feSOleksandr Tymoshenko static int omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
197e53470feSOleksandr Tymoshenko static int omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
198e53470feSOleksandr Tymoshenko
199e53470feSOleksandr Tymoshenko /**
200e53470feSOleksandr Tymoshenko * omap_clk_devmap - Array of clock devices available on OMAP4xxx devices
201e53470feSOleksandr Tymoshenko *
202e53470feSOleksandr Tymoshenko * This map only defines which clocks are valid and the callback functions
203e53470feSOleksandr Tymoshenko * for clock activate, deactivate, etc. It is used by the top level omap_prcm
204e53470feSOleksandr Tymoshenko * driver.
205e53470feSOleksandr Tymoshenko *
206e53470feSOleksandr Tymoshenko * The actual details of the clocks (config registers, bit fields, sources,
207e53470feSOleksandr Tymoshenko * etc) are in the private g_omap3_clk_details array below.
208e53470feSOleksandr Tymoshenko *
209e53470feSOleksandr Tymoshenko */
210e53470feSOleksandr Tymoshenko
211e53470feSOleksandr Tymoshenko #define OMAP4_GENERIC_CLOCK_DEV(i) \
212e53470feSOleksandr Tymoshenko { .id = (i), \
213e53470feSOleksandr Tymoshenko .clk_activate = omap4_clk_generic_activate, \
214e53470feSOleksandr Tymoshenko .clk_deactivate = omap4_clk_generic_deactivate, \
215e53470feSOleksandr Tymoshenko .clk_set_source = omap4_clk_generic_set_source, \
216e53470feSOleksandr Tymoshenko .clk_accessible = omap4_clk_generic_accessible, \
217a08b6d11SOleksandr Tymoshenko .clk_get_source_freq = omap4_clk_generic_get_source_freq, \
218a08b6d11SOleksandr Tymoshenko .clk_set_source_freq = NULL \
219e53470feSOleksandr Tymoshenko }
220e53470feSOleksandr Tymoshenko
221e53470feSOleksandr Tymoshenko #define OMAP4_GPTIMER_CLOCK_DEV(i) \
222e53470feSOleksandr Tymoshenko { .id = (i), \
223e53470feSOleksandr Tymoshenko .clk_activate = omap4_clk_generic_activate, \
224e53470feSOleksandr Tymoshenko .clk_deactivate = omap4_clk_generic_deactivate, \
225e53470feSOleksandr Tymoshenko .clk_set_source = omap4_clk_gptimer_set_source, \
226e53470feSOleksandr Tymoshenko .clk_accessible = omap4_clk_generic_accessible, \
227a08b6d11SOleksandr Tymoshenko .clk_get_source_freq = omap4_clk_gptimer_get_source_freq, \
228a08b6d11SOleksandr Tymoshenko .clk_set_source_freq = NULL \
229e53470feSOleksandr Tymoshenko }
230e53470feSOleksandr Tymoshenko
231e53470feSOleksandr Tymoshenko #define OMAP4_HSMMC_CLOCK_DEV(i) \
232e53470feSOleksandr Tymoshenko { .id = (i), \
233e53470feSOleksandr Tymoshenko .clk_activate = omap4_clk_generic_activate, \
234e53470feSOleksandr Tymoshenko .clk_deactivate = omap4_clk_generic_deactivate, \
235e53470feSOleksandr Tymoshenko .clk_set_source = omap4_clk_hsmmc_set_source, \
236e53470feSOleksandr Tymoshenko .clk_accessible = omap4_clk_generic_accessible, \
237a08b6d11SOleksandr Tymoshenko .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq, \
238a08b6d11SOleksandr Tymoshenko .clk_set_source_freq = NULL \
239e53470feSOleksandr Tymoshenko }
240e53470feSOleksandr Tymoshenko
241e53470feSOleksandr Tymoshenko #define OMAP4_HSUSBHOST_CLOCK_DEV(i) \
242e53470feSOleksandr Tymoshenko { .id = (i), \
243e53470feSOleksandr Tymoshenko .clk_activate = omap4_clk_hsusbhost_activate, \
244e53470feSOleksandr Tymoshenko .clk_deactivate = omap4_clk_hsusbhost_deactivate, \
245e53470feSOleksandr Tymoshenko .clk_set_source = omap4_clk_hsusbhost_set_source, \
246e53470feSOleksandr Tymoshenko .clk_accessible = omap4_clk_hsusbhost_accessible, \
247a08b6d11SOleksandr Tymoshenko .clk_get_source_freq = NULL, \
248a08b6d11SOleksandr Tymoshenko .clk_set_source_freq = NULL \
249e53470feSOleksandr Tymoshenko }
250e53470feSOleksandr Tymoshenko
2510a8c1fdfSAndrew Turner struct ti_clock_dev ti_omap4_clk_devmap[] = {
252e53470feSOleksandr Tymoshenko /* System clocks */
253e53470feSOleksandr Tymoshenko { .id = SYS_CLK,
254e53470feSOleksandr Tymoshenko .clk_activate = NULL,
255e53470feSOleksandr Tymoshenko .clk_deactivate = NULL,
256e53470feSOleksandr Tymoshenko .clk_set_source = NULL,
257e53470feSOleksandr Tymoshenko .clk_accessible = NULL,
258e53470feSOleksandr Tymoshenko .clk_get_source_freq = omap4_clk_get_sysclk_freq,
259a08b6d11SOleksandr Tymoshenko .clk_set_source_freq = NULL,
260e53470feSOleksandr Tymoshenko },
261e53470feSOleksandr Tymoshenko /* MPU (ARM) core clocks */
262e53470feSOleksandr Tymoshenko { .id = MPU_CLK,
263e53470feSOleksandr Tymoshenko .clk_activate = NULL,
264e53470feSOleksandr Tymoshenko .clk_deactivate = NULL,
265e53470feSOleksandr Tymoshenko .clk_set_source = NULL,
266e53470feSOleksandr Tymoshenko .clk_accessible = NULL,
267e53470feSOleksandr Tymoshenko .clk_get_source_freq = omap4_clk_get_arm_fclk_freq,
268a08b6d11SOleksandr Tymoshenko .clk_set_source_freq = NULL,
269e53470feSOleksandr Tymoshenko },
270e53470feSOleksandr Tymoshenko
271e53470feSOleksandr Tymoshenko /* UART device clocks */
272e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(UART1_CLK),
273e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(UART2_CLK),
274e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(UART3_CLK),
275e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(UART4_CLK),
276e53470feSOleksandr Tymoshenko
277e53470feSOleksandr Tymoshenko /* Timer device source clocks */
2785b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER1_CLK),
2795b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER2_CLK),
2805b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER3_CLK),
2815b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER4_CLK),
2825b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER5_CLK),
2835b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER6_CLK),
2845b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER7_CLK),
2855b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER8_CLK),
2865b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER9_CLK),
2875b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER10_CLK),
2885b03aba6SOleksandr Tymoshenko OMAP4_GPTIMER_CLOCK_DEV(TIMER11_CLK),
289e53470feSOleksandr Tymoshenko
290e53470feSOleksandr Tymoshenko /* MMC device clocks (MMC1 and MMC2 can have different input clocks) */
291e53470feSOleksandr Tymoshenko OMAP4_HSMMC_CLOCK_DEV(MMC1_CLK),
292e53470feSOleksandr Tymoshenko OMAP4_HSMMC_CLOCK_DEV(MMC2_CLK),
293e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(MMC3_CLK),
294e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(MMC4_CLK),
295e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(MMC5_CLK),
296e53470feSOleksandr Tymoshenko
297e53470feSOleksandr Tymoshenko /* USB HS (high speed TLL, EHCI and OHCI) */
298e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBTLL_CLK),
299e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBHSHOST_CLK),
300e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBFSHOST_CLK),
301e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_PHY_CLK),
302e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_PHY_CLK),
303e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_UTMI_CLK),
304e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_UTMI_CLK),
305e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBP1_HSIC_CLK),
306e53470feSOleksandr Tymoshenko OMAP4_HSUSBHOST_CLOCK_DEV(USBP2_HSIC_CLK),
307e53470feSOleksandr Tymoshenko
308e53470feSOleksandr Tymoshenko /* GPIO */
309e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(GPIO1_CLK),
310e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(GPIO2_CLK),
311e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(GPIO3_CLK),
312e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(GPIO4_CLK),
313e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(GPIO5_CLK),
314e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(GPIO6_CLK),
315e53470feSOleksandr Tymoshenko
316e53470feSOleksandr Tymoshenko /* sDMA */
317e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(SDMA_CLK),
318e53470feSOleksandr Tymoshenko
319e53470feSOleksandr Tymoshenko /* I2C */
320e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(I2C1_CLK),
321e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(I2C2_CLK),
322e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(I2C3_CLK),
323e53470feSOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DEV(I2C4_CLK),
324e53470feSOleksandr Tymoshenko { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
325e53470feSOleksandr Tymoshenko };
326e53470feSOleksandr Tymoshenko
327e53470feSOleksandr Tymoshenko /**
328e53470feSOleksandr Tymoshenko * omap4_clk_details - Stores details for all the different clocks supported
329e53470feSOleksandr Tymoshenko *
330e53470feSOleksandr Tymoshenko * Whenever an operation on a clock is being performed (activated, deactivated,
331e53470feSOleksandr Tymoshenko * etc) this array is looked up to find the correct register and bit(s) we
332e53470feSOleksandr Tymoshenko * should be modifying.
333e53470feSOleksandr Tymoshenko *
334e53470feSOleksandr Tymoshenko */
335e53470feSOleksandr Tymoshenko struct omap4_clk_details {
336e53470feSOleksandr Tymoshenko clk_ident_t id;
337e53470feSOleksandr Tymoshenko
3385b03aba6SOleksandr Tymoshenko uint32_t instance;
339e53470feSOleksandr Tymoshenko uint32_t clksel_reg;
340e53470feSOleksandr Tymoshenko
341e53470feSOleksandr Tymoshenko int32_t src_freq;
342e53470feSOleksandr Tymoshenko
343e53470feSOleksandr Tymoshenko uint32_t enable_mode;
344e53470feSOleksandr Tymoshenko };
345e53470feSOleksandr Tymoshenko
3465b03aba6SOleksandr Tymoshenko #define OMAP4_GENERIC_CLOCK_DETAILS(i, f, di, r, e) \
347e53470feSOleksandr Tymoshenko { .id = (i), \
3485b03aba6SOleksandr Tymoshenko .instance = (di), \
349e53470feSOleksandr Tymoshenko .clksel_reg = (r), \
350e53470feSOleksandr Tymoshenko .src_freq = (f), \
351e53470feSOleksandr Tymoshenko .enable_mode = (e), \
352e53470feSOleksandr Tymoshenko }
353e53470feSOleksandr Tymoshenko
354e53470feSOleksandr Tymoshenko static struct omap4_clk_details g_omap4_clk_details[] = {
355e53470feSOleksandr Tymoshenko /* UART */
3565b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(UART1_CLK, FREQ_48MHZ, CM2_INSTANCE,
357e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0140), CLKCTRL_MODULEMODE_ENABLE),
3585b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(UART2_CLK, FREQ_48MHZ, CM2_INSTANCE,
359e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0148), CLKCTRL_MODULEMODE_ENABLE),
3605b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(UART3_CLK, FREQ_48MHZ, CM2_INSTANCE,
3612927e6a8SOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0150), CLKCTRL_MODULEMODE_ENABLE),
3625b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(UART4_CLK, FREQ_48MHZ, CM2_INSTANCE,
3632927e6a8SOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0158), CLKCTRL_MODULEMODE_ENABLE),
364e53470feSOleksandr Tymoshenko
365e53470feSOleksandr Tymoshenko /* General purpose timers */
3665b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER1_CLK, -1, PRM_INSTANCE,
367e53470feSOleksandr Tymoshenko (WKUP_CM_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE),
3685b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER2_CLK, -1, CM2_INSTANCE,
369e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x038), CLKCTRL_MODULEMODE_ENABLE),
3705b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER3_CLK, -1, CM2_INSTANCE,
371e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x040), CLKCTRL_MODULEMODE_ENABLE),
3725b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER4_CLK, -1, CM2_INSTANCE,
373e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x048), CLKCTRL_MODULEMODE_ENABLE),
3745b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER5_CLK, -1, CM1_INSTANCE,
375e53470feSOleksandr Tymoshenko (ABE_CM1_OFFSET + 0x068), CLKCTRL_MODULEMODE_ENABLE),
3765b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER6_CLK, -1, CM1_INSTANCE,
377e53470feSOleksandr Tymoshenko (ABE_CM1_OFFSET + 0x070), CLKCTRL_MODULEMODE_ENABLE),
3785b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER7_CLK, -1, CM1_INSTANCE,
379e53470feSOleksandr Tymoshenko (ABE_CM1_OFFSET + 0x078), CLKCTRL_MODULEMODE_ENABLE),
3805b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER8_CLK, -1, CM1_INSTANCE,
381e53470feSOleksandr Tymoshenko (ABE_CM1_OFFSET + 0x080), CLKCTRL_MODULEMODE_ENABLE),
3825b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER9_CLK, -1, CM2_INSTANCE,
383e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x050), CLKCTRL_MODULEMODE_ENABLE),
3845b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER10_CLK, -1, CM2_INSTANCE,
385e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x028), CLKCTRL_MODULEMODE_ENABLE),
3865b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(TIMER11_CLK, -1, CM2_INSTANCE,
387e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x030), CLKCTRL_MODULEMODE_ENABLE),
388e53470feSOleksandr Tymoshenko
389e53470feSOleksandr Tymoshenko /* HSMMC (MMC1 and MMC2 can have different input clocks) */
3905b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(MMC1_CLK, -1, CM2_INSTANCE,
391e53470feSOleksandr Tymoshenko (L3INIT_CM2_OFFSET + 0x028), /*CLKCTRL_MODULEMODE_ENABLE*/2),
3925b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(MMC2_CLK, -1, CM2_INSTANCE,
393e53470feSOleksandr Tymoshenko (L3INIT_CM2_OFFSET + 0x030), /*CLKCTRL_MODULEMODE_ENABLE*/2),
3945b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(MMC3_CLK, FREQ_48MHZ, CM2_INSTANCE,
395e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x120), /*CLKCTRL_MODULEMODE_ENABLE*/2),
3965b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(MMC4_CLK, FREQ_48MHZ, CM2_INSTANCE,
397e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x128), /*CLKCTRL_MODULEMODE_ENABLE*/2),
3985b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(MMC5_CLK, FREQ_48MHZ, CM2_INSTANCE,
399e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x160), /*CLKCTRL_MODULEMODE_ENABLE*/1),
400e53470feSOleksandr Tymoshenko
401e53470feSOleksandr Tymoshenko /* GPIO modules */
4025b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(GPIO1_CLK, -1, PRM_INSTANCE,
403e53470feSOleksandr Tymoshenko (WKUP_CM_OFFSET + 0x038), CLKCTRL_MODULEMODE_AUTO),
4045b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(GPIO2_CLK, -1, CM2_INSTANCE,
405e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x060), CLKCTRL_MODULEMODE_AUTO),
4065b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(GPIO3_CLK, -1, CM2_INSTANCE,
407e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x068), CLKCTRL_MODULEMODE_AUTO),
4085b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(GPIO4_CLK, -1, CM2_INSTANCE,
409e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x070), CLKCTRL_MODULEMODE_AUTO),
4105b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(GPIO5_CLK, -1, CM2_INSTANCE,
411e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x078), CLKCTRL_MODULEMODE_AUTO),
4125b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(GPIO6_CLK, -1, CM2_INSTANCE,
413e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x080), CLKCTRL_MODULEMODE_AUTO),
414e53470feSOleksandr Tymoshenko
415e53470feSOleksandr Tymoshenko /* sDMA block */
4165b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(SDMA_CLK, -1, CM2_INSTANCE,
417e53470feSOleksandr Tymoshenko (CORE_CM2_OFFSET + 0x300), CLKCTRL_MODULEMODE_AUTO),
418e53470feSOleksandr Tymoshenko
419e53470feSOleksandr Tymoshenko /* I2C modules */
4205b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(I2C1_CLK, -1, CM2_INSTANCE,
421e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0A0), CLKCTRL_MODULEMODE_ENABLE),
4225b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(I2C2_CLK, -1, CM2_INSTANCE,
423e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0A8), CLKCTRL_MODULEMODE_ENABLE),
4245b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(I2C3_CLK, -1, CM2_INSTANCE,
425e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0B0), CLKCTRL_MODULEMODE_ENABLE),
4265b03aba6SOleksandr Tymoshenko OMAP4_GENERIC_CLOCK_DETAILS(I2C4_CLK, -1, CM2_INSTANCE,
427e53470feSOleksandr Tymoshenko (L4PER_CM2_OFFSET + 0x0B8), CLKCTRL_MODULEMODE_ENABLE),
428e53470feSOleksandr Tymoshenko
429e53470feSOleksandr Tymoshenko { INVALID_CLK_IDENT, 0, 0, 0, 0 },
430e53470feSOleksandr Tymoshenko };
431e53470feSOleksandr Tymoshenko
432e53470feSOleksandr Tymoshenko /**
433e53470feSOleksandr Tymoshenko * MAX_MODULE_ENABLE_WAIT - the number of loops to wait for the module to come
434e53470feSOleksandr Tymoshenko * alive.
435e53470feSOleksandr Tymoshenko *
436e53470feSOleksandr Tymoshenko */
437e53470feSOleksandr Tymoshenko #define MAX_MODULE_ENABLE_WAIT 100
438e53470feSOleksandr Tymoshenko
439e53470feSOleksandr Tymoshenko /**
440e53470feSOleksandr Tymoshenko * ARRAY_SIZE - Macro to return the number of elements in a static const array.
441e53470feSOleksandr Tymoshenko *
442e53470feSOleksandr Tymoshenko */
443e53470feSOleksandr Tymoshenko #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
444e53470feSOleksandr Tymoshenko
445e53470feSOleksandr Tymoshenko /**
446e53470feSOleksandr Tymoshenko * omap4_clk_details - writes a 32-bit value to one of the timer registers
447e53470feSOleksandr Tymoshenko * @timer: Timer device context
448e53470feSOleksandr Tymoshenko * @off: The offset of a register from the timer register address range
449e53470feSOleksandr Tymoshenko * @val: The value to write into the register
450e53470feSOleksandr Tymoshenko *
451e53470feSOleksandr Tymoshenko *
452e53470feSOleksandr Tymoshenko * RETURNS:
453e53470feSOleksandr Tymoshenko * nothing
454e53470feSOleksandr Tymoshenko */
455e53470feSOleksandr Tymoshenko static struct omap4_clk_details*
omap4_clk_details(clk_ident_t id)456e53470feSOleksandr Tymoshenko omap4_clk_details(clk_ident_t id)
457e53470feSOleksandr Tymoshenko {
458e53470feSOleksandr Tymoshenko struct omap4_clk_details *walker;
459e53470feSOleksandr Tymoshenko
460e53470feSOleksandr Tymoshenko for (walker = g_omap4_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
461e53470feSOleksandr Tymoshenko if (id == walker->id)
462e53470feSOleksandr Tymoshenko return (walker);
463e53470feSOleksandr Tymoshenko }
464e53470feSOleksandr Tymoshenko
465e53470feSOleksandr Tymoshenko return NULL;
466e53470feSOleksandr Tymoshenko }
467e53470feSOleksandr Tymoshenko
4685b03aba6SOleksandr Tymoshenko static struct omap4_prcm_softc *
omap4_prcm_get_instance_softc(int module_instance)4695b03aba6SOleksandr Tymoshenko omap4_prcm_get_instance_softc(int module_instance)
4705b03aba6SOleksandr Tymoshenko {
4715b03aba6SOleksandr Tymoshenko int i, maxunit;
4725b03aba6SOleksandr Tymoshenko devclass_t prcm_devclass;
4735b03aba6SOleksandr Tymoshenko device_t dev;
4745b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
4755b03aba6SOleksandr Tymoshenko
4765b03aba6SOleksandr Tymoshenko prcm_devclass = devclass_find("omap4_prcm");
4775b03aba6SOleksandr Tymoshenko maxunit = devclass_get_maxunit(prcm_devclass);
4785b03aba6SOleksandr Tymoshenko
4795b03aba6SOleksandr Tymoshenko for (i = 0; i < maxunit; i++) {
4805b03aba6SOleksandr Tymoshenko dev = devclass_get_device(prcm_devclass, i);
4815b03aba6SOleksandr Tymoshenko sc = device_get_softc(dev);
4825b03aba6SOleksandr Tymoshenko if (sc->sc_instance == module_instance)
4835b03aba6SOleksandr Tymoshenko return (sc);
4845b03aba6SOleksandr Tymoshenko }
4855b03aba6SOleksandr Tymoshenko
4865b03aba6SOleksandr Tymoshenko return (NULL);
4875b03aba6SOleksandr Tymoshenko }
4885b03aba6SOleksandr Tymoshenko
489e53470feSOleksandr Tymoshenko /**
490e53470feSOleksandr Tymoshenko * omap4_clk_generic_activate - checks if a module is accessible
491e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
492e53470feSOleksandr Tymoshenko * of possible modules.
493e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
494e53470feSOleksandr Tymoshenko *
495e53470feSOleksandr Tymoshenko *
496e53470feSOleksandr Tymoshenko *
497e53470feSOleksandr Tymoshenko * LOCKING:
498e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
499e53470feSOleksandr Tymoshenko *
500e53470feSOleksandr Tymoshenko * RETURNS:
501e53470feSOleksandr Tymoshenko * Returns 0 on success or a positive error code on failure.
502e53470feSOleksandr Tymoshenko */
503e53470feSOleksandr Tymoshenko static int
omap4_clk_generic_activate(struct ti_clock_dev * clkdev)504e53470feSOleksandr Tymoshenko omap4_clk_generic_activate(struct ti_clock_dev *clkdev)
505e53470feSOleksandr Tymoshenko {
5065b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
507e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
508e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
509e53470feSOleksandr Tymoshenko uint32_t clksel;
510e53470feSOleksandr Tymoshenko unsigned int i;
511e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
512e53470feSOleksandr Tymoshenko
513e53470feSOleksandr Tymoshenko if (clk_details == NULL)
514e53470feSOleksandr Tymoshenko return (ENXIO);
515e53470feSOleksandr Tymoshenko
5165b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
5175b03aba6SOleksandr Tymoshenko if (sc == NULL)
5185b03aba6SOleksandr Tymoshenko return ENXIO;
5195b03aba6SOleksandr Tymoshenko
5205b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
521e53470feSOleksandr Tymoshenko
522e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
523e53470feSOleksandr Tymoshenko return (EINVAL);
524e53470feSOleksandr Tymoshenko
525e53470feSOleksandr Tymoshenko /* All the 'generic' clocks have a CLKCTRL register which is more or less
526e53470feSOleksandr Tymoshenko * generic - the have at least two fielda called MODULEMODE and IDLEST.
527e53470feSOleksandr Tymoshenko */
528e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
529e53470feSOleksandr Tymoshenko clksel &= ~CLKCTRL_MODULEMODE_MASK;
530e53470feSOleksandr Tymoshenko clksel |= clk_details->enable_mode;
531e53470feSOleksandr Tymoshenko bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
532e53470feSOleksandr Tymoshenko
533e53470feSOleksandr Tymoshenko /* Now poll on the IDLEST register to tell us if the module has come up.
534e53470feSOleksandr Tymoshenko * TODO: We need to take into account the parent clocks.
535e53470feSOleksandr Tymoshenko */
536e53470feSOleksandr Tymoshenko
537e53470feSOleksandr Tymoshenko /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
538e53470feSOleksandr Tymoshenko for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
539e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
540e53470feSOleksandr Tymoshenko if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED)
541e53470feSOleksandr Tymoshenko break;
542e53470feSOleksandr Tymoshenko DELAY(10);
543e53470feSOleksandr Tymoshenko }
544e53470feSOleksandr Tymoshenko
545e53470feSOleksandr Tymoshenko /* Check the enabled state */
546e53470feSOleksandr Tymoshenko if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) {
547e53470feSOleksandr Tymoshenko printf("Error: failed to enable module with clock %d\n", clkdev->id);
548e53470feSOleksandr Tymoshenko printf("Error: 0x%08x => 0x%08x\n", clk_details->clksel_reg, clksel);
549e53470feSOleksandr Tymoshenko return (ETIMEDOUT);
550e53470feSOleksandr Tymoshenko }
551e53470feSOleksandr Tymoshenko
552e53470feSOleksandr Tymoshenko return (0);
553e53470feSOleksandr Tymoshenko }
554e53470feSOleksandr Tymoshenko
555e53470feSOleksandr Tymoshenko /**
556e53470feSOleksandr Tymoshenko * omap4_clk_generic_deactivate - checks if a module is accessible
557e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
558e53470feSOleksandr Tymoshenko * of possible modules.
559e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
560e53470feSOleksandr Tymoshenko *
561e53470feSOleksandr Tymoshenko *
562e53470feSOleksandr Tymoshenko *
563e53470feSOleksandr Tymoshenko * LOCKING:
564e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
565e53470feSOleksandr Tymoshenko *
566e53470feSOleksandr Tymoshenko * RETURNS:
567e53470feSOleksandr Tymoshenko * Returns 0 on success or a positive error code on failure.
568e53470feSOleksandr Tymoshenko */
569e53470feSOleksandr Tymoshenko static int
omap4_clk_generic_deactivate(struct ti_clock_dev * clkdev)570e53470feSOleksandr Tymoshenko omap4_clk_generic_deactivate(struct ti_clock_dev *clkdev)
571e53470feSOleksandr Tymoshenko {
5725b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
573e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
574e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
575e53470feSOleksandr Tymoshenko uint32_t clksel;
576e53470feSOleksandr Tymoshenko
577e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
578e53470feSOleksandr Tymoshenko
579e53470feSOleksandr Tymoshenko if (clk_details == NULL)
580e53470feSOleksandr Tymoshenko return (ENXIO);
581e53470feSOleksandr Tymoshenko
5825b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
5835b03aba6SOleksandr Tymoshenko if (sc == NULL)
5845b03aba6SOleksandr Tymoshenko return ENXIO;
5855b03aba6SOleksandr Tymoshenko
5865b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
587e53470feSOleksandr Tymoshenko
588e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
589e53470feSOleksandr Tymoshenko return (EINVAL);
590e53470feSOleksandr Tymoshenko
591e53470feSOleksandr Tymoshenko /* All the 'generic' clocks have a CLKCTRL register which is more or less
592e53470feSOleksandr Tymoshenko * generic - the have at least two fielda called MODULEMODE and IDLEST.
593e53470feSOleksandr Tymoshenko */
594e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
595e53470feSOleksandr Tymoshenko clksel &= ~CLKCTRL_MODULEMODE_MASK;
596e53470feSOleksandr Tymoshenko clksel |= CLKCTRL_MODULEMODE_DISABLE;
597e53470feSOleksandr Tymoshenko bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
598e53470feSOleksandr Tymoshenko
599e53470feSOleksandr Tymoshenko return (0);
600e53470feSOleksandr Tymoshenko }
601e53470feSOleksandr Tymoshenko
602e53470feSOleksandr Tymoshenko /**
603e53470feSOleksandr Tymoshenko * omap4_clk_generic_set_source - checks if a module is accessible
604e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
605e53470feSOleksandr Tymoshenko * of possible modules.
606e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
607e53470feSOleksandr Tymoshenko *
608e53470feSOleksandr Tymoshenko *
609e53470feSOleksandr Tymoshenko *
610e53470feSOleksandr Tymoshenko * LOCKING:
611e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
612e53470feSOleksandr Tymoshenko *
613e53470feSOleksandr Tymoshenko * RETURNS:
614e53470feSOleksandr Tymoshenko * Returns 0 on success or a positive error code on failure.
615e53470feSOleksandr Tymoshenko */
616e53470feSOleksandr Tymoshenko static int
omap4_clk_generic_set_source(struct ti_clock_dev * clkdev,clk_src_t clksrc)617e53470feSOleksandr Tymoshenko omap4_clk_generic_set_source(struct ti_clock_dev *clkdev,
618e53470feSOleksandr Tymoshenko clk_src_t clksrc)
619e53470feSOleksandr Tymoshenko {
620e53470feSOleksandr Tymoshenko
621e53470feSOleksandr Tymoshenko return (0);
622e53470feSOleksandr Tymoshenko }
623e53470feSOleksandr Tymoshenko
624e53470feSOleksandr Tymoshenko /**
625e53470feSOleksandr Tymoshenko * omap4_clk_generic_accessible - checks if a module is accessible
626e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
627e53470feSOleksandr Tymoshenko * of possible modules.
628e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
629e53470feSOleksandr Tymoshenko *
630e53470feSOleksandr Tymoshenko *
631e53470feSOleksandr Tymoshenko *
632e53470feSOleksandr Tymoshenko * LOCKING:
633e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
634e53470feSOleksandr Tymoshenko *
635e53470feSOleksandr Tymoshenko * RETURNS:
636e53470feSOleksandr Tymoshenko * Returns 0 on success or a negative error code on failure.
637e53470feSOleksandr Tymoshenko */
638e53470feSOleksandr Tymoshenko static int
omap4_clk_generic_accessible(struct ti_clock_dev * clkdev)639e53470feSOleksandr Tymoshenko omap4_clk_generic_accessible(struct ti_clock_dev *clkdev)
640e53470feSOleksandr Tymoshenko {
6415b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
642e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
643e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
644e53470feSOleksandr Tymoshenko uint32_t clksel;
645e53470feSOleksandr Tymoshenko
646e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
647e53470feSOleksandr Tymoshenko
648e53470feSOleksandr Tymoshenko if (clk_details == NULL)
649e53470feSOleksandr Tymoshenko return (ENXIO);
650e53470feSOleksandr Tymoshenko
6515b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
6525b03aba6SOleksandr Tymoshenko if (sc == NULL)
6535b03aba6SOleksandr Tymoshenko return ENXIO;
6545b03aba6SOleksandr Tymoshenko
6555b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
656e53470feSOleksandr Tymoshenko
657e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
658e53470feSOleksandr Tymoshenko return (EINVAL);
659e53470feSOleksandr Tymoshenko
660e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
661e53470feSOleksandr Tymoshenko
662e53470feSOleksandr Tymoshenko /* Check the enabled state */
663e53470feSOleksandr Tymoshenko if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED)
664e53470feSOleksandr Tymoshenko return (0);
665e53470feSOleksandr Tymoshenko
666e53470feSOleksandr Tymoshenko return (1);
667e53470feSOleksandr Tymoshenko }
668e53470feSOleksandr Tymoshenko
669e53470feSOleksandr Tymoshenko /**
670e53470feSOleksandr Tymoshenko * omap4_clk_generic_get_source_freq - checks if a module is accessible
671e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
672e53470feSOleksandr Tymoshenko * of possible modules.
673e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
674e53470feSOleksandr Tymoshenko *
675e53470feSOleksandr Tymoshenko *
676e53470feSOleksandr Tymoshenko *
677e53470feSOleksandr Tymoshenko * LOCKING:
678e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
679e53470feSOleksandr Tymoshenko *
680e53470feSOleksandr Tymoshenko * RETURNS:
681e53470feSOleksandr Tymoshenko * Returns 0 on success or a negative error code on failure.
682e53470feSOleksandr Tymoshenko */
683e53470feSOleksandr Tymoshenko static int
omap4_clk_generic_get_source_freq(struct ti_clock_dev * clkdev,unsigned int * freq)684e53470feSOleksandr Tymoshenko omap4_clk_generic_get_source_freq(struct ti_clock_dev *clkdev,
685e53470feSOleksandr Tymoshenko unsigned int *freq
686e53470feSOleksandr Tymoshenko )
687e53470feSOleksandr Tymoshenko {
688e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details = omap4_clk_details(clkdev->id);
689e53470feSOleksandr Tymoshenko
690e53470feSOleksandr Tymoshenko if (clk_details == NULL)
691e53470feSOleksandr Tymoshenko return (ENXIO);
692e53470feSOleksandr Tymoshenko
693e53470feSOleksandr Tymoshenko /* Simply return the stored frequency */
694e53470feSOleksandr Tymoshenko if (freq)
695e53470feSOleksandr Tymoshenko *freq = (unsigned int)clk_details->src_freq;
696e53470feSOleksandr Tymoshenko
697e53470feSOleksandr Tymoshenko return (0);
698e53470feSOleksandr Tymoshenko }
699e53470feSOleksandr Tymoshenko
700e53470feSOleksandr Tymoshenko /**
701e53470feSOleksandr Tymoshenko * omap4_clk_gptimer_set_source - checks if a module is accessible
702e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
703e53470feSOleksandr Tymoshenko * of possible modules.
704e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
705e53470feSOleksandr Tymoshenko *
706e53470feSOleksandr Tymoshenko *
707e53470feSOleksandr Tymoshenko *
708e53470feSOleksandr Tymoshenko * LOCKING:
709e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
710e53470feSOleksandr Tymoshenko *
711e53470feSOleksandr Tymoshenko * RETURNS:
712e53470feSOleksandr Tymoshenko * Returns 0 on success or a negative error code on failure.
713e53470feSOleksandr Tymoshenko */
714e53470feSOleksandr Tymoshenko static int
omap4_clk_gptimer_set_source(struct ti_clock_dev * clkdev,clk_src_t clksrc)715e53470feSOleksandr Tymoshenko omap4_clk_gptimer_set_source(struct ti_clock_dev *clkdev,
716e53470feSOleksandr Tymoshenko clk_src_t clksrc)
717e53470feSOleksandr Tymoshenko {
7185b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
719e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
720e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
721e53470feSOleksandr Tymoshenko
722e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
723e53470feSOleksandr Tymoshenko
724e53470feSOleksandr Tymoshenko if (clk_details == NULL)
725e53470feSOleksandr Tymoshenko return (ENXIO);
726e53470feSOleksandr Tymoshenko
7275b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
7285b03aba6SOleksandr Tymoshenko if (sc == NULL)
7295b03aba6SOleksandr Tymoshenko return ENXIO;
7305b03aba6SOleksandr Tymoshenko
7315b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
732e53470feSOleksandr Tymoshenko
733e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
734e53470feSOleksandr Tymoshenko return (EINVAL);
735e53470feSOleksandr Tymoshenko
736e53470feSOleksandr Tymoshenko /* TODO: Implement */
737e53470feSOleksandr Tymoshenko
738e53470feSOleksandr Tymoshenko return (0);
739e53470feSOleksandr Tymoshenko }
740e53470feSOleksandr Tymoshenko
741e53470feSOleksandr Tymoshenko /**
742e53470feSOleksandr Tymoshenko * omap4_clk_gptimer_get_source_freq - checks if a module is accessible
743e53470feSOleksandr Tymoshenko * @module: identifier for the module to check, see omap3_prcm.h for a list
744e53470feSOleksandr Tymoshenko * of possible modules.
745e53470feSOleksandr Tymoshenko * Example: OMAP3_MODULE_MMC1
746e53470feSOleksandr Tymoshenko *
747e53470feSOleksandr Tymoshenko *
748e53470feSOleksandr Tymoshenko *
749e53470feSOleksandr Tymoshenko * LOCKING:
750e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
751e53470feSOleksandr Tymoshenko *
752e53470feSOleksandr Tymoshenko * RETURNS:
753e53470feSOleksandr Tymoshenko * Returns 0 on success or a negative error code on failure.
754e53470feSOleksandr Tymoshenko */
755e53470feSOleksandr Tymoshenko static int
omap4_clk_gptimer_get_source_freq(struct ti_clock_dev * clkdev,unsigned int * freq)756e53470feSOleksandr Tymoshenko omap4_clk_gptimer_get_source_freq(struct ti_clock_dev *clkdev,
757e53470feSOleksandr Tymoshenko unsigned int *freq
758e53470feSOleksandr Tymoshenko )
759e53470feSOleksandr Tymoshenko {
7605b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
761e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
762e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
763e53470feSOleksandr Tymoshenko uint32_t clksel;
764e53470feSOleksandr Tymoshenko unsigned int src_freq;
765e53470feSOleksandr Tymoshenko
766e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
767e53470feSOleksandr Tymoshenko
768e53470feSOleksandr Tymoshenko if (clk_details == NULL)
769e53470feSOleksandr Tymoshenko return (ENXIO);
770e53470feSOleksandr Tymoshenko
7715b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
7725b03aba6SOleksandr Tymoshenko if (sc == NULL)
7735b03aba6SOleksandr Tymoshenko return ENXIO;
7745b03aba6SOleksandr Tymoshenko
7755b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
776e53470feSOleksandr Tymoshenko
777e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
778e53470feSOleksandr Tymoshenko return (EINVAL);
779e53470feSOleksandr Tymoshenko
780e53470feSOleksandr Tymoshenko /* Need to read the CLKSEL field to determine the clock source */
781e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
782e53470feSOleksandr Tymoshenko if (clksel & (0x1UL << 24))
783e53470feSOleksandr Tymoshenko src_freq = FREQ_32KHZ;
784e53470feSOleksandr Tymoshenko else
785e53470feSOleksandr Tymoshenko omap4_clk_get_sysclk_freq(NULL, &src_freq);
786e53470feSOleksandr Tymoshenko
787e53470feSOleksandr Tymoshenko /* Return the frequency */
788e53470feSOleksandr Tymoshenko if (freq)
789e53470feSOleksandr Tymoshenko *freq = src_freq;
790e53470feSOleksandr Tymoshenko
791e53470feSOleksandr Tymoshenko return (0);
792e53470feSOleksandr Tymoshenko }
793e53470feSOleksandr Tymoshenko
794e53470feSOleksandr Tymoshenko /**
795e53470feSOleksandr Tymoshenko * omap4_clk_hsmmc_set_source - sets the source clock (freq)
796e53470feSOleksandr Tymoshenko * @clkdev: pointer to the clockdev structure (id field will contain clock id)
797e53470feSOleksandr Tymoshenko *
798e53470feSOleksandr Tymoshenko * The MMC 1 and 2 clocks can be source from either a 64MHz or 96MHz clock.
799e53470feSOleksandr Tymoshenko *
800e53470feSOleksandr Tymoshenko * LOCKING:
801e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
802e53470feSOleksandr Tymoshenko *
803e53470feSOleksandr Tymoshenko * RETURNS:
804e53470feSOleksandr Tymoshenko * Returns 0 on success or a negative error code on failure.
805e53470feSOleksandr Tymoshenko */
806e53470feSOleksandr Tymoshenko static int
omap4_clk_hsmmc_set_source(struct ti_clock_dev * clkdev,clk_src_t clksrc)807e53470feSOleksandr Tymoshenko omap4_clk_hsmmc_set_source(struct ti_clock_dev *clkdev,
808e53470feSOleksandr Tymoshenko clk_src_t clksrc)
809e53470feSOleksandr Tymoshenko {
8105b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
811e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
812e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
813e53470feSOleksandr Tymoshenko uint32_t clksel;
814e53470feSOleksandr Tymoshenko
815e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
816e53470feSOleksandr Tymoshenko
817e53470feSOleksandr Tymoshenko if (clk_details == NULL)
818e53470feSOleksandr Tymoshenko return (ENXIO);
819e53470feSOleksandr Tymoshenko
8205b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
8215b03aba6SOleksandr Tymoshenko if (sc == NULL)
8225b03aba6SOleksandr Tymoshenko return ENXIO;
8235b03aba6SOleksandr Tymoshenko
8245b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
825e53470feSOleksandr Tymoshenko
826e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
827e53470feSOleksandr Tymoshenko return (EINVAL);
828e53470feSOleksandr Tymoshenko
829e53470feSOleksandr Tymoshenko /* For MMC modules 3, 4 & 5 you can't change the freq, it's always 48MHz */
830e53470feSOleksandr Tymoshenko if ((clkdev->id == MMC3_CLK) || (clkdev->id == MMC4_CLK) ||
831e53470feSOleksandr Tymoshenko (clkdev->id == MMC5_CLK)) {
832e53470feSOleksandr Tymoshenko if (clksrc != F48MHZ_CLK)
833e53470feSOleksandr Tymoshenko return (EINVAL);
834e53470feSOleksandr Tymoshenko return 0;
835e53470feSOleksandr Tymoshenko }
836e53470feSOleksandr Tymoshenko
837e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
838e53470feSOleksandr Tymoshenko
839e53470feSOleksandr Tymoshenko /* Bit 24 is set if 96MHz clock or cleared for 64MHz clock */
840e53470feSOleksandr Tymoshenko if (clksrc == F64MHZ_CLK)
841e53470feSOleksandr Tymoshenko clksel &= ~(0x1UL << 24);
842e53470feSOleksandr Tymoshenko else if (clksrc == F96MHZ_CLK)
843e53470feSOleksandr Tymoshenko clksel |= (0x1UL << 24);
844e53470feSOleksandr Tymoshenko else
845e53470feSOleksandr Tymoshenko return (EINVAL);
846e53470feSOleksandr Tymoshenko
847e53470feSOleksandr Tymoshenko bus_write_4(clk_mem_res, clk_details->clksel_reg, clksel);
848e53470feSOleksandr Tymoshenko
849e53470feSOleksandr Tymoshenko return (0);
850e53470feSOleksandr Tymoshenko }
851e53470feSOleksandr Tymoshenko
852e53470feSOleksandr Tymoshenko /**
853e53470feSOleksandr Tymoshenko * omap4_clk_hsmmc_get_source_freq - checks if a module is accessible
854e53470feSOleksandr Tymoshenko * @clkdev: pointer to the clockdev structure (id field will contain clock id)
855e53470feSOleksandr Tymoshenko *
856e53470feSOleksandr Tymoshenko *
857e53470feSOleksandr Tymoshenko *
858e53470feSOleksandr Tymoshenko * LOCKING:
859e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
860e53470feSOleksandr Tymoshenko *
861e53470feSOleksandr Tymoshenko * RETURNS:
862e53470feSOleksandr Tymoshenko * Returns 0 on success or a negative error code on failure.
863e53470feSOleksandr Tymoshenko */
864e53470feSOleksandr Tymoshenko static int
omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev * clkdev,unsigned int * freq)865e53470feSOleksandr Tymoshenko omap4_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,
866e53470feSOleksandr Tymoshenko unsigned int *freq
867e53470feSOleksandr Tymoshenko )
868e53470feSOleksandr Tymoshenko {
8695b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
870e53470feSOleksandr Tymoshenko struct omap4_clk_details* clk_details;
871e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
872e53470feSOleksandr Tymoshenko uint32_t clksel;
873e53470feSOleksandr Tymoshenko unsigned int src_freq;
874e53470feSOleksandr Tymoshenko
875e53470feSOleksandr Tymoshenko clk_details = omap4_clk_details(clkdev->id);
876e53470feSOleksandr Tymoshenko
877e53470feSOleksandr Tymoshenko if (clk_details == NULL)
878e53470feSOleksandr Tymoshenko return (ENXIO);
879e53470feSOleksandr Tymoshenko
8805b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(clk_details->instance);
8815b03aba6SOleksandr Tymoshenko if (sc == NULL)
8825b03aba6SOleksandr Tymoshenko return ENXIO;
8835b03aba6SOleksandr Tymoshenko
8845b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
885e53470feSOleksandr Tymoshenko
886e53470feSOleksandr Tymoshenko if (clk_mem_res == NULL)
887e53470feSOleksandr Tymoshenko return (EINVAL);
888e53470feSOleksandr Tymoshenko
889e53470feSOleksandr Tymoshenko switch (clkdev->id) {
890e53470feSOleksandr Tymoshenko case MMC1_CLK:
891e53470feSOleksandr Tymoshenko case MMC2_CLK:
892e53470feSOleksandr Tymoshenko /* Need to read the CLKSEL field to determine the clock source */
893e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clk_details->clksel_reg);
894e53470feSOleksandr Tymoshenko if (clksel & (0x1UL << 24))
895e53470feSOleksandr Tymoshenko src_freq = FREQ_96MHZ;
896e53470feSOleksandr Tymoshenko else
897e53470feSOleksandr Tymoshenko src_freq = FREQ_64MHZ;
898e53470feSOleksandr Tymoshenko break;
899e53470feSOleksandr Tymoshenko case MMC3_CLK:
900e53470feSOleksandr Tymoshenko case MMC4_CLK:
901e53470feSOleksandr Tymoshenko case MMC5_CLK:
902e53470feSOleksandr Tymoshenko src_freq = FREQ_48MHZ;
903e53470feSOleksandr Tymoshenko break;
904e53470feSOleksandr Tymoshenko default:
905e53470feSOleksandr Tymoshenko return (EINVAL);
906e53470feSOleksandr Tymoshenko }
907e53470feSOleksandr Tymoshenko
908e53470feSOleksandr Tymoshenko /* Return the frequency */
909e53470feSOleksandr Tymoshenko if (freq)
910e53470feSOleksandr Tymoshenko *freq = src_freq;
911e53470feSOleksandr Tymoshenko
912e53470feSOleksandr Tymoshenko return (0);
913e53470feSOleksandr Tymoshenko }
914e53470feSOleksandr Tymoshenko
915e53470feSOleksandr Tymoshenko /**
916e53470feSOleksandr Tymoshenko * omap4_clk_get_sysclk_freq - gets the sysclk frequency
917e53470feSOleksandr Tymoshenko * @sc: pointer to the clk module/device context
918e53470feSOleksandr Tymoshenko *
919e53470feSOleksandr Tymoshenko * Read the clocking information from the power-control/boot-strap registers,
920e53470feSOleksandr Tymoshenko * and stored in two global variables.
921e53470feSOleksandr Tymoshenko *
922e53470feSOleksandr Tymoshenko * RETURNS:
923e53470feSOleksandr Tymoshenko * nothing, values are saved in global variables
924e53470feSOleksandr Tymoshenko */
925e53470feSOleksandr Tymoshenko static int
omap4_clk_get_sysclk_freq(struct ti_clock_dev * clkdev,unsigned int * freq)926e53470feSOleksandr Tymoshenko omap4_clk_get_sysclk_freq(struct ti_clock_dev *clkdev,
927e53470feSOleksandr Tymoshenko unsigned int *freq)
928e53470feSOleksandr Tymoshenko {
929e53470feSOleksandr Tymoshenko uint32_t clksel;
930e53470feSOleksandr Tymoshenko uint32_t sysclk;
9315b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
932e53470feSOleksandr Tymoshenko
9335b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(PRM_INSTANCE);
934e53470feSOleksandr Tymoshenko if (sc == NULL)
935e53470feSOleksandr Tymoshenko return ENXIO;
936e53470feSOleksandr Tymoshenko
937e53470feSOleksandr Tymoshenko /* Read the input clock freq from the configuration register (CM_SYS_CLKSEL) */
9385b03aba6SOleksandr Tymoshenko clksel = bus_read_4(sc->sc_res, CM_SYS_CLKSEL_OFFSET);
939e53470feSOleksandr Tymoshenko switch (clksel & 0x7) {
940e53470feSOleksandr Tymoshenko case 0x1:
941e53470feSOleksandr Tymoshenko /* 12Mhz */
942e53470feSOleksandr Tymoshenko sysclk = 12000000;
943e53470feSOleksandr Tymoshenko break;
944e53470feSOleksandr Tymoshenko case 0x3:
945e53470feSOleksandr Tymoshenko /* 16.8Mhz */
946e53470feSOleksandr Tymoshenko sysclk = 16800000;
947e53470feSOleksandr Tymoshenko break;
948e53470feSOleksandr Tymoshenko case 0x4:
949e53470feSOleksandr Tymoshenko /* 19.2Mhz */
950e53470feSOleksandr Tymoshenko sysclk = 19200000;
951e53470feSOleksandr Tymoshenko break;
952e53470feSOleksandr Tymoshenko case 0x5:
953e53470feSOleksandr Tymoshenko /* 26Mhz */
954e53470feSOleksandr Tymoshenko sysclk = 26000000;
955e53470feSOleksandr Tymoshenko break;
956e53470feSOleksandr Tymoshenko case 0x7:
957e53470feSOleksandr Tymoshenko /* 38.4Mhz */
958e53470feSOleksandr Tymoshenko sysclk = 38400000;
959e53470feSOleksandr Tymoshenko break;
960e53470feSOleksandr Tymoshenko default:
961e53470feSOleksandr Tymoshenko panic("%s: Invalid clock freq", __func__);
962e53470feSOleksandr Tymoshenko }
963e53470feSOleksandr Tymoshenko
964e53470feSOleksandr Tymoshenko /* Return the value */
965e53470feSOleksandr Tymoshenko if (freq)
966e53470feSOleksandr Tymoshenko *freq = sysclk;
967e53470feSOleksandr Tymoshenko
968e53470feSOleksandr Tymoshenko return (0);
969e53470feSOleksandr Tymoshenko }
970e53470feSOleksandr Tymoshenko
971e53470feSOleksandr Tymoshenko /**
972e53470feSOleksandr Tymoshenko * omap4_clk_get_arm_fclk_freq - gets the MPU clock frequency
973e53470feSOleksandr Tymoshenko * @clkdev: ignored
974e53470feSOleksandr Tymoshenko * @freq: pointer which upon return will contain the freq in hz
975e53470feSOleksandr Tymoshenko * @mem_res: array of allocated memory resources
976e53470feSOleksandr Tymoshenko *
977e53470feSOleksandr Tymoshenko * Reads the frequency setting information registers and returns the value
978e53470feSOleksandr Tymoshenko * in the freq variable.
979e53470feSOleksandr Tymoshenko *
980e53470feSOleksandr Tymoshenko * RETURNS:
981e53470feSOleksandr Tymoshenko * returns 0 on success, a positive error code on failure.
982e53470feSOleksandr Tymoshenko */
983e53470feSOleksandr Tymoshenko static int
omap4_clk_get_arm_fclk_freq(struct ti_clock_dev * clkdev,unsigned int * freq)984e53470feSOleksandr Tymoshenko omap4_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev,
985e53470feSOleksandr Tymoshenko unsigned int *freq)
986e53470feSOleksandr Tymoshenko {
987e53470feSOleksandr Tymoshenko uint32_t clksel;
988e53470feSOleksandr Tymoshenko uint32_t pll_mult, pll_div;
989e53470feSOleksandr Tymoshenko uint32_t mpuclk, sysclk;
9905b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
991e53470feSOleksandr Tymoshenko
9925b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(CM1_INSTANCE);
993e53470feSOleksandr Tymoshenko if (sc == NULL)
994e53470feSOleksandr Tymoshenko return ENXIO;
995e53470feSOleksandr Tymoshenko
996e53470feSOleksandr Tymoshenko /* Read the clksel register which contains the DPLL multiple and divide
997e53470feSOleksandr Tymoshenko * values. These are applied to the sysclk.
998e53470feSOleksandr Tymoshenko */
9995b03aba6SOleksandr Tymoshenko clksel = bus_read_4(sc->sc_res, CM_CLKSEL_DPLL_MPU);
1000e53470feSOleksandr Tymoshenko
1001e53470feSOleksandr Tymoshenko pll_mult = ((clksel >> 8) & 0x7ff);
1002e53470feSOleksandr Tymoshenko pll_div = (clksel & 0x7f) + 1;
1003e53470feSOleksandr Tymoshenko
1004e53470feSOleksandr Tymoshenko /* Get the system clock freq */
1005e53470feSOleksandr Tymoshenko omap4_clk_get_sysclk_freq(NULL, &sysclk);
1006e53470feSOleksandr Tymoshenko
1007e53470feSOleksandr Tymoshenko /* Calculate the MPU freq */
10085b4e50aeSOlivier Houchard mpuclk = ((uint64_t)sysclk * pll_mult) / pll_div;
1009e53470feSOleksandr Tymoshenko
1010e53470feSOleksandr Tymoshenko /* Return the value */
1011e53470feSOleksandr Tymoshenko if (freq)
1012e53470feSOleksandr Tymoshenko *freq = mpuclk;
1013e53470feSOleksandr Tymoshenko
1014e53470feSOleksandr Tymoshenko return (0);
1015e53470feSOleksandr Tymoshenko }
1016e53470feSOleksandr Tymoshenko
1017e53470feSOleksandr Tymoshenko /**
1018e53470feSOleksandr Tymoshenko * omap4_clk_hsusbhost_activate - activates the USB clocks for the given module
1019e53470feSOleksandr Tymoshenko * @clkdev: pointer to the clock device structure.
1020b78540b1SGabor Kovesdan * @mem_res: array of memory resources allocated by the top level PRCM driver.
1021e53470feSOleksandr Tymoshenko *
1022e53470feSOleksandr Tymoshenko * The USB clocking setup seems to be a bit more tricky than the other modules,
1023e53470feSOleksandr Tymoshenko * to start with the clocking diagram for the HS host module shows 13 different
1024e53470feSOleksandr Tymoshenko * clocks. So to try and make it easier to follow the clocking activation
102528323addSBryan Drewery * and deactivation is handled in its own set of callbacks.
1026e53470feSOleksandr Tymoshenko *
1027e53470feSOleksandr Tymoshenko * LOCKING:
1028e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
1029e53470feSOleksandr Tymoshenko *
1030e53470feSOleksandr Tymoshenko * RETURNS:
1031e53470feSOleksandr Tymoshenko * Returns 0 on success or a positive error code on failure.
1032e53470feSOleksandr Tymoshenko */
1033e53470feSOleksandr Tymoshenko
1034e53470feSOleksandr Tymoshenko struct dpll_param {
1035e53470feSOleksandr Tymoshenko unsigned int m;
1036e53470feSOleksandr Tymoshenko unsigned int n;
1037e53470feSOleksandr Tymoshenko unsigned int m2;
1038e53470feSOleksandr Tymoshenko unsigned int m3;
1039e53470feSOleksandr Tymoshenko unsigned int m4;
1040e53470feSOleksandr Tymoshenko unsigned int m5;
1041e53470feSOleksandr Tymoshenko unsigned int m6;
1042e53470feSOleksandr Tymoshenko unsigned int m7;
1043e53470feSOleksandr Tymoshenko };
1044e53470feSOleksandr Tymoshenko /* USB parameters */
1045e53470feSOleksandr Tymoshenko struct dpll_param usb_dpll_param[7] = {
1046e53470feSOleksandr Tymoshenko /* 12M values */
1047e53470feSOleksandr Tymoshenko {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
1048e53470feSOleksandr Tymoshenko /* 13M values */
1049e53470feSOleksandr Tymoshenko {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
1050e53470feSOleksandr Tymoshenko /* 16.8M values */
1051e53470feSOleksandr Tymoshenko {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
1052e53470feSOleksandr Tymoshenko /* 19.2M values */
1053e53470feSOleksandr Tymoshenko {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
1054e53470feSOleksandr Tymoshenko /* 26M values */
1055e53470feSOleksandr Tymoshenko {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
1056e53470feSOleksandr Tymoshenko /* 27M values */
1057e53470feSOleksandr Tymoshenko {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
1058e53470feSOleksandr Tymoshenko /* 38.4M values */
1059e53470feSOleksandr Tymoshenko #ifdef CONFIG_OMAP4_SDC
1060e53470feSOleksandr Tymoshenko {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0},
1061e53470feSOleksandr Tymoshenko #else
1062e53470feSOleksandr Tymoshenko {0x32, 0x1, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0},
1063e53470feSOleksandr Tymoshenko #endif
1064e53470feSOleksandr Tymoshenko };
1065e53470feSOleksandr Tymoshenko static int
omap4_clk_hsusbhost_activate(struct ti_clock_dev * clkdev)1066e53470feSOleksandr Tymoshenko omap4_clk_hsusbhost_activate(struct ti_clock_dev *clkdev)
1067e53470feSOleksandr Tymoshenko {
10685b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
1069e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
1070e53470feSOleksandr Tymoshenko uint32_t clksel_reg_off;
1071e53470feSOleksandr Tymoshenko uint32_t clksel;
1072e53470feSOleksandr Tymoshenko unsigned int i;
1073e53470feSOleksandr Tymoshenko
10745b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
1075e53470feSOleksandr Tymoshenko if (sc == NULL)
1076e53470feSOleksandr Tymoshenko return ENXIO;
1077e53470feSOleksandr Tymoshenko
1078e53470feSOleksandr Tymoshenko switch (clkdev->id) {
1079e53470feSOleksandr Tymoshenko case USBTLL_CLK:
1080e53470feSOleksandr Tymoshenko /* For the USBTLL module we need to enable the following clocks:
1081e53470feSOleksandr Tymoshenko * - INIT_L4_ICLK (will be enabled by bootloader)
1082e53470feSOleksandr Tymoshenko * - TLL_CH0_FCLK
1083e53470feSOleksandr Tymoshenko * - TLL_CH1_FCLK
1084e53470feSOleksandr Tymoshenko */
1085e53470feSOleksandr Tymoshenko
1086e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
10875b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1088e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
1089e53470feSOleksandr Tymoshenko
1090e53470feSOleksandr Tymoshenko /* Enable the module and also enable the optional func clocks for
1091e53470feSOleksandr Tymoshenko * channels 0 & 1 (is this needed ?)
1092e53470feSOleksandr Tymoshenko */
1093e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1094e53470feSOleksandr Tymoshenko clksel &= ~CLKCTRL_MODULEMODE_MASK;
1095e53470feSOleksandr Tymoshenko clksel |= CLKCTRL_MODULEMODE_ENABLE;
1096e53470feSOleksandr Tymoshenko
1097e53470feSOleksandr Tymoshenko clksel |= (0x1 << 8); /* USB-HOST optional clock: USB_CH0_CLK */
1098e53470feSOleksandr Tymoshenko clksel |= (0x1 << 9); /* USB-HOST optional clock: USB_CH1_CLK */
1099e53470feSOleksandr Tymoshenko break;
1100e53470feSOleksandr Tymoshenko
1101e53470feSOleksandr Tymoshenko case USBHSHOST_CLK:
1102e53470feSOleksandr Tymoshenko case USBP1_PHY_CLK:
1103e53470feSOleksandr Tymoshenko case USBP2_PHY_CLK:
1104e53470feSOleksandr Tymoshenko case USBP1_UTMI_CLK:
1105e53470feSOleksandr Tymoshenko case USBP2_UTMI_CLK:
1106e53470feSOleksandr Tymoshenko case USBP1_HSIC_CLK:
1107e53470feSOleksandr Tymoshenko case USBP2_HSIC_CLK:
1108e53470feSOleksandr Tymoshenko /* For the USB HS HOST module we need to enable the following clocks:
1109e53470feSOleksandr Tymoshenko * - INIT_L4_ICLK (will be enabled by bootloader)
1110e53470feSOleksandr Tymoshenko * - INIT_L3_ICLK (will be enabled by bootloader)
1111e53470feSOleksandr Tymoshenko * - INIT_48MC_FCLK
1112e53470feSOleksandr Tymoshenko * - UTMI_ROOT_GFCLK (UTMI only, create a new clock for that ?)
1113e53470feSOleksandr Tymoshenko * - UTMI_P1_FCLK (UTMI only, create a new clock for that ?)
1114e53470feSOleksandr Tymoshenko * - UTMI_P2_FCLK (UTMI only, create a new clock for that ?)
1115e53470feSOleksandr Tymoshenko * - HSIC_P1_60 (HSIC only, create a new clock for that ?)
1116e53470feSOleksandr Tymoshenko * - HSIC_P1_480 (HSIC only, create a new clock for that ?)
1117e53470feSOleksandr Tymoshenko * - HSIC_P2_60 (HSIC only, create a new clock for that ?)
1118e53470feSOleksandr Tymoshenko * - HSIC_P2_480 (HSIC only, create a new clock for that ?)
1119e53470feSOleksandr Tymoshenko */
1120e53470feSOleksandr Tymoshenko
1121e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
11225b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1123e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
1124e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1125e53470feSOleksandr Tymoshenko /* Enable the module and also enable the optional func clocks */
1126e53470feSOleksandr Tymoshenko if (clkdev->id == USBHSHOST_CLK) {
1127e53470feSOleksandr Tymoshenko clksel &= ~CLKCTRL_MODULEMODE_MASK;
1128e53470feSOleksandr Tymoshenko clksel |= /*CLKCTRL_MODULEMODE_ENABLE*/2;
1129e53470feSOleksandr Tymoshenko
1130e53470feSOleksandr Tymoshenko clksel |= (0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
1131e53470feSOleksandr Tymoshenko }
1132e53470feSOleksandr Tymoshenko
1133e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP1_UTMI_CLK)
1134e53470feSOleksandr Tymoshenko clksel |= (0x1 << 8); /* UTMI_P1_CLK */
1135e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP2_UTMI_CLK)
1136e53470feSOleksandr Tymoshenko clksel |= (0x1 << 9); /* UTMI_P2_CLK */
1137e53470feSOleksandr Tymoshenko
1138e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP1_HSIC_CLK)
1139e53470feSOleksandr Tymoshenko clksel |= (0x5 << 11); /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */
1140e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP2_HSIC_CLK)
1141e53470feSOleksandr Tymoshenko clksel |= (0x5 << 12); /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */
1142e53470feSOleksandr Tymoshenko
1143e53470feSOleksandr Tymoshenko break;
1144e53470feSOleksandr Tymoshenko
1145e53470feSOleksandr Tymoshenko default:
1146e53470feSOleksandr Tymoshenko return (EINVAL);
1147e53470feSOleksandr Tymoshenko }
1148e53470feSOleksandr Tymoshenko
1149e53470feSOleksandr Tymoshenko bus_write_4(clk_mem_res, clksel_reg_off, clksel);
1150e53470feSOleksandr Tymoshenko
1151e53470feSOleksandr Tymoshenko /* Try MAX_MODULE_ENABLE_WAIT number of times to check if enabled */
1152e53470feSOleksandr Tymoshenko for (i = 0; i < MAX_MODULE_ENABLE_WAIT; i++) {
1153e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1154e53470feSOleksandr Tymoshenko if ((clksel & CLKCTRL_IDLEST_MASK) == CLKCTRL_IDLEST_ENABLED)
1155e53470feSOleksandr Tymoshenko break;
1156e53470feSOleksandr Tymoshenko }
1157e53470feSOleksandr Tymoshenko
1158e53470feSOleksandr Tymoshenko /* Check the enabled state */
1159e53470feSOleksandr Tymoshenko if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED) {
1160e53470feSOleksandr Tymoshenko printf("Error: HERE failed to enable module with clock %d\n", clkdev->id);
1161e53470feSOleksandr Tymoshenko printf("Error: 0x%08x => 0x%08x\n", clksel_reg_off, clksel);
1162e53470feSOleksandr Tymoshenko return (ETIMEDOUT);
1163e53470feSOleksandr Tymoshenko }
1164e53470feSOleksandr Tymoshenko
1165e53470feSOleksandr Tymoshenko return (0);
1166e53470feSOleksandr Tymoshenko }
1167e53470feSOleksandr Tymoshenko
1168e53470feSOleksandr Tymoshenko /**
1169e53470feSOleksandr Tymoshenko * omap4_clk_generic_deactivate - checks if a module is accessible
1170e53470feSOleksandr Tymoshenko * @clkdev: pointer to the clock device structure.
1171b78540b1SGabor Kovesdan * @mem_res: array of memory resources allocated by the top level PRCM driver.
1172e53470feSOleksandr Tymoshenko *
1173e53470feSOleksandr Tymoshenko *
1174e53470feSOleksandr Tymoshenko *
1175e53470feSOleksandr Tymoshenko * LOCKING:
1176e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
1177e53470feSOleksandr Tymoshenko *
1178e53470feSOleksandr Tymoshenko * RETURNS:
1179e53470feSOleksandr Tymoshenko * Returns 0 on success or a positive error code on failure.
1180e53470feSOleksandr Tymoshenko */
1181e53470feSOleksandr Tymoshenko static int
omap4_clk_hsusbhost_deactivate(struct ti_clock_dev * clkdev)1182e53470feSOleksandr Tymoshenko omap4_clk_hsusbhost_deactivate(struct ti_clock_dev *clkdev)
1183e53470feSOleksandr Tymoshenko {
11845b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
1185e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
1186e53470feSOleksandr Tymoshenko uint32_t clksel_reg_off;
1187e53470feSOleksandr Tymoshenko uint32_t clksel;
1188e53470feSOleksandr Tymoshenko
11895b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
1190e53470feSOleksandr Tymoshenko if (sc == NULL)
1191e53470feSOleksandr Tymoshenko return ENXIO;
1192e53470feSOleksandr Tymoshenko
1193e53470feSOleksandr Tymoshenko switch (clkdev->id) {
1194e53470feSOleksandr Tymoshenko case USBTLL_CLK:
1195e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
11965b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1197e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
1198e53470feSOleksandr Tymoshenko
1199e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1200e53470feSOleksandr Tymoshenko clksel &= ~CLKCTRL_MODULEMODE_MASK;
1201e53470feSOleksandr Tymoshenko clksel |= CLKCTRL_MODULEMODE_DISABLE;
1202e53470feSOleksandr Tymoshenko break;
1203e53470feSOleksandr Tymoshenko
1204e53470feSOleksandr Tymoshenko case USBHSHOST_CLK:
1205e53470feSOleksandr Tymoshenko case USBP1_PHY_CLK:
1206e53470feSOleksandr Tymoshenko case USBP2_PHY_CLK:
1207e53470feSOleksandr Tymoshenko case USBP1_UTMI_CLK:
1208e53470feSOleksandr Tymoshenko case USBP2_UTMI_CLK:
1209e53470feSOleksandr Tymoshenko case USBP1_HSIC_CLK:
1210e53470feSOleksandr Tymoshenko case USBP2_HSIC_CLK:
1211e53470feSOleksandr Tymoshenko /* For the USB HS HOST module we need to enable the following clocks:
1212e53470feSOleksandr Tymoshenko * - INIT_L4_ICLK (will be enabled by bootloader)
1213e53470feSOleksandr Tymoshenko * - INIT_L3_ICLK (will be enabled by bootloader)
1214e53470feSOleksandr Tymoshenko * - INIT_48MC_FCLK
1215e53470feSOleksandr Tymoshenko * - UTMI_ROOT_GFCLK (UTMI only, create a new clock for that ?)
1216e53470feSOleksandr Tymoshenko * - UTMI_P1_FCLK (UTMI only, create a new clock for that ?)
1217e53470feSOleksandr Tymoshenko * - UTMI_P2_FCLK (UTMI only, create a new clock for that ?)
1218e53470feSOleksandr Tymoshenko * - HSIC_P1_60 (HSIC only, create a new clock for that ?)
1219e53470feSOleksandr Tymoshenko * - HSIC_P1_480 (HSIC only, create a new clock for that ?)
1220e53470feSOleksandr Tymoshenko * - HSIC_P2_60 (HSIC only, create a new clock for that ?)
1221e53470feSOleksandr Tymoshenko * - HSIC_P2_480 (HSIC only, create a new clock for that ?)
1222e53470feSOleksandr Tymoshenko */
1223e53470feSOleksandr Tymoshenko
1224e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
12255b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1226e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
1227e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1228e53470feSOleksandr Tymoshenko
1229e53470feSOleksandr Tymoshenko /* Enable the module and also enable the optional func clocks */
1230e53470feSOleksandr Tymoshenko if (clkdev->id == USBHSHOST_CLK) {
1231e53470feSOleksandr Tymoshenko clksel &= ~CLKCTRL_MODULEMODE_MASK;
1232e53470feSOleksandr Tymoshenko clksel |= CLKCTRL_MODULEMODE_DISABLE;
1233e53470feSOleksandr Tymoshenko
1234e53470feSOleksandr Tymoshenko clksel &= ~(0x1 << 15); /* USB-HOST clock control: FUNC48MCLK */
1235e53470feSOleksandr Tymoshenko }
1236e53470feSOleksandr Tymoshenko
1237e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP1_UTMI_CLK)
1238e53470feSOleksandr Tymoshenko clksel &= ~(0x1 << 8); /* UTMI_P1_CLK */
1239e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP2_UTMI_CLK)
1240e53470feSOleksandr Tymoshenko clksel &= ~(0x1 << 9); /* UTMI_P2_CLK */
1241e53470feSOleksandr Tymoshenko
1242e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP1_HSIC_CLK)
1243e53470feSOleksandr Tymoshenko clksel &= ~(0x5 << 11); /* HSIC60M_P1_CLK + HSIC480M_P1_CLK */
1244e53470feSOleksandr Tymoshenko else if (clkdev->id == USBP2_HSIC_CLK)
1245e53470feSOleksandr Tymoshenko clksel &= ~(0x5 << 12); /* HSIC60M_P2_CLK + HSIC480M_P2_CLK */
1246e53470feSOleksandr Tymoshenko
1247e53470feSOleksandr Tymoshenko break;
1248e53470feSOleksandr Tymoshenko
1249e53470feSOleksandr Tymoshenko default:
1250e53470feSOleksandr Tymoshenko return (EINVAL);
1251e53470feSOleksandr Tymoshenko }
1252e53470feSOleksandr Tymoshenko
1253e53470feSOleksandr Tymoshenko bus_write_4(clk_mem_res, clksel_reg_off, clksel);
1254e53470feSOleksandr Tymoshenko
1255e53470feSOleksandr Tymoshenko return (0);
1256e53470feSOleksandr Tymoshenko }
1257e53470feSOleksandr Tymoshenko
1258e53470feSOleksandr Tymoshenko /**
1259e53470feSOleksandr Tymoshenko * omap4_clk_hsusbhost_accessible - checks if a module is accessible
1260e53470feSOleksandr Tymoshenko * @clkdev: pointer to the clock device structure.
1261b78540b1SGabor Kovesdan * @mem_res: array of memory resources allocated by the top level PRCM driver.
1262e53470feSOleksandr Tymoshenko *
1263e53470feSOleksandr Tymoshenko *
1264e53470feSOleksandr Tymoshenko *
1265e53470feSOleksandr Tymoshenko * LOCKING:
1266e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
1267e53470feSOleksandr Tymoshenko *
1268e53470feSOleksandr Tymoshenko * RETURNS:
1269e53470feSOleksandr Tymoshenko * Returns 0 if module is not enable, 1 if module is enabled or a negative
1270e53470feSOleksandr Tymoshenko * error code on failure.
1271e53470feSOleksandr Tymoshenko */
1272e53470feSOleksandr Tymoshenko static int
omap4_clk_hsusbhost_accessible(struct ti_clock_dev * clkdev)1273e53470feSOleksandr Tymoshenko omap4_clk_hsusbhost_accessible(struct ti_clock_dev *clkdev)
1274e53470feSOleksandr Tymoshenko {
12755b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
1276e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
1277e53470feSOleksandr Tymoshenko uint32_t clksel_reg_off;
1278e53470feSOleksandr Tymoshenko uint32_t clksel;
1279e53470feSOleksandr Tymoshenko
12805b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
1281e53470feSOleksandr Tymoshenko if (sc == NULL)
1282e53470feSOleksandr Tymoshenko return ENXIO;
1283e53470feSOleksandr Tymoshenko
1284e53470feSOleksandr Tymoshenko if (clkdev->id == USBTLL_CLK) {
1285e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBTLL_CLKCTRL register in CM2 register set */
12865b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1287e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x68;
1288e53470feSOleksandr Tymoshenko }
1289e53470feSOleksandr Tymoshenko else if (clkdev->id == USBHSHOST_CLK) {
1290e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
12915b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1292e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
1293e53470feSOleksandr Tymoshenko }
1294e53470feSOleksandr Tymoshenko else {
1295e53470feSOleksandr Tymoshenko return (EINVAL);
1296e53470feSOleksandr Tymoshenko }
1297e53470feSOleksandr Tymoshenko
1298e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1299e53470feSOleksandr Tymoshenko
1300e53470feSOleksandr Tymoshenko /* Check the enabled state */
1301e53470feSOleksandr Tymoshenko if ((clksel & CLKCTRL_IDLEST_MASK) != CLKCTRL_IDLEST_ENABLED)
1302e53470feSOleksandr Tymoshenko return (0);
1303e53470feSOleksandr Tymoshenko
1304e53470feSOleksandr Tymoshenko return (1);
1305e53470feSOleksandr Tymoshenko }
1306e53470feSOleksandr Tymoshenko
1307e53470feSOleksandr Tymoshenko /**
1308e53470feSOleksandr Tymoshenko * omap4_clk_hsusbhost_set_source - sets the source clocks
1309e53470feSOleksandr Tymoshenko * @clkdev: pointer to the clock device structure.
1310e53470feSOleksandr Tymoshenko * @clksrc: the clock source ID for the given clock.
1311b78540b1SGabor Kovesdan * @mem_res: array of memory resources allocated by the top level PRCM driver.
1312e53470feSOleksandr Tymoshenko *
1313e53470feSOleksandr Tymoshenko *
1314e53470feSOleksandr Tymoshenko *
1315e53470feSOleksandr Tymoshenko * LOCKING:
1316e53470feSOleksandr Tymoshenko * Inherits the locks from the omap_prcm driver, no internal locking.
1317e53470feSOleksandr Tymoshenko *
1318e53470feSOleksandr Tymoshenko * RETURNS:
1319255eff3bSPedro F. Giffuni * Returns 0 if successful otherwise a negative error code on failure.
1320e53470feSOleksandr Tymoshenko */
1321e53470feSOleksandr Tymoshenko static int
omap4_clk_hsusbhost_set_source(struct ti_clock_dev * clkdev,clk_src_t clksrc)1322e53470feSOleksandr Tymoshenko omap4_clk_hsusbhost_set_source(struct ti_clock_dev *clkdev,
1323e53470feSOleksandr Tymoshenko clk_src_t clksrc)
1324e53470feSOleksandr Tymoshenko {
13255b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
1326e53470feSOleksandr Tymoshenko struct resource* clk_mem_res;
1327e53470feSOleksandr Tymoshenko uint32_t clksel_reg_off;
1328e53470feSOleksandr Tymoshenko uint32_t clksel;
1329e53470feSOleksandr Tymoshenko unsigned int bit;
1330e53470feSOleksandr Tymoshenko
13315b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(CM2_INSTANCE);
1332e53470feSOleksandr Tymoshenko if (sc == NULL)
1333e53470feSOleksandr Tymoshenko return ENXIO;
1334e53470feSOleksandr Tymoshenko
1335e53470feSOleksandr Tymoshenko if (clkdev->id == USBP1_PHY_CLK)
1336e53470feSOleksandr Tymoshenko bit = 24;
1337e53470feSOleksandr Tymoshenko else if (clkdev->id != USBP2_PHY_CLK)
1338e53470feSOleksandr Tymoshenko bit = 25;
1339e53470feSOleksandr Tymoshenko else
1340e53470feSOleksandr Tymoshenko return (EINVAL);
1341e53470feSOleksandr Tymoshenko
1342e53470feSOleksandr Tymoshenko /* We need the CM_L3INIT_HSUSBHOST_CLKCTRL register in CM2 register set */
13435b03aba6SOleksandr Tymoshenko clk_mem_res = sc->sc_res;
1344e53470feSOleksandr Tymoshenko clksel_reg_off = L3INIT_CM2_OFFSET + 0x58;
1345e53470feSOleksandr Tymoshenko clksel = bus_read_4(clk_mem_res, clksel_reg_off);
1346e53470feSOleksandr Tymoshenko
1347e53470feSOleksandr Tymoshenko /* Set the clock source to either external or internal */
1348e53470feSOleksandr Tymoshenko if (clksrc == EXT_CLK)
1349e53470feSOleksandr Tymoshenko clksel |= (0x1 << bit);
1350e53470feSOleksandr Tymoshenko else
1351e53470feSOleksandr Tymoshenko clksel &= ~(0x1 << bit);
1352e53470feSOleksandr Tymoshenko
1353e53470feSOleksandr Tymoshenko bus_write_4(clk_mem_res, clksel_reg_off, clksel);
1354e53470feSOleksandr Tymoshenko
1355e53470feSOleksandr Tymoshenko return (0);
1356e53470feSOleksandr Tymoshenko }
1357e53470feSOleksandr Tymoshenko
1358e53470feSOleksandr Tymoshenko #define PRM_RSTCTRL 0x1b00
1359e53470feSOleksandr Tymoshenko #define PRM_RSTCTRL_RESET 0x2
1360e53470feSOleksandr Tymoshenko
1361e53470feSOleksandr Tymoshenko static void
omap4_prcm_reset(void)1362e53470feSOleksandr Tymoshenko omap4_prcm_reset(void)
1363e53470feSOleksandr Tymoshenko {
13645b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
13655b03aba6SOleksandr Tymoshenko
13665b03aba6SOleksandr Tymoshenko sc = omap4_prcm_get_instance_softc(PRM_INSTANCE);
13675b03aba6SOleksandr Tymoshenko if (sc == NULL)
13685b03aba6SOleksandr Tymoshenko return;
13695b03aba6SOleksandr Tymoshenko
13705b03aba6SOleksandr Tymoshenko bus_write_4(sc->sc_res, PRM_RSTCTRL,
13715b03aba6SOleksandr Tymoshenko bus_read_4(sc->sc_res, PRM_RSTCTRL) | PRM_RSTCTRL_RESET);
13725b03aba6SOleksandr Tymoshenko bus_read_4(sc->sc_res, PRM_RSTCTRL);
1373e53470feSOleksandr Tymoshenko }
1374e53470feSOleksandr Tymoshenko
1375e53470feSOleksandr Tymoshenko /**
1376e53470feSOleksandr Tymoshenko * omap4_prcm_probe - probe function for the driver
1377e53470feSOleksandr Tymoshenko * @dev: prcm device handle
1378e53470feSOleksandr Tymoshenko *
1379e53470feSOleksandr Tymoshenko * Simply sets the name of the driver module.
1380e53470feSOleksandr Tymoshenko *
1381e53470feSOleksandr Tymoshenko * LOCKING:
1382e53470feSOleksandr Tymoshenko * None
1383e53470feSOleksandr Tymoshenko *
1384e53470feSOleksandr Tymoshenko * RETURNS:
1385e53470feSOleksandr Tymoshenko * Always returns 0
1386e53470feSOleksandr Tymoshenko */
1387e53470feSOleksandr Tymoshenko static int
omap4_prcm_probe(device_t dev)1388e53470feSOleksandr Tymoshenko omap4_prcm_probe(device_t dev)
1389e53470feSOleksandr Tymoshenko {
13905b03aba6SOleksandr Tymoshenko const struct ofw_compat_data *ocd;
1391add35ed5SIan Lepore
1392add35ed5SIan Lepore if (!ofw_bus_status_okay(dev))
1393add35ed5SIan Lepore return (ENXIO);
1394add35ed5SIan Lepore
13955b03aba6SOleksandr Tymoshenko ocd = ofw_bus_search_compatible(dev, compat_data);
13965b03aba6SOleksandr Tymoshenko if ((int)ocd->ocd_data == 0)
1397e53470feSOleksandr Tymoshenko return (ENXIO);
1398e53470feSOleksandr Tymoshenko
13995b03aba6SOleksandr Tymoshenko switch ((int)ocd->ocd_data) {
14005b03aba6SOleksandr Tymoshenko case PRM_INSTANCE:
14015b03aba6SOleksandr Tymoshenko device_set_desc(dev, "TI OMAP Power, Reset and Clock Management (PRM)");
14025b03aba6SOleksandr Tymoshenko break;
14035b03aba6SOleksandr Tymoshenko case CM1_INSTANCE:
14045b03aba6SOleksandr Tymoshenko device_set_desc(dev, "TI OMAP Power, Reset and Clock Management (C1)");
14055b03aba6SOleksandr Tymoshenko break;
14065b03aba6SOleksandr Tymoshenko case CM2_INSTANCE:
14075b03aba6SOleksandr Tymoshenko device_set_desc(dev, "TI OMAP Power, Reset and Clock Management (C2)");
14085b03aba6SOleksandr Tymoshenko break;
14095b03aba6SOleksandr Tymoshenko default:
14105b03aba6SOleksandr Tymoshenko device_printf(dev, "unknown instance type: %d\n", (int)ocd->ocd_data);
14115b03aba6SOleksandr Tymoshenko return (ENXIO);
14125b03aba6SOleksandr Tymoshenko }
14135b03aba6SOleksandr Tymoshenko
14145b03aba6SOleksandr Tymoshenko return (BUS_PROBE_DEFAULT);
1415e53470feSOleksandr Tymoshenko }
1416e53470feSOleksandr Tymoshenko
1417e53470feSOleksandr Tymoshenko /**
1418e53470feSOleksandr Tymoshenko * omap_prcm_attach - attach function for the driver
1419e53470feSOleksandr Tymoshenko * @dev: prcm device handle
1420e53470feSOleksandr Tymoshenko *
1421e53470feSOleksandr Tymoshenko * Allocates and sets up the driver context, this simply entails creating a
1422e53470feSOleksandr Tymoshenko * bus mappings for the PRCM register set.
1423e53470feSOleksandr Tymoshenko *
1424e53470feSOleksandr Tymoshenko * LOCKING:
1425e53470feSOleksandr Tymoshenko * None
1426e53470feSOleksandr Tymoshenko *
1427e53470feSOleksandr Tymoshenko * RETURNS:
1428e53470feSOleksandr Tymoshenko * Always returns 0
1429e53470feSOleksandr Tymoshenko */
14307497e626SOlivier Houchard
14317497e626SOlivier Houchard extern uint32_t platform_arm_tmr_freq;
14327497e626SOlivier Houchard
1433e53470feSOleksandr Tymoshenko static int
omap4_prcm_attach(device_t dev)1434e53470feSOleksandr Tymoshenko omap4_prcm_attach(device_t dev)
1435e53470feSOleksandr Tymoshenko {
14365b03aba6SOleksandr Tymoshenko struct omap4_prcm_softc *sc;
14375b03aba6SOleksandr Tymoshenko const struct ofw_compat_data *ocd;
1438e53470feSOleksandr Tymoshenko
14395b03aba6SOleksandr Tymoshenko sc = device_get_softc(dev);
14405b03aba6SOleksandr Tymoshenko ocd = ofw_bus_search_compatible(dev, compat_data);
14415b03aba6SOleksandr Tymoshenko sc->sc_instance = (int)ocd->ocd_data;
14425b03aba6SOleksandr Tymoshenko
14435b03aba6SOleksandr Tymoshenko sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
14445b03aba6SOleksandr Tymoshenko RF_ACTIVE);
14455b03aba6SOleksandr Tymoshenko if (sc->sc_res == NULL) {
1446e53470feSOleksandr Tymoshenko device_printf(dev, "could not allocate resources\n");
1447e53470feSOleksandr Tymoshenko return (ENXIO);
1448e53470feSOleksandr Tymoshenko }
1449e53470feSOleksandr Tymoshenko
1450e53470feSOleksandr Tymoshenko ti_cpu_reset = omap4_prcm_reset;
14515b03aba6SOleksandr Tymoshenko
145268301119SEmmanuel Vadot return (0);
145368301119SEmmanuel Vadot }
145468301119SEmmanuel Vadot
145568301119SEmmanuel Vadot static void
omap4_prcm_new_pass(device_t dev)145668301119SEmmanuel Vadot omap4_prcm_new_pass(device_t dev)
145768301119SEmmanuel Vadot {
145868301119SEmmanuel Vadot struct omap4_prcm_softc *sc = device_get_softc(dev);
145968301119SEmmanuel Vadot unsigned int freq;
146068301119SEmmanuel Vadot
146168301119SEmmanuel Vadot if (sc->attach_done ||
1462*3514f989SElliott Mitchell bus_get_pass() < (BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY)) {
146368301119SEmmanuel Vadot bus_generic_new_pass(dev);
146468301119SEmmanuel Vadot return;
146568301119SEmmanuel Vadot }
146668301119SEmmanuel Vadot sc->attach_done = 1;
146768301119SEmmanuel Vadot
14685b03aba6SOleksandr Tymoshenko /*
14695b03aba6SOleksandr Tymoshenko * In order to determine ARM frequency we need both RPM and CM1
14705b03aba6SOleksandr Tymoshenko * instances up and running. So wait until all CRM devices are
14715b03aba6SOleksandr Tymoshenko * initialized. Should be replaced with proper clock framework
14725b03aba6SOleksandr Tymoshenko */
14735b03aba6SOleksandr Tymoshenko if (device_get_unit(dev) == 2) {
14747497e626SOlivier Houchard omap4_clk_get_arm_fclk_freq(NULL, &freq);
1475b24b2743SIan Lepore arm_tmr_change_frequency(freq / 2);
14765b03aba6SOleksandr Tymoshenko }
1477e53470feSOleksandr Tymoshenko
147868301119SEmmanuel Vadot return;
1479e53470feSOleksandr Tymoshenko }
1480e53470feSOleksandr Tymoshenko
1481e53470feSOleksandr Tymoshenko static device_method_t omap4_prcm_methods[] = {
1482e53470feSOleksandr Tymoshenko DEVMETHOD(device_probe, omap4_prcm_probe),
1483e53470feSOleksandr Tymoshenko DEVMETHOD(device_attach, omap4_prcm_attach),
148468301119SEmmanuel Vadot
148568301119SEmmanuel Vadot /* Bus interface */
148668301119SEmmanuel Vadot DEVMETHOD(bus_new_pass, omap4_prcm_new_pass),
148768301119SEmmanuel Vadot
1488e53470feSOleksandr Tymoshenko {0, 0},
1489e53470feSOleksandr Tymoshenko };
1490e53470feSOleksandr Tymoshenko
1491e53470feSOleksandr Tymoshenko static driver_t omap4_prcm_driver = {
1492e53470feSOleksandr Tymoshenko "omap4_prcm",
1493e53470feSOleksandr Tymoshenko omap4_prcm_methods,
1494e53470feSOleksandr Tymoshenko sizeof(struct omap4_prcm_softc),
1495e53470feSOleksandr Tymoshenko };
1496e53470feSOleksandr Tymoshenko
14978537e671SJohn Baldwin EARLY_DRIVER_MODULE(omap4_prcm, simplebus, omap4_prcm_driver, 0, 0,
14988537e671SJohn Baldwin BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
1499e53470feSOleksandr Tymoshenko MODULE_VERSION(omap4_prcm, 1);
1500