am335x_prcm.c revision 278061
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 278061 2015-02-02 08:01:10Z rpaulo $");
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/intr.h>
43
44#include <arm/ti/tivar.h>
45#include <arm/ti/ti_scm.h>
46#include <arm/ti/ti_prcm.h>
47
48#include <dev/fdt/fdt_common.h>
49#include <dev/ofw/openfirm.h>
50#include <dev/ofw/ofw_bus.h>
51#include <dev/ofw/ofw_bus_subr.h>
52
53#include <machine/bus.h>
54#include <machine/fdt.h>
55
56#define CM_PER				0
57#define CM_PER_L4LS_CLKSTCTRL		(CM_PER + 0x000)
58#define CM_PER_L3S_CLKSTCTRL		(CM_PER + 0x004)
59#define CM_PER_L3_CLKSTCTRL		(CM_PER + 0x00C)
60#define CM_PER_CPGMAC0_CLKCTRL		(CM_PER + 0x014)
61#define CM_PER_LCDC_CLKCTRL		(CM_PER + 0x018)
62#define CM_PER_USB0_CLKCTRL		(CM_PER + 0x01C)
63#define CM_PER_TPTC0_CLKCTRL		(CM_PER + 0x024)
64#define CM_PER_UART5_CLKCTRL		(CM_PER + 0x038)
65#define CM_PER_MMC0_CLKCTRL		(CM_PER + 0x03C)
66#define CM_PER_I2C2_CLKCTRL		(CM_PER + 0x044)
67#define CM_PER_I2C1_CLKCTRL		(CM_PER + 0x048)
68#define CM_PER_UART1_CLKCTRL		(CM_PER + 0x06C)
69#define CM_PER_UART2_CLKCTRL		(CM_PER + 0x070)
70#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#define CM_WKUP_ADC_TSC_CLKCTRL		(CM_WKUP + 0x0BC)
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	CM_RTC				0x800
122#define	CM_RTC_RTC_CLKCTRL		(CM_RTC + 0x000)
123#define	CM_RTC_CLKSTCTRL		(CM_RTC + 0x004)
124
125#define	PRM_PER				0xC00
126#define	PRM_PER_RSTCTRL			(PRM_PER + 0x00)
127
128#define PRM_DEVICE_OFFSET		0xF00
129#define PRM_RSTCTRL			(PRM_DEVICE_OFFSET + 0x00)
130
131struct am335x_prcm_softc {
132	struct resource *	res[2];
133	bus_space_tag_t		bst;
134	bus_space_handle_t	bsh;
135};
136
137static struct resource_spec am335x_prcm_spec[] = {
138	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
139	{ -1, 0 }
140};
141
142static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
143
144static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
145static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
146static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
147static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
148static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
149static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
150static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
151static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq);
152static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
153static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
154static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
155static void am335x_prcm_reset(void);
156static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
157static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
158static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
159static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
160
161#define AM335X_NOOP_CLOCK_DEV(i) \
162	{	.id = (i), \
163		.clk_activate = am335x_clk_noop_activate, \
164		.clk_deactivate = am335x_clk_noop_deactivate, \
165		.clk_set_source = am335x_clk_noop_set_source, \
166		.clk_accessible = NULL, \
167		.clk_get_source_freq = NULL \
168	}
169
170#define AM335X_GENERIC_CLOCK_DEV(i) \
171	{	.id = (i), \
172		.clk_activate = am335x_clk_generic_activate, \
173		.clk_deactivate = am335x_clk_generic_deactivate, \
174		.clk_set_source = am335x_clk_generic_set_source, \
175		.clk_accessible = NULL, \
176		.clk_get_source_freq = NULL \
177	}
178
179#define AM335X_GPIO_CLOCK_DEV(i) \
180	{	.id = (i), \
181		.clk_activate = am335x_clk_gpio_activate, \
182		.clk_deactivate = am335x_clk_generic_deactivate, \
183		.clk_set_source = am335x_clk_generic_set_source, \
184		.clk_accessible = NULL, \
185		.clk_get_source_freq = NULL \
186	}
187
188#define AM335X_MMCHS_CLOCK_DEV(i) \
189	{	.id = (i), \
190		.clk_activate = am335x_clk_generic_activate, \
191		.clk_deactivate = am335x_clk_generic_deactivate, \
192		.clk_set_source = am335x_clk_generic_set_source, \
193		.clk_accessible = NULL, \
194		.clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \
195	}
196
197struct ti_clock_dev ti_am335x_clk_devmap[] = {
198	/* System clocks */
199	{	.id                  = SYS_CLK,
200		.clk_activate        = NULL,
201		.clk_deactivate      = NULL,
202		.clk_set_source      = NULL,
203		.clk_accessible      = NULL,
204		.clk_get_source_freq = am335x_clk_get_sysclk_freq,
205	},
206	/* MPU (ARM) core clocks */
207	{	.id                  = MPU_CLK,
208		.clk_activate        = NULL,
209		.clk_deactivate      = NULL,
210		.clk_set_source      = NULL,
211		.clk_accessible      = NULL,
212		.clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
213	},
214	/* CPSW Ethernet Switch core clocks */
215	{	.id                  = CPSW_CLK,
216		.clk_activate        = am335x_clk_cpsw_activate,
217		.clk_deactivate      = NULL,
218		.clk_set_source      = NULL,
219		.clk_accessible      = NULL,
220		.clk_get_source_freq = NULL,
221	},
222
223	/* Mentor USB HS controller core clocks */
224	{	.id                  = MUSB0_CLK,
225		.clk_activate        = am335x_clk_musb0_activate,
226		.clk_deactivate      = NULL,
227		.clk_set_source      = NULL,
228		.clk_accessible      = NULL,
229		.clk_get_source_freq = NULL,
230	},
231
232	/* LCD controller clocks */
233	{	.id                  = LCDC_CLK,
234		.clk_activate        = am335x_clk_lcdc_activate,
235		.clk_deactivate      = NULL,
236		.clk_set_source      = NULL,
237		.clk_accessible      = NULL,
238		.clk_get_source_freq = am335x_clk_get_arm_disp_freq,
239	},
240
241        /* UART.  Uart0 clock cannot be controlled. */
242	AM335X_NOOP_CLOCK_DEV(UART0_CLK),
243	AM335X_GENERIC_CLOCK_DEV(UART1_CLK),
244	AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
245	AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
246	AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
247	AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
248
249	/* DMTimer */
250	AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK),
251	AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK),
252	AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK),
253	AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK),
254	AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK),
255	AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK),
256
257	/* GPIO */
258	AM335X_GPIO_CLOCK_DEV(GPIO0_CLK),
259	AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
260	AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
261	AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
262
263	/* I2C */
264	AM335X_GENERIC_CLOCK_DEV(I2C0_CLK),
265	AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
266	AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
267
268	/* TSC_ADC */
269	AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
270
271	/* EDMA */
272	AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
273	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
274	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
275	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
276
277	/* MMCHS */
278	AM335X_MMCHS_CLOCK_DEV(MMC0_CLK),
279	AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
280	AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
281
282	/* PWMSS */
283	AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
284	AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
285	AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
286
287	/* System Mailbox clock */
288	AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
289
290	/* SPINLOCK */
291	AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
292
293	/* PRU-ICSS */
294	{	.id		     = PRUSS_CLK,
295		.clk_activate	     = am335x_clk_pruss_activate,
296		.clk_deactivate      = NULL,
297		.clk_set_source      = NULL,
298		.clk_accessible      = NULL,
299		.clk_get_source_freq = NULL,
300	},
301
302	/* RTC */
303	AM335X_GENERIC_CLOCK_DEV(RTC_CLK),
304
305	{  INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
306};
307
308struct am335x_clk_details {
309	clk_ident_t	id;
310	uint32_t	clkctrl_reg;
311	uint32_t	clksel_reg;
312};
313
314#define _CLK_DETAIL(i, c, s) \
315	{	.id = (i), \
316		.clkctrl_reg = (c), \
317		.clksel_reg = (s), \
318	}
319
320static struct am335x_clk_details g_am335x_clk_details[] = {
321
322        /* UART. UART0 clock not controllable. */
323	_CLK_DETAIL(UART0_CLK, 0, 0),
324	_CLK_DETAIL(UART1_CLK, CM_PER_UART1_CLKCTRL, 0),
325	_CLK_DETAIL(UART2_CLK, CM_PER_UART2_CLKCTRL, 0),
326	_CLK_DETAIL(UART3_CLK, CM_PER_UART3_CLKCTRL, 0),
327	_CLK_DETAIL(UART4_CLK, CM_PER_UART4_CLKCTRL, 0),
328	_CLK_DETAIL(UART5_CLK, CM_PER_UART5_CLKCTRL, 0),
329
330	/* DMTimer modules */
331	_CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
332	_CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
333	_CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
334	_CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
335	_CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
336	_CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
337
338	/* GPIO modules */
339	_CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
340	_CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0),
341	_CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0),
342	_CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0),
343
344	/* I2C modules */
345	_CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
346	_CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0),
347	_CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0),
348
349	/* TSC_ADC module */
350	_CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
351
352	/* EDMA modules */
353	_CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
354	_CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
355	_CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
356	_CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
357
358	/* MMCHS modules*/
359	_CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0),
360	_CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0),
361	_CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
362
363	/* PWMSS modules */
364	_CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
365	_CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
366	_CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
367
368	_CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
369	_CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
370
371	/* RTC module */
372	_CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0),
373
374	{ INVALID_CLK_IDENT, 0},
375};
376
377/* Read/Write macros */
378#define prcm_read_4(reg)		\
379	bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
380#define prcm_write_4(reg, val)		\
381	bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
382
383void am335x_prcm_setup_dmtimer(int);
384
385static int
386am335x_prcm_probe(device_t dev)
387{
388
389	if (!ofw_bus_status_okay(dev))
390		return (ENXIO);
391
392	if (ofw_bus_is_compatible(dev, "am335x,prcm")) {
393		device_set_desc(dev, "AM335x Power and Clock Management");
394		return(BUS_PROBE_DEFAULT);
395	}
396
397	return (ENXIO);
398}
399
400static int
401am335x_prcm_attach(device_t dev)
402{
403	struct am335x_prcm_softc *sc = device_get_softc(dev);
404	unsigned int sysclk, fclk;
405
406	if (am335x_prcm_sc)
407		return (ENXIO);
408
409	if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
410		device_printf(dev, "could not allocate resources\n");
411		return (ENXIO);
412	}
413
414	sc->bst = rman_get_bustag(sc->res[0]);
415	sc->bsh = rman_get_bushandle(sc->res[0]);
416
417	am335x_prcm_sc = sc;
418	ti_cpu_reset = am335x_prcm_reset;
419
420	am335x_clk_get_sysclk_freq(NULL, &sysclk);
421	am335x_clk_get_arm_fclk_freq(NULL, &fclk);
422	device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
423		sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
424
425	return (0);
426}
427
428static device_method_t am335x_prcm_methods[] = {
429	DEVMETHOD(device_probe,		am335x_prcm_probe),
430	DEVMETHOD(device_attach,	am335x_prcm_attach),
431	{ 0, 0 }
432};
433
434static driver_t am335x_prcm_driver = {
435	"am335x_prcm",
436	am335x_prcm_methods,
437	sizeof(struct am335x_prcm_softc),
438};
439
440static devclass_t am335x_prcm_devclass;
441
442DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
443	am335x_prcm_devclass, 0, 0);
444MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
445
446static struct am335x_clk_details*
447am335x_clk_details(clk_ident_t id)
448{
449	struct am335x_clk_details *walker;
450
451	for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
452		if (id == walker->id)
453			return (walker);
454	}
455
456	return NULL;
457}
458
459static int
460am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
461{
462
463	return (0);
464}
465
466static int
467am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
468{
469	struct am335x_prcm_softc *sc = am335x_prcm_sc;
470	struct am335x_clk_details* clk_details;
471
472	if (sc == NULL)
473		return ENXIO;
474
475	clk_details = am335x_clk_details(clkdev->id);
476
477	if (clk_details == NULL)
478		return (ENXIO);
479
480	/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
481	prcm_write_4(clk_details->clkctrl_reg, 2);
482	while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
483		DELAY(10);
484
485	return (0);
486}
487
488static int
489am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
490{
491	struct am335x_prcm_softc *sc = am335x_prcm_sc;
492	struct am335x_clk_details* clk_details;
493
494	if (sc == NULL)
495		return ENXIO;
496
497	clk_details = am335x_clk_details(clkdev->id);
498
499	if (clk_details == NULL)
500		return (ENXIO);
501
502	/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
503	/* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
504	prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
505	while ((prcm_read_4(clk_details->clkctrl_reg) &
506	    (3 | (1 << 18) )) != (2 | (1 << 18)))
507		DELAY(10);
508
509	return (0);
510}
511
512static int
513am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
514{
515
516	return(0);
517}
518
519static int
520am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
521{
522	struct am335x_prcm_softc *sc = am335x_prcm_sc;
523	struct am335x_clk_details* clk_details;
524
525	if (sc == NULL)
526		return ENXIO;
527
528	clk_details = am335x_clk_details(clkdev->id);
529
530	if (clk_details == NULL)
531		return (ENXIO);
532
533	/* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
534	prcm_write_4(clk_details->clkctrl_reg, 0);
535	while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
536		DELAY(10);
537
538	return (0);
539}
540
541static int
542am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
543{
544
545	return (0);
546}
547
548static int
549am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
550{
551	struct am335x_prcm_softc *sc = am335x_prcm_sc;
552	struct am335x_clk_details* clk_details;
553	uint32_t reg;
554
555	if (sc == NULL)
556		return ENXIO;
557
558	clk_details = am335x_clk_details(clkdev->id);
559
560	if (clk_details == NULL)
561		return (ENXIO);
562
563	switch (clksrc) {
564		case EXT_CLK:
565			reg = 0; /* SEL2: TCLKIN clock */
566			break;
567		case SYSCLK_CLK:
568			reg = 1; /* SEL1: CLK_M_OSC clock */
569			break;
570		case F32KHZ_CLK:
571			reg = 2; /* SEL3: CLK_32KHZ clock */
572			break;
573		default:
574			return (ENXIO);
575	}
576
577	prcm_write_4(clk_details->clksel_reg, reg);
578	while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
579		DELAY(10);
580
581	return (0);
582}
583
584static int
585am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq)
586{
587	*freq = 96000000;
588	return (0);
589}
590
591static int
592am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
593{
594	uint32_t ctrl_status;
595
596	/* Read the input clock freq from the control module */
597	/* control_status reg (0x40) */
598	if (ti_scm_reg_read_4(0x40, &ctrl_status))
599		return ENXIO;
600
601	switch ((ctrl_status>>22) & 0x3) {
602	case 0x0:
603		/* 19.2Mhz */
604		*freq = 19200000;
605		break;
606	case 0x1:
607		/* 24Mhz */
608		*freq = 24000000;
609		break;
610	case 0x2:
611		/* 25Mhz */
612		*freq = 25000000;
613		break;
614	case 0x3:
615		/* 26Mhz */
616		*freq = 26000000;
617		break;
618	}
619
620	return (0);
621}
622
623#define DPLL_BYP_CLKSEL(reg)	((reg>>23) & 1)
624#define DPLL_DIV(reg)		((reg & 0x7f)+1)
625#define DPLL_MULT(reg)		((reg>>8) & 0x7FF)
626
627static int
628am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
629{
630	uint32_t reg;
631	uint32_t sysclk;
632
633	reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
634
635	/*Check if we are running in bypass */
636	if (DPLL_BYP_CLKSEL(reg))
637		return ENXIO;
638
639	am335x_clk_get_sysclk_freq(NULL, &sysclk);
640	*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
641	return(0);
642}
643
644static int
645am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
646{
647	uint32_t reg;
648	uint32_t sysclk;
649
650	reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
651
652	/*Check if we are running in bypass */
653	if (DPLL_BYP_CLKSEL(reg))
654		return ENXIO;
655
656	am335x_clk_get_sysclk_freq(NULL, &sysclk);
657	*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
658	return(0);
659}
660
661static void
662am335x_prcm_reset(void)
663{
664	prcm_write_4(PRM_RSTCTRL, (1<<1));
665}
666
667static int
668am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
669{
670	struct am335x_prcm_softc *sc = am335x_prcm_sc;
671
672	if (sc == NULL)
673		return ENXIO;
674
675	/* set MODULENAME to ENABLE */
676	prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
677
678	/* wait for IDLEST to become Func(0) */
679	while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
680
681	/*set CLKTRCTRL to SW_WKUP(2) */
682	prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
683
684	/* wait for 125 MHz OCP clock to become active */
685	while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
686	return(0);
687}
688
689static int
690am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
691{
692	struct am335x_prcm_softc *sc = am335x_prcm_sc;
693
694	if (sc == NULL)
695		return ENXIO;
696
697	/* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
698	/* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
699        prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
700
701	/*set MODULEMODE to ENABLE(2) */
702	prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
703
704	/* wait for MODULEMODE to become ENABLE(2) */
705	while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
706		DELAY(10);
707
708	/* wait for IDLEST to become Func(0) */
709	while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
710		DELAY(10);
711
712	return(0);
713}
714
715static int
716am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
717{
718	struct am335x_prcm_softc *sc = am335x_prcm_sc;
719
720	if (sc == NULL)
721		return (ENXIO);
722
723	/* Bypass mode */
724	prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
725
726	/* Make sure it's in bypass mode */
727	while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
728	    & (1 << 8)))
729		DELAY(10);
730
731	/*
732	 * For now set frequency to  99*SYSFREQ/8 which is twice as
733	 * HDMI 1080p pixel clock (minimum LCDC freq divisor is 2)
734	 */
735	prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (99 << 8) | 8);
736
737	/* Locked mode */
738	prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
739
740	int timeout = 10000;
741	while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
742	    & (1 << 0))) && timeout--)
743		DELAY(10);
744
745	/*set MODULEMODE to ENABLE(2) */
746	prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
747
748	/* wait for MODULEMODE to become ENABLE(2) */
749	while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
750		DELAY(10);
751
752	/* wait for IDLEST to become Func(0) */
753	while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
754		DELAY(10);
755
756	return (0);
757}
758
759static int
760am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
761{
762	struct am335x_prcm_softc *sc = am335x_prcm_sc;
763
764	if (sc == NULL)
765		return (ENXIO);
766
767	/* Set MODULEMODE to ENABLE(2) */
768	prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
769
770	/* Wait for MODULEMODE to become ENABLE(2) */
771	while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
772		DELAY(10);
773
774	/* Set CLKTRCTRL to SW_WKUP(2) */
775	prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
776
777	/* Wait for the 200 MHz OCP clock to become active */
778	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
779		DELAY(10);
780
781	/* Wait for the 200 MHz IEP clock to become active */
782	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
783		DELAY(10);
784
785	/* Wait for the 192 MHz UART clock to become active */
786	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
787		DELAY(10);
788
789	/* Select L3F as OCP clock */
790	prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0);
791	while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0)
792		DELAY(10);
793
794	/* Clear the RESET bit */
795	prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
796
797	return (0);
798}
799