Home | History | Annotate | Line # | Download | only in ixp12x0
ixp12x0_clk.c revision 1.3
      1  1.3  provos /*	$NetBSD: ixp12x0_clk.c,v 1.3 2002/09/27 15:35:48 provos Exp $	*/
      2  1.1  ichiro 
      3  1.1  ichiro /*
      4  1.1  ichiro  * Copyright (c) 1997 Mark Brinicombe.
      5  1.1  ichiro  * Copyright (c) 1997 Causality Limited.
      6  1.1  ichiro  * All rights reserved.
      7  1.1  ichiro  *
      8  1.1  ichiro  * This code is derived from software contributed to The NetBSD Foundation
      9  1.1  ichiro  * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
     10  1.1  ichiro  *
     11  1.1  ichiro  * Redistribution and use in source and binary forms, with or without
     12  1.1  ichiro  * modification, are permitted provided that the following conditions
     13  1.1  ichiro  * are met:
     14  1.1  ichiro  * 1. Redistributions of source code must retain the above copyright
     15  1.1  ichiro  *    notice, this list of conditions and the following disclaimer.
     16  1.1  ichiro  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.1  ichiro  *    notice, this list of conditions and the following disclaimer in the
     18  1.1  ichiro  *    documentation and/or other materials provided with the distribution.
     19  1.1  ichiro  * 3. All advertising materials mentioning features or use of this software
     20  1.1  ichiro  *    must display the following acknowledgement:
     21  1.1  ichiro  *	This product includes software developed by the NetBSD
     22  1.1  ichiro  *	Foundation, Inc. and its contributors.
     23  1.1  ichiro  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  1.1  ichiro  *    contributors may be used to endorse or promote products derived
     25  1.1  ichiro  *    from this software without specific prior written permission.
     26  1.1  ichiro  *
     27  1.1  ichiro  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  1.1  ichiro  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  1.1  ichiro  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  1.1  ichiro  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  1.1  ichiro  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  1.1  ichiro  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  1.1  ichiro  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  1.1  ichiro  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  1.1  ichiro  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  1.1  ichiro  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  1.1  ichiro  * POSSIBILITY OF SUCH DAMAGE.
     38  1.1  ichiro  */
     39  1.1  ichiro 
     40  1.1  ichiro #include <sys/types.h>
     41  1.1  ichiro #include <sys/param.h>
     42  1.1  ichiro #include <sys/systm.h>
     43  1.1  ichiro #include <sys/kernel.h>
     44  1.1  ichiro #include <sys/time.h>
     45  1.1  ichiro #include <sys/device.h>
     46  1.1  ichiro 
     47  1.1  ichiro #include <machine/bus.h>
     48  1.1  ichiro #include <machine/intr.h>
     49  1.1  ichiro 
     50  1.1  ichiro #include <arm/cpufunc.h>
     51  1.1  ichiro 
     52  1.1  ichiro #include <arm/ixp12x0/ixpsipvar.h>
     53  1.1  ichiro 
     54  1.1  ichiro #include <arm/ixp12x0/ixp12x0_pcireg.h>
     55  1.1  ichiro #include <arm/ixp12x0/ixp12x0_clkreg.h>
     56  1.1  ichiro #include <arm/ixp12x0/ixp12x0var.h>
     57  1.1  ichiro 
     58  1.1  ichiro static int	ixpclk_match(struct device *, struct cfdata *, void *);
     59  1.1  ichiro static void	ixpclk_attach(struct device *, struct device *, void *);
     60  1.1  ichiro 
     61  1.1  ichiro int		gettick(void);
     62  1.1  ichiro void		rtcinit(void);
     63  1.1  ichiro 
     64  1.1  ichiro /* callback functions for intr_functions */
     65  1.1  ichiro static int      ixpclk_intr(void* arg);
     66  1.1  ichiro 
     67  1.1  ichiro struct ixpclk_softc {
     68  1.1  ichiro 	struct device		sc_dev;
     69  1.1  ichiro 	bus_addr_t		sc_baseaddr;
     70  1.1  ichiro 	bus_space_tag_t		sc_iot;
     71  1.1  ichiro 	bus_space_handle_t	sc_ioh;
     72  1.1  ichiro 
     73  1.1  ichiro 	u_int32_t		sc_clock_count;
     74  1.1  ichiro 	u_int32_t		sc_count_per_usec;
     75  1.1  ichiro 	u_int32_t		sc_coreclock_freq;
     76  1.1  ichiro };
     77  1.1  ichiro 
     78  1.1  ichiro #define XTAL_FREQ		3686400		/* 3.6864MHz */
     79  1.1  ichiro #define XTAL_FREQ3686400
     80  1.1  ichiro #undef XTAL_FREQ3787800
     81  1.1  ichiro #undef XTAL_FREQ3579500
     82  1.1  ichiro #define	MAX_CCF			22
     83  1.1  ichiro 
     84  1.1  ichiro #if defined(XTAL_FREQ3686400)
     85  1.1  ichiro static u_int32_t ccf_to_coreclock[MAX_CCF + 1] = {
     86  1.1  ichiro 	29491000,
     87  1.1  ichiro 	36865000,
     88  1.1  ichiro 	44237000,
     89  1.1  ichiro 	51610000,
     90  1.1  ichiro 	58982000,
     91  1.1  ichiro 	66355000,
     92  1.1  ichiro 	73728000,
     93  1.1  ichiro 	81101000,
     94  1.1  ichiro 	88474000,
     95  1.1  ichiro 	95846000,
     96  1.1  ichiro 	103219000,
     97  1.1  ichiro 	110592000,
     98  1.1  ichiro 	132710000,
     99  1.1  ichiro 	147456000,
    100  1.1  ichiro 	154829000,
    101  1.1  ichiro 	162202000,
    102  1.1  ichiro 	165890000,
    103  1.1  ichiro 	176947000,
    104  1.1  ichiro 	191693000,
    105  1.1  ichiro 	199066000,
    106  1.1  ichiro 	206438000,
    107  1.1  ichiro 	221184000,
    108  1.1  ichiro 	232243000,
    109  1.1  ichiro };
    110  1.1  ichiro #elif defined(XTAL_FREQ3787800)
    111  1.1  ichiro #elif defined(XTAL_FREQ3579500)
    112  1.1  ichiro #else
    113  1.1  ichiro #error
    114  1.1  ichiro #endif
    115  1.1  ichiro 
    116  1.1  ichiro static struct ixpclk_softc *ixpclk_sc = NULL;
    117  1.1  ichiro 
    118  1.1  ichiro #define TIMER_FREQUENCY         3686400         /* 3.6864MHz */
    119  1.1  ichiro #define TICKS_PER_MICROSECOND   (TIMER_FREQUENCY/1000000)
    120  1.1  ichiro 
    121  1.1  ichiro struct cfattach ixpclk_ca = {
    122  1.1  ichiro 	sizeof(struct ixpclk_softc), ixpclk_match, ixpclk_attach
    123  1.1  ichiro };
    124  1.1  ichiro 
    125  1.1  ichiro #define GET_TIMER_VALUE(sc)	(bus_space_read_4((sc)->sc_iot,		\
    126  1.1  ichiro 						  (sc)->sc_ioh,		\
    127  1.1  ichiro 						  IXPCLK_VALUE)		\
    128  1.1  ichiro 				 & IXPCL_CTV)
    129  1.1  ichiro 
    130  1.1  ichiro static int
    131  1.1  ichiro ixpclk_match(parent, match, aux)
    132  1.1  ichiro 	struct device *parent;
    133  1.1  ichiro 	struct cfdata *match;
    134  1.1  ichiro 	void *aux;
    135  1.1  ichiro {
    136  1.1  ichiro 	return (1);
    137  1.1  ichiro }
    138  1.1  ichiro 
    139  1.1  ichiro static void
    140  1.1  ichiro ixpclk_attach(parent, self, aux)
    141  1.1  ichiro 	struct device *parent;
    142  1.1  ichiro 	struct device *self;
    143  1.1  ichiro 	void *aux;
    144  1.1  ichiro {
    145  1.1  ichiro 	struct ixpclk_softc *sc = (struct ixpclk_softc*) self;
    146  1.1  ichiro 	struct ixpsip_attach_args *sa = aux;
    147  1.1  ichiro 
    148  1.1  ichiro 	printf("\n");
    149  1.1  ichiro 
    150  1.1  ichiro 	sc->sc_iot = sa->sa_iot;
    151  1.1  ichiro 	sc->sc_baseaddr = sa->sa_addr;
    152  1.1  ichiro 
    153  1.1  ichiro 	/* using first timer for system ticks */
    154  1.1  ichiro 	if (ixpclk_sc == NULL)
    155  1.1  ichiro 		ixpclk_sc = sc;
    156  1.1  ichiro 
    157  1.1  ichiro 	if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0,
    158  1.1  ichiro 			  &sc->sc_ioh))
    159  1.3  provos 		panic("%s: Cannot map registers", self->dv_xname);
    160  1.1  ichiro 
    161  1.1  ichiro 	/* disable all channel and clear interrupt status */
    162  1.1  ichiro 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXPCLK_CONTROL,
    163  1.1  ichiro 			  IXPCL_DISABLE | IXPCL_PERIODIC | IXPCL_STP_CORE);
    164  1.1  ichiro 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXPCLK_CLEAR, 0);
    165  1.1  ichiro 	printf("%s: IXP12x0 Interval Timer\n",  sc->sc_dev.dv_xname);
    166  1.1  ichiro }
    167  1.1  ichiro 
    168  1.1  ichiro /*
    169  1.1  ichiro  * ixpclk_intr:
    170  1.1  ichiro  *
    171  1.1  ichiro  *	Handle the hardclock interrupt.
    172  1.1  ichiro  */
    173  1.1  ichiro static int
    174  1.1  ichiro ixpclk_intr(void *arg)
    175  1.1  ichiro 
    176  1.1  ichiro {
    177  1.1  ichiro 	/* XXX XXX */
    178  1.1  ichiro 	if (!(IXPREG(IXPPCI_IRQ_RAW_STATUS)
    179  1.1  ichiro 	      & (1U << (IXPPCI_INTR_T1 - SYS_NIRQ))))
    180  1.1  ichiro 		return (0);
    181  1.1  ichiro 
    182  1.1  ichiro 	bus_space_write_4(ixpclk_sc->sc_iot, ixpclk_sc->sc_ioh,
    183  1.1  ichiro 			  IXPCLK_CLEAR, 1);
    184  1.1  ichiro 
    185  1.1  ichiro 	hardclock((struct clockframe*) arg);
    186  1.1  ichiro 	return (1);
    187  1.1  ichiro }
    188  1.1  ichiro 
    189  1.1  ichiro /*
    190  1.1  ichiro  * setstatclockrate:
    191  1.1  ichiro  *
    192  1.1  ichiro  *	Set the rate of the statistics clock.
    193  1.1  ichiro  *
    194  1.1  ichiro  *	We assume that hz is either stathz or profhz, and that neither
    195  1.1  ichiro  *	will change after being set by cpu_initclocks().  We could
    196  1.1  ichiro  *	recalculate the intervals here, but that would be a pain.
    197  1.1  ichiro  */
    198  1.1  ichiro void
    199  1.1  ichiro setstatclockrate(hz)
    200  1.1  ichiro 	int hz;
    201  1.1  ichiro {
    202  1.1  ichiro 	/* use hardclock */
    203  1.1  ichiro 
    204  1.1  ichiro 	/* XXX should I use TIMER2? */
    205  1.1  ichiro }
    206  1.1  ichiro 
    207  1.1  ichiro /*
    208  1.1  ichiro  * cpu_initclocks:
    209  1.1  ichiro  *
    210  1.1  ichiro  *	Initialize the clock and get them going.
    211  1.1  ichiro  */
    212  1.1  ichiro void
    213  1.1  ichiro cpu_initclocks()
    214  1.1  ichiro {
    215  1.1  ichiro 	struct ixpclk_softc*	sc = ixpclk_sc;
    216  1.1  ichiro 	u_int32_t		ccf;
    217  1.1  ichiro 
    218  1.1  ichiro 	stathz = profhz = 0;
    219  1.1  ichiro 
    220  1.1  ichiro 	printf("clock: hz = %d stathz = %d\n", hz, stathz);
    221  1.1  ichiro 
    222  1.1  ichiro 	ccf = IXPREG(IXP12X0_PLL_CFG) & IXP12X0_PLL_CFG_CCF;
    223  1.1  ichiro 	sc->sc_coreclock_freq = ccf_to_coreclock[ccf];
    224  1.1  ichiro 
    225  1.1  ichiro 	printf("pll_cfg:ccf = %x coreclock frequency = %dHz\n",
    226  1.1  ichiro 	       ccf, sc->sc_coreclock_freq);
    227  1.1  ichiro 
    228  1.1  ichiro 	sc->sc_clock_count = sc->sc_coreclock_freq / hz;
    229  1.1  ichiro 	sc->sc_count_per_usec = sc->sc_coreclock_freq / 10000000;
    230  1.1  ichiro 
    231  1.1  ichiro 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXPCLK_CLEAR, IXPT_CLEAR);
    232  1.1  ichiro 
    233  1.1  ichiro 	ixp12x0_intr_establish(IXPPCI_INTR_T1, IPL_CLOCK, ixpclk_intr, NULL);
    234  1.1  ichiro 
    235  1.1  ichiro 	IXPREG(IXPPCI_IRQ_ENABLE_SET) = (1U << (IXPPCI_INTR_T1 - SYS_NIRQ));
    236  1.1  ichiro 
    237  1.1  ichiro 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXPCLK_LOAD,
    238  1.1  ichiro 			  sc->sc_clock_count);
    239  1.1  ichiro 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXPCLK_CONTROL,
    240  1.1  ichiro 			  IXPCL_ENABLE | IXPCL_PERIODIC
    241  1.1  ichiro 			  | IXPCL_STP_CORE);
    242  1.1  ichiro }
    243  1.1  ichiro 
    244  1.1  ichiro int
    245  1.1  ichiro gettick()
    246  1.1  ichiro {
    247  1.1  ichiro 	int counter;
    248  1.1  ichiro 	u_int savedints;
    249  1.1  ichiro 	savedints = disable_interrupts(I32_bit);
    250  1.1  ichiro 
    251  1.1  ichiro 	counter = GET_TIMER_VALUE(ixpclk_sc);
    252  1.1  ichiro 
    253  1.1  ichiro 	restore_interrupts(savedints);
    254  1.1  ichiro 	return counter;
    255  1.1  ichiro }
    256  1.1  ichiro 
    257  1.1  ichiro /*
    258  1.1  ichiro  * microtime:
    259  1.1  ichiro  *
    260  1.1  ichiro  *	Fill in the specified timeval struct with the current time
    261  1.1  ichiro  *	accurate to the microsecond.
    262  1.1  ichiro  */
    263  1.1  ichiro void
    264  1.1  ichiro microtime(tvp)
    265  1.1  ichiro 	register struct timeval *tvp;
    266  1.1  ichiro {
    267  1.1  ichiro 	u_int			oldirqstate;
    268  1.1  ichiro 	u_int32_t		counts;
    269  1.1  ichiro 	static struct timeval	lasttv;
    270  1.1  ichiro 
    271  1.1  ichiro 	if (ixpclk_sc == NULL) {
    272  1.1  ichiro #ifdef DEBUG
    273  1.1  ichiro 		printf("microtime: called befor initialize ixpclk\n");
    274  1.1  ichiro #endif
    275  1.1  ichiro 		tvp->tv_sec = 0;
    276  1.1  ichiro 		tvp->tv_usec = 0;
    277  1.1  ichiro 		return;
    278  1.1  ichiro 	}
    279  1.1  ichiro 
    280  1.1  ichiro 	oldirqstate = disable_interrupts(I32_bit);
    281  1.1  ichiro 
    282  1.1  ichiro 	counts = ixpclk_sc->sc_clock_count - GET_TIMER_VALUE(ixpclk_sc);
    283  1.1  ichiro 
    284  1.1  ichiro         /* Fill in the timeval struct. */
    285  1.1  ichiro 	*tvp = time;
    286  1.1  ichiro 	tvp->tv_usec += counts / ixpclk_sc->sc_count_per_usec;
    287  1.1  ichiro 
    288  1.1  ichiro         /* Make sure microseconds doesn't overflow. */
    289  1.1  ichiro 	while (tvp->tv_usec >= 1000000) {
    290  1.1  ichiro 		tvp->tv_usec -= 1000000;
    291  1.1  ichiro 		tvp->tv_sec++;
    292  1.1  ichiro 	}
    293  1.1  ichiro 
    294  1.1  ichiro         /* Make sure the time has advanced. */
    295  1.1  ichiro 	if (tvp->tv_sec == lasttv.tv_sec &&
    296  1.1  ichiro 	    tvp->tv_usec <= lasttv.tv_usec) {
    297  1.1  ichiro 		tvp->tv_usec = lasttv.tv_usec + 1;
    298  1.1  ichiro 		if (tvp->tv_usec >= 1000000) {
    299  1.1  ichiro 			tvp->tv_usec -= 1000000;
    300  1.1  ichiro 			tvp->tv_sec++;
    301  1.1  ichiro 		}
    302  1.1  ichiro 	}
    303  1.1  ichiro 
    304  1.1  ichiro 	lasttv = *tvp;
    305  1.1  ichiro 
    306  1.1  ichiro 	restore_interrupts(oldirqstate);
    307  1.1  ichiro }
    308  1.1  ichiro 
    309  1.1  ichiro /*
    310  1.1  ichiro  * delay:
    311  1.1  ichiro  *
    312  1.1  ichiro  *	Delay for at least N microseconds.
    313  1.1  ichiro  */
    314  1.1  ichiro void
    315  1.1  ichiro delay(usecs)
    316  1.1  ichiro 	u_int usecs;
    317  1.1  ichiro {
    318  1.1  ichiro 	u_int32_t tick, otick, delta;
    319  1.1  ichiro 	int j, csec, usec;
    320  1.1  ichiro 
    321  1.1  ichiro 	csec = usecs / 10000;
    322  1.1  ichiro 	usec = usecs % 10000;
    323  1.1  ichiro 
    324  1.1  ichiro 	if (ixpclk_sc == NULL) {
    325  1.1  ichiro 		static u_int32_t	coreclock_freq = 0;
    326  1.1  ichiro 
    327  1.1  ichiro #ifdef DEBUG
    328  1.1  ichiro 		printf("delay: called befor initialize ixpclk\n");
    329  1.1  ichiro #endif
    330  1.1  ichiro 		if (coreclock_freq == 0) {
    331  1.1  ichiro 			coreclock_freq
    332  1.1  ichiro 				= ccf_to_coreclock[IXPREG(IXP12X0_PLL_CFG)
    333  1.1  ichiro 						   & IXP12X0_PLL_CFG_CCF];
    334  1.1  ichiro 		}
    335  1.1  ichiro 
    336  1.1  ichiro 		usecs = (TIMER_FREQUENCY / 100) * csec
    337  1.1  ichiro 			+ (TIMER_FREQUENCY / 100) * usec / 10000;
    338  1.1  ichiro 		/* clock isn't initialized yet */
    339  1.1  ichiro 		for(; usecs > 0; usecs--)
    340  1.1  ichiro 			for(j = 100; j > 0; j--)
    341  1.1  ichiro 				;
    342  1.1  ichiro 		return;
    343  1.1  ichiro 	}
    344  1.1  ichiro 
    345  1.1  ichiro 	usecs = (ixpclk_sc->sc_coreclock_freq / 100) * csec
    346  1.1  ichiro 		+ (ixpclk_sc->sc_coreclock_freq / 100) * usec / 10000;
    347  1.1  ichiro 
    348  1.1  ichiro 	otick = gettick();
    349  1.1  ichiro 
    350  1.1  ichiro 	while (1) {
    351  1.1  ichiro 		for(j = 100; j > 0; j--)
    352  1.1  ichiro 			;
    353  1.1  ichiro 		tick = gettick();
    354  1.1  ichiro 
    355  1.1  ichiro 		delta = otick > tick
    356  1.1  ichiro 			? otick - tick
    357  1.1  ichiro 			: otick - tick + IXPCL_ITV + 1;
    358  1.1  ichiro 		if (delta > usecs)
    359  1.1  ichiro 			break;
    360  1.1  ichiro 		usecs -= delta;
    361  1.1  ichiro 		otick = tick;
    362  1.1  ichiro 	}
    363  1.1  ichiro }
    364  1.1  ichiro 
    365  1.1  ichiro void
    366  1.1  ichiro resettodr()
    367  1.1  ichiro {
    368  1.1  ichiro }
    369  1.1  ichiro 
    370  1.1  ichiro void
    371  1.1  ichiro inittodr(base)
    372  1.1  ichiro 	time_t base;
    373  1.1  ichiro {
    374  1.1  ichiro 	time.tv_sec = base;
    375  1.1  ichiro 	time.tv_usec = 0;
    376  1.1  ichiro }
    377