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