am335x_prcm.c revision 254593
1/*-
2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/arm/ti/am335x/am335x_prcm.c 254593 2013-08-21 04:49:58Z ian $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/kernel.h>
34#include <sys/module.h>
35#include <sys/malloc.h>
36#include <sys/rman.h>
37#include <sys/timeet.h>
38#include <sys/timetc.h>
39#include <sys/watchdog.h>
40#include <machine/bus.h>
41#include <machine/cpu.h>
42#include <machine/frame.h>
43#include <machine/intr.h>
44
45#include <arm/ti/tivar.h>
46#include <arm/ti/ti_scm.h>
47#include <arm/ti/ti_prcm.h>
48
49#include <dev/fdt/fdt_common.h>
50#include <dev/ofw/openfirm.h>
51#include <dev/ofw/ofw_bus.h>
52#include <dev/ofw/ofw_bus_subr.h>
53
54#include <machine/bus.h>
55#include <machine/fdt.h>
56
57#define CM_PER				0
58#define CM_PER_L4LS_CLKSTCTRL		(CM_PER + 0x000)
59#define CM_PER_L3S_CLKSTCTRL		(CM_PER + 0x004)
60#define CM_PER_L3_CLKSTCTRL		(CM_PER + 0x00C)
61#define CM_PER_CPGMAC0_CLKCTRL		(CM_PER + 0x014)
62#define CM_PER_LCDC_CLKCTRL		(CM_PER + 0x018)
63#define CM_PER_USB0_CLKCTRL		(CM_PER + 0x01C)
64#define CM_PER_TPTC0_CLKCTRL		(CM_PER + 0x024)
65#define CM_PER_UART5_CLKCTRL		(CM_PER + 0x038)
66#define CM_PER_MMC0_CLKCTRL		(CM_PER + 0x03C)
67#define CM_PER_I2C2_CLKCTRL		(CM_PER + 0x044)
68#define CM_PER_I2C1_CLKCTRL		(CM_PER + 0x048)
69#define CM_PER_UART1_CLKCTRL		(CM_PER + 0x06C)
70#define CM_PER_UART2_CLKCTRL		(CM_PER + 0x070)
71#define CM_PER_UART3_CLKCTRL		(CM_PER + 0x074)
72#define CM_PER_UART4_CLKCTRL		(CM_PER + 0x078)
73#define CM_PER_TIMER7_CLKCTRL		(CM_PER + 0x07C)
74#define CM_PER_TIMER2_CLKCTRL		(CM_PER + 0x080)
75#define CM_PER_TIMER3_CLKCTRL		(CM_PER + 0x084)
76#define CM_PER_TIMER4_CLKCTRL		(CM_PER + 0x088)
77#define CM_PER_GPIO1_CLKCTRL		(CM_PER + 0x0AC)
78#define CM_PER_GPIO2_CLKCTRL		(CM_PER + 0x0B0)
79#define CM_PER_GPIO3_CLKCTRL		(CM_PER + 0x0B4)
80#define CM_PER_TPCC_CLKCTRL		(CM_PER + 0x0BC)
81#define CM_PER_EPWMSS1_CLKCTRL		(CM_PER + 0x0CC)
82#define CM_PER_EPWMSS0_CLKCTRL		(CM_PER + 0x0D4)
83#define CM_PER_EPWMSS2_CLKCTRL		(CM_PER + 0x0D8)
84#define CM_PER_L3_INSTR_CLKCTRL		(CM_PER + 0x0DC)
85#define CM_PER_L3_CLKCTRL		(CM_PER + 0x0E0)
86#define	CM_PER_PRUSS_CLKCTRL		(CM_PER + 0x0E8)
87#define CM_PER_TIMER5_CLKCTRL		(CM_PER + 0x0EC)
88#define CM_PER_TIMER6_CLKCTRL		(CM_PER + 0x0F0)
89#define CM_PER_MMC1_CLKCTRL		(CM_PER + 0x0F4)
90#define CM_PER_MMC2_CLKCTRL		(CM_PER + 0x0F8)
91#define CM_PER_TPTC1_CLKCTRL		(CM_PER + 0x0FC)
92#define CM_PER_TPTC2_CLKCTRL		(CM_PER + 0x100)
93#define	CM_PER_SPINLOCK0_CLKCTRL	(CM_PER + 0x10C)
94#define	CM_PER_MAILBOX0_CLKCTRL		(CM_PER + 0x110)
95#define CM_PER_OCPWP_L3_CLKSTCTRL	(CM_PER + 0x12C)
96#define CM_PER_OCPWP_CLKCTRL		(CM_PER + 0x130)
97#define CM_PER_CPSW_CLKSTCTRL		(CM_PER + 0x144)
98#define	CM_PER_PRUSS_CLKSTCTRL		(CM_PER + 0x140)
99
100#define CM_WKUP				0x400
101#define CM_WKUP_CLKSTCTRL		(CM_WKUP + 0x000)
102#define CM_WKUP_CONTROL_CLKCTRL		(CM_WKUP + 0x004)
103#define CM_WKUP_GPIO0_CLKCTRL		(CM_WKUP + 0x008)
104#define CM_WKUP_CM_L3_AON_CLKSTCTRL	(CM_WKUP + 0x01C)
105#define CM_WKUP_CM_CLKSEL_DPLL_MPU	(CM_WKUP + 0x02C)
106#define CM_WKUP_CM_IDLEST_DPLL_DISP	(CM_WKUP + 0x048)
107#define CM_WKUP_CM_CLKSEL_DPLL_DISP	(CM_WKUP + 0x054)
108#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER	(CM_WKUP + 0x07C)
109#define CM_WKUP_CM_CLKMODE_DPLL_DISP	(CM_WKUP + 0x098)
110#define CM_WKUP_I2C0_CLKCTRL		(CM_WKUP + 0x0B8)
111
112#define CM_DPLL				0x500
113#define CLKSEL_TIMER7_CLK		(CM_DPLL + 0x004)
114#define CLKSEL_TIMER2_CLK		(CM_DPLL + 0x008)
115#define CLKSEL_TIMER3_CLK		(CM_DPLL + 0x00C)
116#define CLKSEL_TIMER4_CLK		(CM_DPLL + 0x010)
117#define CLKSEL_TIMER5_CLK		(CM_DPLL + 0x018)
118#define CLKSEL_TIMER6_CLK		(CM_DPLL + 0x01C)
119#define	CLKSEL_PRUSS_OCP_CLK		(CM_DPLL + 0x030)
120
121#define	PRM_PER				0xC00
122#define	PRM_PER_RSTCTRL			(PRM_PER + 0x00)
123
124#define PRM_DEVICE_OFFSET		0xF00
125#define PRM_RSTCTRL			(PRM_DEVICE_OFFSET + 0x00)
126
127struct am335x_prcm_softc {
128	struct resource *	res[2];
129	bus_space_tag_t		bst;
130	bus_space_handle_t	bsh;
131};
132
133static struct resource_spec am335x_prcm_spec[] = {
134	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
135	{ -1, 0 }
136};
137
138static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
139
140static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
141static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
142static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
143static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
144static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
145static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
146static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
147static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq);
148static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
149static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
150static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
151static void am335x_prcm_reset(void);
152static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
153static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
154static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
155static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
156
157#define AM335X_NOOP_CLOCK_DEV(i) \
158	{	.id = (i), \
159		.clk_activate = am335x_clk_noop_activate, \
160		.clk_deactivate = am335x_clk_noop_deactivate, \
161		.clk_set_source = am335x_clk_noop_set_source, \
162		.clk_accessible = NULL, \
163		.clk_get_source_freq = NULL \
164	}
165
166#define AM335X_GENERIC_CLOCK_DEV(i) \
167	{	.id = (i), \
168		.clk_activate = am335x_clk_generic_activate, \
169		.clk_deactivate = am335x_clk_generic_deactivate, \
170		.clk_set_source = am335x_clk_generic_set_source, \
171		.clk_accessible = NULL, \
172		.clk_get_source_freq = NULL \
173	}
174
175#define AM335X_GPIO_CLOCK_DEV(i) \
176	{	.id = (i), \
177		.clk_activate = am335x_clk_gpio_activate, \
178		.clk_deactivate = am335x_clk_generic_deactivate, \
179		.clk_set_source = am335x_clk_generic_set_source, \
180		.clk_accessible = NULL, \
181		.clk_get_source_freq = NULL \
182	}
183
184#define AM335X_MMCHS_CLOCK_DEV(i) \
185	{	.id = (i), \
186		.clk_activate = am335x_clk_generic_activate, \
187		.clk_deactivate = am335x_clk_generic_deactivate, \
188		.clk_set_source = am335x_clk_generic_set_source, \
189		.clk_accessible = NULL, \
190		.clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \
191	}
192
193struct ti_clock_dev ti_clk_devmap[] = {
194	/* System clocks */
195	{	.id                  = SYS_CLK,
196		.clk_activate        = NULL,
197		.clk_deactivate      = NULL,
198		.clk_set_source      = NULL,
199		.clk_accessible      = NULL,
200		.clk_get_source_freq = am335x_clk_get_sysclk_freq,
201	},
202	/* MPU (ARM) core clocks */
203	{	.id                  = MPU_CLK,
204		.clk_activate        = NULL,
205		.clk_deactivate      = NULL,
206		.clk_set_source      = NULL,
207		.clk_accessible      = NULL,
208		.clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
209	},
210	/* CPSW Ethernet Switch core clocks */
211	{	.id                  = CPSW_CLK,
212		.clk_activate        = am335x_clk_cpsw_activate,
213		.clk_deactivate      = NULL,
214		.clk_set_source      = NULL,
215		.clk_accessible      = NULL,
216		.clk_get_source_freq = NULL,
217	},
218
219	/* Mentor USB HS controller core clocks */
220	{	.id                  = MUSB0_CLK,
221		.clk_activate        = am335x_clk_musb0_activate,
222		.clk_deactivate      = NULL,
223		.clk_set_source      = NULL,
224		.clk_accessible      = NULL,
225		.clk_get_source_freq = NULL,
226	},
227
228	/* LCD controller clocks */
229	{	.id                  = LCDC_CLK,
230		.clk_activate        = am335x_clk_lcdc_activate,
231		.clk_deactivate      = NULL,
232		.clk_set_source      = NULL,
233		.clk_accessible      = NULL,
234		.clk_get_source_freq = am335x_clk_get_arm_disp_freq,
235	},
236
237        /* UART.  Uart0 clock cannot be controlled. */
238	AM335X_NOOP_CLOCK_DEV(UART0_CLK),
239	AM335X_GENERIC_CLOCK_DEV(UART1_CLK),
240	AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
241	AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
242	AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
243	AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
244
245	/* DMTimer */
246	AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK),
247	AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK),
248	AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK),
249	AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK),
250	AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK),
251	AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK),
252
253	/* GPIO */
254	AM335X_GPIO_CLOCK_DEV(GPIO0_CLK),
255	AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
256	AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
257	AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
258
259	/* I2C */
260	AM335X_GENERIC_CLOCK_DEV(I2C0_CLK),
261	AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
262	AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
263
264	/* EDMA */
265	AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
266	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
267	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
268	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
269
270	/* MMCHS */
271	AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
272	AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
273	AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
274
275	/* PWMSS */
276	AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
277	AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
278	AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
279
280	/* System Mailbox clock */
281	AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
282
283	/* SPINLOCK */
284	AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
285
286	/* PRU-ICSS */
287	{	.id		     = PRUSS_CLK,
288		.clk_activate	     = am335x_clk_pruss_activate,
289		.clk_deactivate      = NULL,
290		.clk_set_source      = NULL,
291		.clk_accessible      = NULL,
292		.clk_get_source_freq = NULL,
293	},
294
295
296
297	{  INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
298};
299
300struct am335x_clk_details {
301	clk_ident_t	id;
302	uint32_t	clkctrl_reg;
303	uint32_t	clksel_reg;
304};
305
306#define _CLK_DETAIL(i, c, s) \
307	{	.id = (i), \
308		.clkctrl_reg = (c), \
309		.clksel_reg = (s), \
310	}
311
312static struct am335x_clk_details g_am335x_clk_details[] = {
313
314        /* UART. UART0 clock not controllable. */
315	_CLK_DETAIL(UART0_CLK, 0, 0),
316	_CLK_DETAIL(UART1_CLK, CM_PER_UART1_CLKCTRL, 0),
317	_CLK_DETAIL(UART2_CLK, CM_PER_UART2_CLKCTRL, 0),
318	_CLK_DETAIL(UART3_CLK, CM_PER_UART3_CLKCTRL, 0),
319	_CLK_DETAIL(UART4_CLK, CM_PER_UART4_CLKCTRL, 0),
320	_CLK_DETAIL(UART5_CLK, CM_PER_UART5_CLKCTRL, 0),
321
322	/* DMTimer modules */
323	_CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
324	_CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
325	_CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
326	_CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
327	_CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
328	_CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
329
330	/* GPIO modules */
331	_CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
332	_CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0),
333	_CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0),
334	_CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0),
335
336	/* I2C modules */
337	_CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
338	_CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0),
339	_CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0),
340
341	/* EDMA modules */
342	_CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
343	_CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
344	_CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
345	_CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
346
347	/* MMCHS modules*/
348	_CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0),
349	_CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0),
350	_CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
351
352	/* PWMSS modules */
353	_CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
354	_CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
355	_CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
356
357	_CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
358	_CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
359
360	{ INVALID_CLK_IDENT, 0},
361};
362
363/* Read/Write macros */
364#define prcm_read_4(reg)		\
365	bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
366#define prcm_write_4(reg, val)		\
367	bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
368
369void am335x_prcm_setup_dmtimer(int);
370
371static int
372am335x_prcm_probe(device_t dev)
373{
374	if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
375		device_set_desc(dev, "AM335x Power and Clock Management");
376		return(BUS_PROBE_DEFAULT);
377	}
378
379	return (ENXIO);
380}
381
382static int
383am335x_prcm_attach(device_t dev)
384{
385	struct am335x_prcm_softc *sc = device_get_softc(dev);
386	unsigned int sysclk, fclk;
387
388	if (am335x_prcm_sc)
389		return (ENXIO);
390
391	if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
392		device_printf(dev, "could not allocate resources\n");
393		return (ENXIO);
394	}
395
396	sc->bst = rman_get_bustag(sc->res[0]);
397	sc->bsh = rman_get_bushandle(sc->res[0]);
398
399	am335x_prcm_sc = sc;
400	ti_cpu_reset = am335x_prcm_reset;
401
402	am335x_clk_get_sysclk_freq(NULL, &sysclk);
403	am335x_clk_get_arm_fclk_freq(NULL, &fclk);
404	device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
405		sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
406
407	return (0);
408}
409
410static device_method_t am335x_prcm_methods[] = {
411	DEVMETHOD(device_probe,		am335x_prcm_probe),
412	DEVMETHOD(device_attach,	am335x_prcm_attach),
413	{ 0, 0 }
414};
415
416static driver_t am335x_prcm_driver = {
417	"am335x_prcm",
418	am335x_prcm_methods,
419	sizeof(struct am335x_prcm_softc),
420};
421
422static devclass_t am335x_prcm_devclass;
423
424DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
425	am335x_prcm_devclass, 0, 0);
426MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
427
428static struct am335x_clk_details*
429am335x_clk_details(clk_ident_t id)
430{
431	struct am335x_clk_details *walker;
432
433	for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
434		if (id == walker->id)
435			return (walker);
436	}
437
438	return NULL;
439}
440
441static int
442am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
443{
444
445	return (0);
446}
447
448static int
449am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
450{
451	struct am335x_prcm_softc *sc = am335x_prcm_sc;
452	struct am335x_clk_details* clk_details;
453
454	if (sc == NULL)
455		return ENXIO;
456
457	clk_details = am335x_clk_details(clkdev->id);
458
459	if (clk_details == NULL)
460		return (ENXIO);
461
462	/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
463	prcm_write_4(clk_details->clkctrl_reg, 2);
464	while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
465		DELAY(10);
466
467	return (0);
468}
469
470static int
471am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
472{
473	struct am335x_prcm_softc *sc = am335x_prcm_sc;
474	struct am335x_clk_details* clk_details;
475
476	if (sc == NULL)
477		return ENXIO;
478
479	clk_details = am335x_clk_details(clkdev->id);
480
481	if (clk_details == NULL)
482		return (ENXIO);
483
484	/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
485	/* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
486	prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
487	while ((prcm_read_4(clk_details->clkctrl_reg) &
488	    (3 | (1 << 18) )) != (2 | (1 << 18)))
489		DELAY(10);
490
491	return (0);
492}
493
494static int
495am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
496{
497
498	return(0);
499}
500
501static int
502am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
503{
504	struct am335x_prcm_softc *sc = am335x_prcm_sc;
505	struct am335x_clk_details* clk_details;
506
507	if (sc == NULL)
508		return ENXIO;
509
510	clk_details = am335x_clk_details(clkdev->id);
511
512	if (clk_details == NULL)
513		return (ENXIO);
514
515	/* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
516	prcm_write_4(clk_details->clkctrl_reg, 0);
517	while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
518		DELAY(10);
519
520	return (0);
521}
522
523static int
524am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
525{
526
527	return (0);
528}
529
530static int
531am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
532{
533	struct am335x_prcm_softc *sc = am335x_prcm_sc;
534	struct am335x_clk_details* clk_details;
535	uint32_t reg;
536
537	if (sc == NULL)
538		return ENXIO;
539
540	clk_details = am335x_clk_details(clkdev->id);
541
542	if (clk_details == NULL)
543		return (ENXIO);
544
545	switch (clksrc) {
546		case EXT_CLK:
547			reg = 0; /* SEL2: TCLKIN clock */
548			break;
549		case SYSCLK_CLK:
550			reg = 1; /* SEL1: CLK_M_OSC clock */
551			break;
552		case F32KHZ_CLK:
553			reg = 2; /* SEL3: CLK_32KHZ clock */
554			break;
555		default:
556			return (ENXIO);
557	}
558
559	prcm_write_4(clk_details->clksel_reg, reg);
560	while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
561		DELAY(10);
562
563	return (0);
564}
565
566static int
567am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq)
568{
569	*freq = 96000000;
570	return (0);
571}
572
573static int
574am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
575{
576	uint32_t ctrl_status;
577
578	/* Read the input clock freq from the control module */
579	/* control_status reg (0x40) */
580	if (ti_scm_reg_read_4(0x40, &ctrl_status))
581		return ENXIO;
582
583	switch ((ctrl_status>>22) & 0x3) {
584	case 0x0:
585		/* 19.2Mhz */
586		*freq = 19200000;
587		break;
588	case 0x1:
589		/* 24Mhz */
590		*freq = 24000000;
591		break;
592	case 0x2:
593		/* 25Mhz */
594		*freq = 25000000;
595		break;
596	case 0x3:
597		/* 26Mhz */
598		*freq = 26000000;
599		break;
600	}
601
602	return (0);
603}
604
605#define DPLL_BYP_CLKSEL(reg)	((reg>>23) & 1)
606#define DPLL_DIV(reg)		((reg & 0x7f)+1)
607#define DPLL_MULT(reg)		((reg>>8) & 0x7FF)
608
609static int
610am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
611{
612	uint32_t reg;
613	uint32_t sysclk;
614
615	reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
616
617	/*Check if we are running in bypass */
618	if (DPLL_BYP_CLKSEL(reg))
619		return ENXIO;
620
621	am335x_clk_get_sysclk_freq(NULL, &sysclk);
622	*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
623	return(0);
624}
625
626static int
627am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
628{
629	uint32_t reg;
630	uint32_t sysclk;
631
632	reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
633
634	/*Check if we are running in bypass */
635	if (DPLL_BYP_CLKSEL(reg))
636		return ENXIO;
637
638	am335x_clk_get_sysclk_freq(NULL, &sysclk);
639	*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
640	return(0);
641}
642
643static void
644am335x_prcm_reset(void)
645{
646	prcm_write_4(PRM_RSTCTRL, (1<<1));
647}
648
649static int
650am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
651{
652	struct am335x_prcm_softc *sc = am335x_prcm_sc;
653
654	if (sc == NULL)
655		return ENXIO;
656
657	/* set MODULENAME to ENABLE */
658	prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
659
660	/* wait for IDLEST to become Func(0) */
661	while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
662
663	/*set CLKTRCTRL to SW_WKUP(2) */
664	prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
665
666	/* wait for 125 MHz OCP clock to become active */
667	while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
668	return(0);
669}
670
671static int
672am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
673{
674	struct am335x_prcm_softc *sc = am335x_prcm_sc;
675
676	if (sc == NULL)
677		return ENXIO;
678
679	/* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
680	/* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
681        prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
682
683	/*set MODULEMODE to ENABLE(2) */
684	prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
685
686	/* wait for MODULEMODE to become ENABLE(2) */
687	while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
688		DELAY(10);
689
690	/* wait for IDLEST to become Func(0) */
691	while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
692		DELAY(10);
693
694	return(0);
695}
696
697static int
698am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
699{
700	struct am335x_prcm_softc *sc = am335x_prcm_sc;
701
702	if (sc == NULL)
703		return (ENXIO);
704
705	/* Bypass mode */
706	prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
707
708	/* Make sure it's in bypass mode */
709	while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
710	    & (1 << 8)))
711		DELAY(10);
712
713	/*
714	 * For now set frequency to  5xSYSFREQ
715	 * More flexible control might be required
716	 */
717	prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0);
718
719	/* Locked mode */
720	prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
721
722	int timeout = 10000;
723	while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
724	    & (1 << 0))) && timeout--)
725		DELAY(10);
726
727	/*set MODULEMODE to ENABLE(2) */
728	prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
729
730	/* wait for MODULEMODE to become ENABLE(2) */
731	while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
732		DELAY(10);
733
734	/* wait for IDLEST to become Func(0) */
735	while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
736		DELAY(10);
737
738	return (0);
739}
740
741static int
742am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
743{
744	struct am335x_prcm_softc *sc = am335x_prcm_sc;
745
746	if (sc == NULL)
747		return (ENXIO);
748
749	/* Set MODULEMODE to ENABLE(2) */
750	prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
751
752	/* Wait for MODULEMODE to become ENABLE(2) */
753	while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
754		DELAY(10);
755
756	/* Set CLKTRCTRL to SW_WKUP(2) */
757	prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
758
759	/* Wait for the 200 MHz OCP clock to become active */
760	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
761		DELAY(10);
762
763	/* Wait for the 200 MHz IEP clock to become active */
764	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
765		DELAY(10);
766
767	/* Wait for the 192 MHz UART clock to become active */
768	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
769		DELAY(10);
770
771	/* Select DISP DPLL as OCP clock */
772	prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 1);
773	while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 1)
774		DELAY(10);
775
776	/* Clear the RESET bit */
777	prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
778
779	return (0);
780}
781