xref: /netbsd-src/sys/arch/arm/imx/imx31_clock.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
1*cbab9cadSchs /*	$NetBSD: imx31_clock.c,v 1.5 2012/10/27 17:17:39 chs Exp $ */
2554cfb29Sbsh /*
3554cfb29Sbsh  * Copyright (c) 2009,2010  Genetec corp.  All rights reserved.
4554cfb29Sbsh  * Written by Hashimoto Kenichi for Genetec corp.
5554cfb29Sbsh  *
6554cfb29Sbsh  * Redistribution and use in source and binary forms, with or without
7554cfb29Sbsh  * modification, are permitted provided that the following conditions
8554cfb29Sbsh  * are met:
9554cfb29Sbsh  * 1. Redistributions of source code must retain the above copyright
10554cfb29Sbsh  *    notice, this list of conditions and the following disclaimer.
11554cfb29Sbsh  * 2. Redistributions in binary form must reproduce the above copyright
12554cfb29Sbsh  *    notice, this list of conditions and the following disclaimer in the
13554cfb29Sbsh  *    documentation and/or other materials provided with the distribution.
14554cfb29Sbsh  *
15554cfb29Sbsh  * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
16554cfb29Sbsh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17554cfb29Sbsh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18554cfb29Sbsh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORP.
19554cfb29Sbsh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20554cfb29Sbsh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21554cfb29Sbsh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22554cfb29Sbsh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23554cfb29Sbsh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24554cfb29Sbsh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25554cfb29Sbsh  * POSSIBILITY OF SUCH DAMAGE.
26554cfb29Sbsh  */
27554cfb29Sbsh 
28554cfb29Sbsh #include <sys/param.h>
29554cfb29Sbsh #include <sys/systm.h>
30554cfb29Sbsh #include <sys/kernel.h>
31554cfb29Sbsh #include <sys/evcnt.h>
32554cfb29Sbsh #include <sys/atomic.h>
33554cfb29Sbsh #include <sys/time.h>
34554cfb29Sbsh #include <sys/timetc.h>
35554cfb29Sbsh 
36554cfb29Sbsh #include <sys/types.h>
37554cfb29Sbsh #include <sys/device.h>
38554cfb29Sbsh 
39554cfb29Sbsh #include <machine/intr.h>
40ed9977b1Sdyoung #include <sys/bus.h>
41554cfb29Sbsh 
42554cfb29Sbsh #include <arm/cpu.h>
43554cfb29Sbsh #include <arm/armreg.h>
44554cfb29Sbsh #include <arm/cpufunc.h>
45554cfb29Sbsh 
46554cfb29Sbsh #include <arm/imx/imx31reg.h>
47554cfb29Sbsh #include <arm/imx/imx31var.h>
483747b72bSbsh #if 0 /* notyet */
49554cfb29Sbsh #include <arm/imx/imx31_ccmvar.h>
503747b72bSbsh #endif
51554cfb29Sbsh #include <arm/imx/imxclockvar.h>
523747b72bSbsh #include <arm/imx/imxepitreg.h>
533747b72bSbsh 
543747b72bSbsh #include "imxccm.h"	/* if CCM driver is configured into the kernel */
553747b72bSbsh #include "opt_imx31clk.h"
56554cfb29Sbsh 
57554cfb29Sbsh static int imxclock_match(device_t, struct cfdata *, void *);
58554cfb29Sbsh static void imxclock_attach(device_t, device_t, void *);
59554cfb29Sbsh 
60554cfb29Sbsh struct imxclock_softc *epit1_sc = NULL;
61554cfb29Sbsh struct imxclock_softc *epit2_sc = NULL;
62554cfb29Sbsh 
63554cfb29Sbsh CFATTACH_DECL_NEW(imxclock, sizeof(struct imxclock_softc),
64554cfb29Sbsh     imxclock_match, imxclock_attach, NULL, NULL);
65554cfb29Sbsh 
66554cfb29Sbsh static int
imxclock_match(device_t parent,struct cfdata * match,void * aux)67554cfb29Sbsh imxclock_match(device_t parent, struct cfdata *match, void *aux)
68554cfb29Sbsh {
69554cfb29Sbsh 	struct aips_attach_args *aipsa = aux;
70554cfb29Sbsh 
71554cfb29Sbsh 	if ( (aipsa->aipsa_addr != EPIT1_BASE) &&
72554cfb29Sbsh 	     (aipsa->aipsa_addr != EPIT2_BASE) ) {
73554cfb29Sbsh 		return 0;
74554cfb29Sbsh 	}
75554cfb29Sbsh 
76554cfb29Sbsh 	return 2;
77554cfb29Sbsh }
78554cfb29Sbsh 
79554cfb29Sbsh static void
imxclock_attach(device_t parent,device_t self,void * aux)80554cfb29Sbsh imxclock_attach(device_t parent, device_t self, void *aux)
81554cfb29Sbsh {
82554cfb29Sbsh 	struct imxclock_softc *sc = device_private(self);
83554cfb29Sbsh 	struct aips_attach_args *aipsa = aux;
84554cfb29Sbsh 
85554cfb29Sbsh 	aprint_normal("\n");
86554cfb29Sbsh 
87554cfb29Sbsh 	sc->sc_dev = self;
88554cfb29Sbsh 	sc->sc_iot = aipsa->aipsa_memt;
89554cfb29Sbsh 	sc->sc_intr = aipsa->aipsa_intr;
90554cfb29Sbsh 
91554cfb29Sbsh 	KASSERT((sc->sc_intr == IRQ_EPIT1) || (sc->sc_intr == IRQ_EPIT2));
92554cfb29Sbsh 
93554cfb29Sbsh 	switch ( aipsa->aipsa_addr ) {
94554cfb29Sbsh 	case EPIT1_BASE:
95554cfb29Sbsh 		epit1_sc = sc;
96554cfb29Sbsh 		break;
97554cfb29Sbsh 	case EPIT2_BASE:
98554cfb29Sbsh 		epit2_sc = sc;
99554cfb29Sbsh 		break;
100554cfb29Sbsh 	default:
101*cbab9cadSchs 		panic("%s: invalid address %p", device_xname(self), (void *)aipsa->aipsa_addr);
102554cfb29Sbsh 		break;
103554cfb29Sbsh 	}
104554cfb29Sbsh 
105554cfb29Sbsh 	if (bus_space_map(aipsa->aipsa_memt, aipsa->aipsa_addr,
106554cfb29Sbsh 		aipsa->aipsa_size, 0, &sc->sc_ioh)) {
107554cfb29Sbsh 		panic("%s: Cannot map registers", device_xname(self));
108554cfb29Sbsh 	}
109c368cb1dSbsh 
110c368cb1dSbsh 	sc->sc_clksrc = EPITCR_CLKSRC_HIGH;
111554cfb29Sbsh }
112554cfb29Sbsh 
113554cfb29Sbsh int
imxclock_get_timerfreq(struct imxclock_softc * sc)114554cfb29Sbsh imxclock_get_timerfreq(struct imxclock_softc *sc)
115554cfb29Sbsh {
1163747b72bSbsh #if NIMXCCM > 0
117554cfb29Sbsh 	struct imx31_clocks clk;
118554cfb29Sbsh 	imx31_get_clocks(&clk);
119554cfb29Sbsh 
120554cfb29Sbsh 	return clk.ipg_clk;
1213747b72bSbsh #else
1223747b72bSbsh #ifndef	IMX31_IPGCLK_FREQ
1233747b72bSbsh #error	IMX31_IPGCLK_FREQ need to be defined.
1243747b72bSbsh #endif
1253747b72bSbsh 	return IMX31_IPGCLK_FREQ;
1263747b72bSbsh 
1273747b72bSbsh #endif
128554cfb29Sbsh }
129554cfb29Sbsh 
130554cfb29Sbsh 
131