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