am335x_prcm.c revision 323470
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: stable/11/sys/arm/ti/am335x/am335x_prcm.c 323470 2017-09-11 22:33:29Z 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/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
55#include "am335x_scm.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_SPI0_CLKCTRL		(CM_PER + 0x04C)
70#define CM_PER_SPI1_CLKCTRL		(CM_PER + 0x050)
71#define CM_PER_UART1_CLKCTRL		(CM_PER + 0x06C)
72#define CM_PER_UART2_CLKCTRL		(CM_PER + 0x070)
73#define CM_PER_UART3_CLKCTRL		(CM_PER + 0x074)
74#define CM_PER_UART4_CLKCTRL		(CM_PER + 0x078)
75#define CM_PER_TIMER7_CLKCTRL		(CM_PER + 0x07C)
76#define CM_PER_TIMER2_CLKCTRL		(CM_PER + 0x080)
77#define CM_PER_TIMER3_CLKCTRL		(CM_PER + 0x084)
78#define CM_PER_TIMER4_CLKCTRL		(CM_PER + 0x088)
79#define CM_PER_GPIO1_CLKCTRL		(CM_PER + 0x0AC)
80#define CM_PER_GPIO2_CLKCTRL		(CM_PER + 0x0B0)
81#define CM_PER_GPIO3_CLKCTRL		(CM_PER + 0x0B4)
82#define CM_PER_TPCC_CLKCTRL		(CM_PER + 0x0BC)
83#define CM_PER_EPWMSS1_CLKCTRL		(CM_PER + 0x0CC)
84#define CM_PER_EPWMSS0_CLKCTRL		(CM_PER + 0x0D4)
85#define CM_PER_EPWMSS2_CLKCTRL		(CM_PER + 0x0D8)
86#define CM_PER_L3_INSTR_CLKCTRL		(CM_PER + 0x0DC)
87#define CM_PER_L3_CLKCTRL		(CM_PER + 0x0E0)
88#define	CM_PER_PRUSS_CLKCTRL		(CM_PER + 0x0E8)
89#define CM_PER_TIMER5_CLKCTRL		(CM_PER + 0x0EC)
90#define CM_PER_TIMER6_CLKCTRL		(CM_PER + 0x0F0)
91#define CM_PER_MMC1_CLKCTRL		(CM_PER + 0x0F4)
92#define CM_PER_MMC2_CLKCTRL		(CM_PER + 0x0F8)
93#define CM_PER_TPTC1_CLKCTRL		(CM_PER + 0x0FC)
94#define CM_PER_TPTC2_CLKCTRL		(CM_PER + 0x100)
95#define	CM_PER_SPINLOCK0_CLKCTRL	(CM_PER + 0x10C)
96#define	CM_PER_MAILBOX0_CLKCTRL		(CM_PER + 0x110)
97#define CM_PER_OCPWP_L3_CLKSTCTRL	(CM_PER + 0x12C)
98#define CM_PER_OCPWP_CLKCTRL		(CM_PER + 0x130)
99#define CM_PER_CPSW_CLKSTCTRL		(CM_PER + 0x144)
100#define	CM_PER_PRUSS_CLKSTCTRL		(CM_PER + 0x140)
101
102#define CM_WKUP				0x400
103#define CM_WKUP_CLKSTCTRL		(CM_WKUP + 0x000)
104#define CM_WKUP_CONTROL_CLKCTRL		(CM_WKUP + 0x004)
105#define CM_WKUP_GPIO0_CLKCTRL		(CM_WKUP + 0x008)
106#define CM_WKUP_CM_L3_AON_CLKSTCTRL	(CM_WKUP + 0x01C)
107#define CM_WKUP_CM_CLKSEL_DPLL_MPU	(CM_WKUP + 0x02C)
108#define CM_WKUP_CM_IDLEST_DPLL_DISP	(CM_WKUP + 0x048)
109#define CM_WKUP_CM_CLKSEL_DPLL_DISP	(CM_WKUP + 0x054)
110#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER	(CM_WKUP + 0x07C)
111#define CM_WKUP_CM_CLKMODE_DPLL_DISP	(CM_WKUP + 0x098)
112#define CM_WKUP_I2C0_CLKCTRL		(CM_WKUP + 0x0B8)
113#define CM_WKUP_ADC_TSC_CLKCTRL		(CM_WKUP + 0x0BC)
114
115#define CM_DPLL				0x500
116#define CLKSEL_TIMER7_CLK		(CM_DPLL + 0x004)
117#define CLKSEL_TIMER2_CLK		(CM_DPLL + 0x008)
118#define CLKSEL_TIMER3_CLK		(CM_DPLL + 0x00C)
119#define CLKSEL_TIMER4_CLK		(CM_DPLL + 0x010)
120#define CLKSEL_TIMER5_CLK		(CM_DPLL + 0x018)
121#define CLKSEL_TIMER6_CLK		(CM_DPLL + 0x01C)
122#define	CLKSEL_PRUSS_OCP_CLK		(CM_DPLL + 0x030)
123
124#define	CM_RTC				0x800
125#define	CM_RTC_RTC_CLKCTRL		(CM_RTC + 0x000)
126#define	CM_RTC_CLKSTCTRL		(CM_RTC + 0x004)
127
128#define	PRM_PER				0xC00
129#define	PRM_PER_RSTCTRL			(PRM_PER + 0x00)
130
131#define PRM_DEVICE_OFFSET		0xF00
132#define PRM_RSTCTRL			(PRM_DEVICE_OFFSET + 0x00)
133
134struct am335x_prcm_softc {
135	struct resource *	res[2];
136	bus_space_tag_t		bst;
137	bus_space_handle_t	bsh;
138};
139
140static struct resource_spec am335x_prcm_spec[] = {
141	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
142	{ -1, 0 }
143};
144
145static struct am335x_prcm_softc *am335x_prcm_sc = NULL;
146
147static int am335x_clk_noop_activate(struct ti_clock_dev *clkdev);
148static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev);
149static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev);
150static int am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev);
151static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev);
152static int am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
153static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc);
154static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq);
155static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
156static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
157static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq);
158static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq);
159static void am335x_prcm_reset(void);
160static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev);
161static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev);
162static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev);
163static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev);
164
165#define AM335X_NOOP_CLOCK_DEV(i) \
166	{	.id = (i), \
167		.clk_activate = am335x_clk_noop_activate, \
168		.clk_deactivate = am335x_clk_noop_deactivate, \
169		.clk_set_source = am335x_clk_noop_set_source, \
170		.clk_accessible = NULL, \
171		.clk_get_source_freq = NULL, \
172		.clk_set_source_freq = NULL \
173	}
174
175#define AM335X_GENERIC_CLOCK_DEV(i) \
176	{	.id = (i), \
177		.clk_activate = am335x_clk_generic_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		.clk_set_source_freq = NULL \
183	}
184
185#define AM335X_GPIO_CLOCK_DEV(i) \
186	{	.id = (i), \
187		.clk_activate = am335x_clk_gpio_activate, \
188		.clk_deactivate = am335x_clk_generic_deactivate, \
189		.clk_set_source = am335x_clk_generic_set_source, \
190		.clk_accessible = NULL, \
191		.clk_get_source_freq = NULL, \
192		.clk_set_source_freq = NULL \
193	}
194
195#define AM335X_MMCHS_CLOCK_DEV(i) \
196	{	.id = (i), \
197		.clk_activate = am335x_clk_generic_activate, \
198		.clk_deactivate = am335x_clk_generic_deactivate, \
199		.clk_set_source = am335x_clk_generic_set_source, \
200		.clk_accessible = NULL, \
201		.clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \
202		.clk_set_source_freq = NULL \
203	}
204
205struct ti_clock_dev ti_am335x_clk_devmap[] = {
206	/* System clocks */
207	{	.id                  = SYS_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_sysclk_freq,
213		.clk_set_source_freq = NULL,
214	},
215	/* MPU (ARM) core clocks */
216	{	.id                  = MPU_CLK,
217		.clk_activate        = NULL,
218		.clk_deactivate      = NULL,
219		.clk_set_source      = NULL,
220		.clk_accessible      = NULL,
221		.clk_get_source_freq = am335x_clk_get_arm_fclk_freq,
222		.clk_set_source_freq = NULL,
223	},
224	/* CPSW Ethernet Switch core clocks */
225	{	.id                  = CPSW_CLK,
226		.clk_activate        = am335x_clk_cpsw_activate,
227		.clk_deactivate      = NULL,
228		.clk_set_source      = NULL,
229		.clk_accessible      = NULL,
230		.clk_get_source_freq = NULL,
231		.clk_set_source_freq = NULL,
232	},
233
234	/* Mentor USB HS controller core clocks */
235	{	.id                  = MUSB0_CLK,
236		.clk_activate        = am335x_clk_musb0_activate,
237		.clk_deactivate      = NULL,
238		.clk_set_source      = NULL,
239		.clk_accessible      = NULL,
240		.clk_get_source_freq = NULL,
241		.clk_set_source_freq = NULL,
242	},
243
244	/* LCD controller clocks */
245	{	.id                  = LCDC_CLK,
246		.clk_activate        = am335x_clk_lcdc_activate,
247		.clk_deactivate      = NULL,
248		.clk_set_source      = NULL,
249		.clk_accessible      = NULL,
250		.clk_get_source_freq = am335x_clk_get_arm_disp_freq,
251		.clk_set_source_freq = am335x_clk_set_arm_disp_freq,
252	},
253
254        /* UART */
255	AM335X_NOOP_CLOCK_DEV(UART1_CLK),
256	AM335X_GENERIC_CLOCK_DEV(UART2_CLK),
257	AM335X_GENERIC_CLOCK_DEV(UART3_CLK),
258	AM335X_GENERIC_CLOCK_DEV(UART4_CLK),
259	AM335X_GENERIC_CLOCK_DEV(UART5_CLK),
260	AM335X_GENERIC_CLOCK_DEV(UART6_CLK),
261
262	/* DMTimer */
263	AM335X_GENERIC_CLOCK_DEV(TIMER2_CLK),
264	AM335X_GENERIC_CLOCK_DEV(TIMER3_CLK),
265	AM335X_GENERIC_CLOCK_DEV(TIMER4_CLK),
266	AM335X_GENERIC_CLOCK_DEV(TIMER5_CLK),
267	AM335X_GENERIC_CLOCK_DEV(TIMER6_CLK),
268	AM335X_GENERIC_CLOCK_DEV(TIMER7_CLK),
269
270	/* GPIO, we use hwmods as reference, not units in spec */
271	AM335X_GPIO_CLOCK_DEV(GPIO1_CLK),
272	AM335X_GPIO_CLOCK_DEV(GPIO2_CLK),
273	AM335X_GPIO_CLOCK_DEV(GPIO3_CLK),
274	AM335X_GPIO_CLOCK_DEV(GPIO4_CLK),
275
276	/* I2C we use hwmods as reference, not units in spec */
277	AM335X_GENERIC_CLOCK_DEV(I2C1_CLK),
278	AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
279	AM335X_GENERIC_CLOCK_DEV(I2C3_CLK),
280
281	/* McSPI we use hwmods as reference, not units in spec */
282	AM335X_GENERIC_CLOCK_DEV(SPI0_CLK),
283	AM335X_GENERIC_CLOCK_DEV(SPI1_CLK),
284
285	/* TSC_ADC */
286	AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
287
288	/* EDMA */
289	AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK),
290	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK),
291	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK),
292	AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK),
293
294	/* MMCHS */
295	AM335X_MMCHS_CLOCK_DEV(MMC1_CLK),
296	AM335X_MMCHS_CLOCK_DEV(MMC2_CLK),
297	AM335X_MMCHS_CLOCK_DEV(MMC3_CLK),
298
299	/* PWMSS */
300	AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK),
301	AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK),
302	AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK),
303
304	/* System Mailbox clock */
305	AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK),
306
307	/* SPINLOCK */
308	AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK),
309
310	/* PRU-ICSS */
311	{	.id		     = PRUSS_CLK,
312		.clk_activate	     = am335x_clk_pruss_activate,
313		.clk_deactivate      = NULL,
314		.clk_set_source      = NULL,
315		.clk_accessible      = NULL,
316		.clk_get_source_freq = NULL,
317		.clk_set_source_freq = NULL,
318	},
319
320	/* RTC */
321	AM335X_GENERIC_CLOCK_DEV(RTC_CLK),
322
323	{  INVALID_CLK_IDENT, NULL, NULL, NULL, NULL }
324};
325
326struct am335x_clk_details {
327	clk_ident_t	id;
328	uint32_t	clkctrl_reg;
329	uint32_t	clksel_reg;
330};
331
332#define _CLK_DETAIL(i, c, s) \
333	{	.id = (i), \
334		.clkctrl_reg = (c), \
335		.clksel_reg = (s), \
336	}
337
338static struct am335x_clk_details g_am335x_clk_details[] = {
339
340        /* UART. UART0 clock not controllable. */
341	_CLK_DETAIL(UART1_CLK, 0, 0),
342	_CLK_DETAIL(UART2_CLK, CM_PER_UART1_CLKCTRL, 0),
343	_CLK_DETAIL(UART3_CLK, CM_PER_UART2_CLKCTRL, 0),
344	_CLK_DETAIL(UART4_CLK, CM_PER_UART3_CLKCTRL, 0),
345	_CLK_DETAIL(UART5_CLK, CM_PER_UART4_CLKCTRL, 0),
346	_CLK_DETAIL(UART6_CLK, CM_PER_UART5_CLKCTRL, 0),
347
348	/* DMTimer modules */
349	_CLK_DETAIL(TIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK),
350	_CLK_DETAIL(TIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK),
351	_CLK_DETAIL(TIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK),
352	_CLK_DETAIL(TIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK),
353	_CLK_DETAIL(TIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK),
354	_CLK_DETAIL(TIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK),
355
356	/* GPIO modules, hwmods start with gpio1 */
357	_CLK_DETAIL(GPIO1_CLK, CM_WKUP_GPIO0_CLKCTRL, 0),
358	_CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO1_CLKCTRL, 0),
359	_CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO2_CLKCTRL, 0),
360	_CLK_DETAIL(GPIO4_CLK, CM_PER_GPIO3_CLKCTRL, 0),
361
362	/* I2C modules, hwmods start with i2c1 */
363	_CLK_DETAIL(I2C1_CLK, CM_WKUP_I2C0_CLKCTRL, 0),
364	_CLK_DETAIL(I2C2_CLK, CM_PER_I2C1_CLKCTRL, 0),
365	_CLK_DETAIL(I2C3_CLK, CM_PER_I2C2_CLKCTRL, 0),
366
367	/* McSPI modules, hwmods start with spi0 */
368	_CLK_DETAIL(SPI0_CLK, CM_PER_SPI0_CLKCTRL, 0),
369	_CLK_DETAIL(SPI1_CLK, CM_PER_SPI1_CLKCTRL, 0),
370
371	/* TSC_ADC module */
372	_CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
373
374	/* EDMA modules */
375	_CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0),
376	_CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0),
377	_CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0),
378	_CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0),
379
380	/* MMCHS modules, hwmods start with mmc1*/
381	_CLK_DETAIL(MMC1_CLK, CM_PER_MMC0_CLKCTRL, 0),
382	_CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0),
383	_CLK_DETAIL(MMC3_CLK, CM_PER_MMC1_CLKCTRL, 0),
384
385	/* PWMSS modules */
386	_CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0),
387	_CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0),
388	_CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0),
389
390	_CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0),
391	_CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0),
392
393	/* RTC module */
394	_CLK_DETAIL(RTC_CLK, CM_RTC_RTC_CLKCTRL, 0),
395
396	{ INVALID_CLK_IDENT, 0},
397};
398
399/* Read/Write macros */
400#define prcm_read_4(reg)		\
401	bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg)
402#define prcm_write_4(reg, val)		\
403	bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val)
404
405void am335x_prcm_setup_dmtimer(int);
406
407static int
408am335x_prcm_probe(device_t dev)
409{
410
411	if (!ofw_bus_status_okay(dev))
412		return (ENXIO);
413
414	if (ofw_bus_is_compatible(dev, "ti,am3-prcm")) {
415		device_set_desc(dev, "AM335x Power and Clock Management");
416		return(BUS_PROBE_DEFAULT);
417	}
418
419	return (ENXIO);
420}
421
422static int
423am335x_prcm_attach(device_t dev)
424{
425	struct am335x_prcm_softc *sc = device_get_softc(dev);
426	unsigned int sysclk, fclk;
427
428	if (am335x_prcm_sc)
429		return (ENXIO);
430
431	if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) {
432		device_printf(dev, "could not allocate resources\n");
433		return (ENXIO);
434	}
435
436	sc->bst = rman_get_bustag(sc->res[0]);
437	sc->bsh = rman_get_bushandle(sc->res[0]);
438
439	am335x_prcm_sc = sc;
440	ti_cpu_reset = am335x_prcm_reset;
441
442	if (am335x_clk_get_sysclk_freq(NULL, &sysclk) != 0)
443		sysclk = 0;
444	if (am335x_clk_get_arm_fclk_freq(NULL, &fclk) != 0)
445		fclk = 0;
446	if (sysclk && fclk)
447		device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n",
448		    sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000);
449	else
450		device_printf(dev, "can't read frequencies yet (SCM device not ready?)\n");
451
452	return (0);
453}
454
455static device_method_t am335x_prcm_methods[] = {
456	DEVMETHOD(device_probe,		am335x_prcm_probe),
457	DEVMETHOD(device_attach,	am335x_prcm_attach),
458	{ 0, 0 }
459};
460
461static driver_t am335x_prcm_driver = {
462	"am335x_prcm",
463	am335x_prcm_methods,
464	sizeof(struct am335x_prcm_softc),
465};
466
467static devclass_t am335x_prcm_devclass;
468
469EARLY_DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver,
470	am335x_prcm_devclass, 0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_EARLY);
471MODULE_VERSION(am335x_prcm, 1);
472MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1);
473
474static struct am335x_clk_details*
475am335x_clk_details(clk_ident_t id)
476{
477	struct am335x_clk_details *walker;
478
479	for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) {
480		if (id == walker->id)
481			return (walker);
482	}
483
484	return NULL;
485}
486
487static int
488am335x_clk_noop_activate(struct ti_clock_dev *clkdev)
489{
490
491	return (0);
492}
493
494static int
495am335x_clk_generic_activate(struct ti_clock_dev *clkdev)
496{
497	struct am335x_prcm_softc *sc = am335x_prcm_sc;
498	struct am335x_clk_details* clk_details;
499
500	if (sc == NULL)
501		return ENXIO;
502
503	clk_details = am335x_clk_details(clkdev->id);
504
505	if (clk_details == NULL)
506		return (ENXIO);
507
508	/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
509	prcm_write_4(clk_details->clkctrl_reg, 2);
510	while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2)
511		DELAY(10);
512
513	return (0);
514}
515
516static int
517am335x_clk_gpio_activate(struct ti_clock_dev *clkdev)
518{
519	struct am335x_prcm_softc *sc = am335x_prcm_sc;
520	struct am335x_clk_details* clk_details;
521
522	if (sc == NULL)
523		return ENXIO;
524
525	clk_details = am335x_clk_details(clkdev->id);
526
527	if (clk_details == NULL)
528		return (ENXIO);
529
530	/* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */
531	/* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */
532	prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18));
533	while ((prcm_read_4(clk_details->clkctrl_reg) &
534	    (3 | (1 << 18) )) != (2 | (1 << 18)))
535		DELAY(10);
536
537	return (0);
538}
539
540static int
541am335x_clk_noop_deactivate(struct ti_clock_dev *clkdev)
542{
543
544	return(0);
545}
546
547static int
548am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev)
549{
550	struct am335x_prcm_softc *sc = am335x_prcm_sc;
551	struct am335x_clk_details* clk_details;
552
553	if (sc == NULL)
554		return ENXIO;
555
556	clk_details = am335x_clk_details(clkdev->id);
557
558	if (clk_details == NULL)
559		return (ENXIO);
560
561	/* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */
562	prcm_write_4(clk_details->clkctrl_reg, 0);
563	while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0)
564		DELAY(10);
565
566	return (0);
567}
568
569static int
570am335x_clk_noop_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
571{
572
573	return (0);
574}
575
576static int
577am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc)
578{
579	struct am335x_prcm_softc *sc = am335x_prcm_sc;
580	struct am335x_clk_details* clk_details;
581	uint32_t reg;
582
583	if (sc == NULL)
584		return ENXIO;
585
586	clk_details = am335x_clk_details(clkdev->id);
587
588	if (clk_details == NULL)
589		return (ENXIO);
590
591	switch (clksrc) {
592		case EXT_CLK:
593			reg = 0; /* SEL2: TCLKIN clock */
594			break;
595		case SYSCLK_CLK:
596			reg = 1; /* SEL1: CLK_M_OSC clock */
597			break;
598		case F32KHZ_CLK:
599			reg = 2; /* SEL3: CLK_32KHZ clock */
600			break;
601		default:
602			return (ENXIO);
603	}
604
605	prcm_write_4(clk_details->clksel_reg, reg);
606	while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg)
607		DELAY(10);
608
609	return (0);
610}
611
612static int
613am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev,  unsigned int *freq)
614{
615	*freq = 96000000;
616	return (0);
617}
618
619static int
620am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
621{
622	uint32_t ctrl_status;
623
624	/* Read the input clock freq from the control module. */
625	if (ti_scm_reg_read_4(SCM_CTRL_STATUS, &ctrl_status))
626		return (ENXIO);
627
628	switch ((ctrl_status>>22) & 0x3) {
629	case 0x0:
630		/* 19.2Mhz */
631		*freq = 19200000;
632		break;
633	case 0x1:
634		/* 24Mhz */
635		*freq = 24000000;
636		break;
637	case 0x2:
638		/* 25Mhz */
639		*freq = 25000000;
640		break;
641	case 0x3:
642		/* 26Mhz */
643		*freq = 26000000;
644		break;
645	}
646
647	return (0);
648}
649
650#define DPLL_BYP_CLKSEL(reg)	((reg>>23) & 1)
651#define DPLL_DIV(reg)		((reg & 0x7f)+1)
652#define DPLL_MULT(reg)		((reg>>8) & 0x7FF)
653#define	DPLL_MAX_MUL		0x800
654#define	DPLL_MAX_DIV		0x80
655
656static int
657am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
658{
659	uint32_t reg;
660	uint32_t sysclk;
661
662	reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU);
663
664	/*Check if we are running in bypass */
665	if (DPLL_BYP_CLKSEL(reg))
666		return ENXIO;
667
668	am335x_clk_get_sysclk_freq(NULL, &sysclk);
669	*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
670	return(0);
671}
672
673static int
674am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq)
675{
676	uint32_t reg;
677	uint32_t sysclk;
678
679	reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP);
680
681	/*Check if we are running in bypass */
682	if (DPLL_BYP_CLKSEL(reg))
683		return ENXIO;
684
685	am335x_clk_get_sysclk_freq(NULL, &sysclk);
686	*freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg));
687	return(0);
688}
689
690static int
691am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq)
692{
693	uint32_t sysclk;
694	uint32_t mul, div;
695	uint32_t i, j;
696	unsigned int delta, min_delta;
697
698	am335x_clk_get_sysclk_freq(NULL, &sysclk);
699
700	/* Bypass mode */
701	prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4);
702
703	/* Make sure it's in bypass mode */
704	while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
705	    & (1 << 8)))
706		DELAY(10);
707
708	/* Dumb and non-optimal implementation */
709	min_delta = freq;
710	for (i = 1; i < DPLL_MAX_MUL; i++) {
711		for (j = 1; j < DPLL_MAX_DIV; j++) {
712			delta = abs(freq - i*(sysclk/j));
713			if (delta < min_delta) {
714				mul = i;
715				div = j;
716				min_delta = delta;
717			}
718			if (min_delta == 0)
719				break;
720		}
721	}
722
723	prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1));
724
725	/* Locked mode */
726	prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7);
727
728	int timeout = 10000;
729	while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP)
730	    & (1 << 0))) && timeout--)
731		DELAY(10);
732
733	return(0);
734}
735
736static void
737am335x_prcm_reset(void)
738{
739	prcm_write_4(PRM_RSTCTRL, (1<<1));
740}
741
742static int
743am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev)
744{
745	struct am335x_prcm_softc *sc = am335x_prcm_sc;
746
747	if (sc == NULL)
748		return ENXIO;
749
750	/* set MODULENAME to ENABLE */
751	prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2);
752
753	/* wait for IDLEST to become Func(0) */
754	while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16));
755
756	/*set CLKTRCTRL to SW_WKUP(2) */
757	prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2);
758
759	/* wait for 125 MHz OCP clock to become active */
760	while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0);
761	return(0);
762}
763
764static int
765am335x_clk_musb0_activate(struct ti_clock_dev *clkdev)
766{
767	struct am335x_prcm_softc *sc = am335x_prcm_sc;
768
769	if (sc == NULL)
770		return ENXIO;
771
772	/* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */
773	/* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/
774        prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300);
775
776	/*set MODULEMODE to ENABLE(2) */
777	prcm_write_4(CM_PER_USB0_CLKCTRL, 2);
778
779	/* wait for MODULEMODE to become ENABLE(2) */
780	while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2)
781		DELAY(10);
782
783	/* wait for IDLEST to become Func(0) */
784	while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16))
785		DELAY(10);
786
787	return(0);
788}
789
790static int
791am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev)
792{
793	struct am335x_prcm_softc *sc = am335x_prcm_sc;
794
795	if (sc == NULL)
796		return (ENXIO);
797
798	/*
799	 * For now set frequency to 2*VGA_PIXEL_CLOCK
800	 */
801	am335x_clk_set_arm_disp_freq(clkdev, 25175000*2);
802
803	/*set MODULEMODE to ENABLE(2) */
804	prcm_write_4(CM_PER_LCDC_CLKCTRL, 2);
805
806	/* wait for MODULEMODE to become ENABLE(2) */
807	while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2)
808		DELAY(10);
809
810	/* wait for IDLEST to become Func(0) */
811	while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16))
812		DELAY(10);
813
814	return (0);
815}
816
817static int
818am335x_clk_pruss_activate(struct ti_clock_dev *clkdev)
819{
820	struct am335x_prcm_softc *sc = am335x_prcm_sc;
821
822	if (sc == NULL)
823		return (ENXIO);
824
825	/* Set MODULEMODE to ENABLE(2) */
826	prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2);
827
828	/* Wait for MODULEMODE to become ENABLE(2) */
829	while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2)
830		DELAY(10);
831
832	/* Set CLKTRCTRL to SW_WKUP(2) */
833	prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2);
834
835	/* Wait for the 200 MHz OCP clock to become active */
836	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0)
837		DELAY(10);
838
839	/* Wait for the 200 MHz IEP clock to become active */
840	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0)
841		DELAY(10);
842
843	/* Wait for the 192 MHz UART clock to become active */
844	while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0)
845		DELAY(10);
846
847	/* Select L3F as OCP clock */
848	prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 0);
849	while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 0)
850		DELAY(10);
851
852	/* Clear the RESET bit */
853	prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2);
854
855	return (0);
856}
857