Home | History | Annotate | Line # | Download | only in imx
imx23_timrot.c revision 1.2.2.2
      1 /* $Id: imx23_timrot.c,v 1.2.2.2 2013/01/16 05:32:48 yamt Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Petri Laakso.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/device.h>
     35 #include <sys/errno.h>
     36 #include <sys/systm.h>
     37 
     38 #include <arm/pic/picvar.h>
     39 
     40 #include <arm/imx/imx23_icollreg.h>
     41 #include <arm/imx/imx23_timrotreg.h>
     42 #include <arm/imx/imx23var.h>
     43 
     44 extern int hz;
     45 extern int stathz;
     46 
     47 static int	timrot_match(device_t, cfdata_t, void *);
     48 static void	timrot_attach(device_t, device_t, void *);
     49 static int	timrot_activate(device_t, enum devact);
     50 
     51 static void	timrot_reset(void);
     52 
     53 /*
     54  * Timer IRQ handler definitions.
     55  */
     56 static int	systimer_irq(void *);
     57 static int	stattimer_irq(void *);
     58 
     59 void	cpu_initclocks(void);
     60 void 	setstatclockrate(int);
     61 
     62 /* Allocated for each timer instance. */
     63 struct timrot_softc {
     64 	device_t sc_dev;
     65 	bus_space_tag_t sc_iot;
     66 	bus_space_handle_t sc_hdl;
     67 	int8_t sc_irq;
     68 	int (*irq_handler)(void *);
     69 	int freq;
     70 };
     71 
     72 static bus_space_tag_t timrot_iot;
     73 static bus_space_handle_t timrot_hdl;
     74 
     75 CFATTACH_DECL3_NEW(timrot,
     76 	sizeof(struct timrot_softc),
     77 	timrot_match,
     78 	timrot_attach,
     79 	NULL,
     80 	timrot_activate,
     81 	NULL,
     82 	NULL,
     83 	0);
     84 
     85 #define MAX_TIMERS	4
     86 #define SYS_TIMER	0
     87 #define STAT_TIMER	1
     88 #define SCHED_TIMER	2
     89 
     90 struct timrot_softc *timer_sc[MAX_TIMERS];
     91 
     92 static void	timer_init(struct timrot_softc *);
     93 
     94 #define TIMROT_SOFT_RST_LOOP 455 /* At least 1 us ... */
     95 #define TIMROT_READ(reg)						\
     96 	bus_space_read_4(timrot_iot, timrot_hdl, (reg))
     97 #define TIMROT_WRITE(reg, val)						\
     98 	bus_space_write_4(timrot_iot, timrot_hdl, (reg), (val))
     99 
    100 #define TIMER_REGS_SIZE 0x20
    101 
    102 #define TIMER_CTRL	0x00
    103 #define TIMER_CTRL_SET	0x04
    104 #define TIMER_CTRL_CLR	0x08
    105 #define TIMER_CTRL_TOG	0x0C
    106 #define TIMER_COUNT	0x10
    107 
    108 #define TIMER_READ(sc, reg)						\
    109 	bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
    110 #define TIMER_WRITE(sc, reg, val)					\
    111 	bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
    112 #define TIMER_WRITE_2(sc, reg, val)					\
    113 	bus_space_write_2(sc->sc_iot, sc->sc_hdl, (reg), (val))
    114 
    115 #define SELECT_32KHZ	0x8	/* Use 32kHz clock source. */
    116 #define SOURCE_32KHZ_HZ	32000	/* Above source in Hz. */
    117 
    118 #define IRQ HW_TIMROT_TIMCTRL0_IRQ
    119 #define IRQ_EN HW_TIMROT_TIMCTRL0_IRQ_EN
    120 #define UPDATE HW_TIMROT_TIMCTRL0_UPDATE
    121 #define RELOAD HW_TIMROT_TIMCTRL0_RELOAD
    122 
    123 static int
    124 timrot_match(device_t parent, cfdata_t match, void *aux)
    125 {
    126 	struct apb_attach_args *aa = aux;
    127 
    128 	if ((aa->aa_addr == HW_TIMROT_BASE + HW_TIMROT_TIMCTRL0
    129 	    && aa->aa_size == TIMER_REGS_SIZE))
    130 		return 1;
    131 
    132 	if ((aa->aa_addr == HW_TIMROT_BASE + HW_TIMROT_TIMCTRL1
    133 	    && aa->aa_size == TIMER_REGS_SIZE))
    134 		return 1;
    135 
    136 #if 0
    137 	if ((aa->aa_addr == HW_TIMROT_BASE + HW_TIMROT_TIMCTRL2
    138 	    && aa->aa_size == TIMER_REGS_SIZE))
    139 		return 1;
    140 
    141 	if ((aa->aa_addr == HW_TIMROT_BASE + HW_TIMROT_TIMCTRL3
    142 	    && aa->aa_size == TIMER_REGS_SIZE))
    143 		return 1;
    144 #endif
    145 	return 0;
    146 }
    147 
    148 static void
    149 timrot_attach(device_t parent, device_t self, void *aux)
    150 {
    151 	struct apb_attach_args *aa = aux;
    152 	struct timrot_softc *sc = device_private(self);
    153 	static int timrot_attached = 0;
    154 
    155 	if (!timrot_attached) {
    156 		timrot_iot = aa->aa_iot;
    157 		if (bus_space_map(timrot_iot, HW_TIMROT_BASE, HW_TIMROT_SIZE,
    158 		    0, &timrot_hdl)) {
    159 			aprint_error_dev(sc->sc_dev,
    160 			    "unable to map bus space\n");
    161 			return;
    162 		}
    163 		timrot_reset();
    164 		timrot_attached = 1;
    165 	}
    166 
    167 	if (aa->aa_addr == HW_TIMROT_BASE + HW_TIMROT_TIMCTRL0
    168 	    && aa->aa_size == TIMER_REGS_SIZE
    169 	    && timer_sc[SYS_TIMER] == NULL) {
    170 		if (bus_space_subregion(timrot_iot, timrot_hdl,
    171 		    HW_TIMROT_TIMCTRL0, TIMER_REGS_SIZE,
    172 		    &sc->sc_hdl)) {
    173 			aprint_error_dev(sc->sc_dev,
    174 			    "unable to map subregion\n");
    175 			return;
    176 		}
    177 
    178 		sc->sc_iot = aa->aa_iot;
    179 		sc->sc_irq = aa->aa_irq;
    180 		sc->irq_handler = &systimer_irq;
    181 		sc->freq = hz;
    182 
    183 		timer_sc[SYS_TIMER] = sc;
    184 
    185 		aprint_normal("\n");
    186 
    187 	} else if (aa->aa_addr == HW_TIMROT_BASE + HW_TIMROT_TIMCTRL1
    188 	    && aa->aa_size == TIMER_REGS_SIZE
    189 	    && timer_sc[STAT_TIMER] == NULL) {
    190 		if (bus_space_subregion(timrot_iot, timrot_hdl,
    191 		    HW_TIMROT_TIMCTRL1, TIMER_REGS_SIZE, &sc->sc_hdl)) {
    192 			aprint_error_dev(sc->sc_dev,
    193 			    "unable to map subregion\n");
    194 			return;
    195 		}
    196 
    197 		sc->sc_iot = aa->aa_iot;
    198 		sc->sc_irq = aa->aa_irq;
    199 		sc->irq_handler = &stattimer_irq;
    200 		stathz = (hz>>1);
    201 		sc->freq = stathz;
    202 
    203 		timer_sc[STAT_TIMER] = sc;
    204 
    205 		aprint_normal("\n");
    206 	}
    207 
    208 	return;
    209 }
    210 
    211 static int
    212 timrot_activate(device_t self, enum devact act)
    213 {
    214 	return EOPNOTSUPP;
    215 }
    216 
    217 /*
    218  * cpu_initclock is called once at the boot time.
    219  */
    220 void
    221 cpu_initclocks(void)
    222 {
    223 	if (timer_sc[SYS_TIMER] != NULL)
    224 		timer_init(timer_sc[SYS_TIMER]);
    225 
    226 	if (timer_sc[STAT_TIMER] != NULL)
    227 		timer_init(timer_sc[STAT_TIMER]);
    228 
    229 	return;
    230 }
    231 
    232 /*
    233  * Change statclock rate when profiling takes place.
    234  */
    235 void
    236 setstatclockrate(int newhz)
    237 {
    238 	struct timrot_softc *sc = timer_sc[STAT_TIMER];
    239 	sc->freq = newhz;
    240 
    241 	TIMER_WRITE_2(sc, TIMER_COUNT,
    242 	    __SHIFTIN(SOURCE_32KHZ_HZ / sc->freq,
    243 	    HW_TIMROT_TIMCOUNT0_FIXED_COUNT));
    244 
    245 	return;
    246 }
    247 
    248 /*
    249  * Generic timer initialization function.
    250  */
    251 static void
    252 timer_init(struct timrot_softc *sc)
    253 {
    254 	uint32_t ctrl;
    255 
    256 	TIMER_WRITE_2(sc, TIMER_COUNT,
    257 	    __SHIFTIN(SOURCE_32KHZ_HZ / sc->freq,
    258 	    HW_TIMROT_TIMCOUNT0_FIXED_COUNT));
    259 	ctrl = IRQ_EN | UPDATE | RELOAD | SELECT_32KHZ;
    260 	TIMER_WRITE(sc, TIMER_CTRL, ctrl);
    261 
    262 	intr_establish(sc->sc_irq, IPL_SCHED, IST_LEVEL, sc->irq_handler, NULL);
    263 
    264 	return;
    265 }
    266 
    267 /*
    268  * Timer IRQ handlers.
    269  */
    270 static int
    271 systimer_irq(void *frame)
    272 {
    273 	hardclock(frame);
    274 
    275 	TIMER_WRITE(timer_sc[SYS_TIMER], TIMER_CTRL_CLR, IRQ);
    276 
    277 	return 1;
    278 }
    279 
    280 static int
    281 stattimer_irq(void *frame)
    282 {
    283 	statclock(frame);
    284 
    285 	TIMER_WRITE(timer_sc[STAT_TIMER], TIMER_CTRL_CLR, IRQ);
    286 
    287 	return 1;
    288 }
    289 
    290 /*
    291  * Reset the TIMROT block.
    292  *
    293  * Inspired by i.MX233 RM "39.3.10 Correct Way to Soft Reset a Block"
    294  */
    295 static void
    296 timrot_reset(void)
    297 {
    298 	unsigned int loop;
    299 
    300 	/* Prepare for soft-reset by making sure that SFTRST is not currently
    301 	* asserted. Also clear CLKGATE so we can wait for its assertion below.
    302 	*/
    303 	TIMROT_WRITE(HW_TIMROT_ROTCTRL_CLR, HW_TIMROT_ROTCTRL_SFTRST);
    304 
    305 	/* Wait at least a microsecond for SFTRST to deassert. */
    306 	loop = 0;
    307 	while ((TIMROT_READ(HW_TIMROT_ROTCTRL) & HW_TIMROT_ROTCTRL_SFTRST) ||
    308 	    (loop < TIMROT_SOFT_RST_LOOP))
    309 		loop++;
    310 
    311 	/* Clear CLKGATE so we can wait for its assertion below. */
    312 	TIMROT_WRITE(HW_TIMROT_ROTCTRL_CLR, HW_TIMROT_ROTCTRL_CLKGATE);
    313 
    314 	/* Soft-reset the block. */
    315 	TIMROT_WRITE(HW_TIMROT_ROTCTRL_SET, HW_TIMROT_ROTCTRL_SFTRST);
    316 
    317 	/* Wait until clock is in the gated state. */
    318 	while (!(TIMROT_READ(HW_TIMROT_ROTCTRL) & HW_TIMROT_ROTCTRL_CLKGATE));
    319 
    320 	/* Bring block out of reset. */
    321 	TIMROT_WRITE(HW_TIMROT_ROTCTRL_CLR, HW_TIMROT_ROTCTRL_SFTRST);
    322 
    323 	loop = 0;
    324 	while ((TIMROT_READ(HW_TIMROT_ROTCTRL) & HW_TIMROT_ROTCTRL_SFTRST) ||
    325 	    (loop < TIMROT_SOFT_RST_LOOP))
    326 		loop++;
    327 
    328 	TIMROT_WRITE(HW_TIMROT_ROTCTRL_CLR, HW_TIMROT_ROTCTRL_CLKGATE);
    329 	/* Wait until clock is in the NON-gated state. */
    330 	while (TIMROT_READ(HW_TIMROT_ROTCTRL) & HW_TIMROT_ROTCTRL_CLKGATE);
    331 
    332 	return;
    333 }
    334