1*2868f5bcShkenken /* $NetBSD: imx51_clock.c,v 1.5 2014/07/25 07:49:56 hkenken Exp $ */
2554cfb29Sbsh /*
3554cfb29Sbsh * Copyright (c) 2009 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 #include <sys/cdefs.h>
28*2868f5bcShkenken __KERNEL_RCSID(0, "$NetBSD: imx51_clock.c,v 1.5 2014/07/25 07:49:56 hkenken Exp $");
29*2868f5bcShkenken
30*2868f5bcShkenken #include "opt_imx.h"
31*2868f5bcShkenken #include "opt_imx51clk.h"
32554cfb29Sbsh
33554cfb29Sbsh #include <sys/param.h>
34554cfb29Sbsh #include <sys/systm.h>
35554cfb29Sbsh #include <sys/kernel.h>
36554cfb29Sbsh #include <sys/evcnt.h>
37554cfb29Sbsh #include <sys/atomic.h>
38554cfb29Sbsh #include <sys/time.h>
39554cfb29Sbsh #include <sys/timetc.h>
40554cfb29Sbsh
41554cfb29Sbsh #include <sys/types.h>
42554cfb29Sbsh #include <sys/device.h>
43554cfb29Sbsh
44554cfb29Sbsh #include <dev/clock_subr.h>
45554cfb29Sbsh
46554cfb29Sbsh #include <machine/intr.h>
47ed9977b1Sdyoung #include <sys/bus.h>
48554cfb29Sbsh
49554cfb29Sbsh #include <arm/cpufunc.h>
50554cfb29Sbsh
51554cfb29Sbsh #include <arm/imx/imx51reg.h>
52554cfb29Sbsh #include <arm/imx/imx51var.h>
53554cfb29Sbsh #include <arm/imx/imxepitreg.h>
54056b7b23Sbsh #include <arm/imx/imx51_ccmvar.h>
55554cfb29Sbsh #include <arm/imx/imxclockvar.h>
56554cfb29Sbsh
57554cfb29Sbsh #include "imxccm.h" /* if CCM driver is configured into the kernel */
58554cfb29Sbsh
59554cfb29Sbsh
60554cfb29Sbsh
61554cfb29Sbsh static int imxclock_match(device_t, struct cfdata *, void *);
62554cfb29Sbsh static void imxclock_attach(device_t, device_t, void *);
63554cfb29Sbsh
64554cfb29Sbsh struct imxclock_softc *epit1_sc = NULL;
65554cfb29Sbsh struct imxclock_softc *epit2_sc = NULL;
66554cfb29Sbsh
67554cfb29Sbsh CFATTACH_DECL_NEW(imxclock, sizeof(struct imxclock_softc),
68554cfb29Sbsh imxclock_match, imxclock_attach, NULL, NULL);
69554cfb29Sbsh
70554cfb29Sbsh static int
imxclock_match(device_t parent,struct cfdata * match,void * aux)71554cfb29Sbsh imxclock_match(device_t parent, struct cfdata *match, void *aux)
72554cfb29Sbsh {
73554cfb29Sbsh struct axi_attach_args *aa = aux;
74554cfb29Sbsh
75554cfb29Sbsh if ( (aa->aa_addr != EPIT1_BASE) &&
76554cfb29Sbsh (aa->aa_addr != EPIT2_BASE) ) {
77554cfb29Sbsh return 0;
78554cfb29Sbsh }
79554cfb29Sbsh
80554cfb29Sbsh return 2;
81554cfb29Sbsh }
82554cfb29Sbsh
83554cfb29Sbsh static void
imxclock_attach(device_t parent,device_t self,void * aux)84554cfb29Sbsh imxclock_attach(device_t parent, device_t self, void *aux)
85554cfb29Sbsh {
86554cfb29Sbsh struct imxclock_softc *sc = device_private(self);
87554cfb29Sbsh struct axi_attach_args *aa = aux;
88554cfb29Sbsh
89554cfb29Sbsh aprint_normal("\n");
90554cfb29Sbsh
91554cfb29Sbsh sc->sc_dev = self;
92554cfb29Sbsh sc->sc_iot = aa->aa_iot;
93554cfb29Sbsh sc->sc_intr = aa->aa_irq;
94554cfb29Sbsh
95554cfb29Sbsh switch ( aa->aa_addr ) {
96554cfb29Sbsh case EPIT1_BASE:
97554cfb29Sbsh epit1_sc = sc;
98554cfb29Sbsh break;
99554cfb29Sbsh case EPIT2_BASE:
100554cfb29Sbsh epit2_sc = sc;
101554cfb29Sbsh break;
102554cfb29Sbsh default:
103cbab9cadSchs panic("%s: invalid address %p", device_xname(self), (void *)aa->aa_addr);
104554cfb29Sbsh break;
105554cfb29Sbsh }
106554cfb29Sbsh
107554cfb29Sbsh if (bus_space_map(aa->aa_iot, aa->aa_addr, aa->aa_size, 0, &sc->sc_ioh))
108554cfb29Sbsh panic("%s: Cannot map registers", device_xname(self));
109056b7b23Sbsh
110056b7b23Sbsh sc->sc_clksrc = EPITCR_CLKSRC_IPG;
111554cfb29Sbsh }
112554cfb29Sbsh
113554cfb29Sbsh int
imxclock_get_timerfreq(struct imxclock_softc * sc)114554cfb29Sbsh imxclock_get_timerfreq(struct imxclock_softc *sc)
115554cfb29Sbsh {
116554cfb29Sbsh unsigned int ipg_freq;
117554cfb29Sbsh #if NIMXCCM > 0
118056b7b23Sbsh ipg_freq = imx51_get_clock(IMX51CLK_IPG_CLK_ROOT);
119554cfb29Sbsh #else
120554cfb29Sbsh #ifndef IMX51_IPGCLK_FREQ
121554cfb29Sbsh #error IMX51_IPGCLK_FREQ need to be defined.
122554cfb29Sbsh #endif
123554cfb29Sbsh ipg_freq = IMX51_IPGCLK_FREQ;
124554cfb29Sbsh #endif
125554cfb29Sbsh
126554cfb29Sbsh return ipg_freq;
127554cfb29Sbsh }
128554cfb29Sbsh
129