Home | History | Annotate | Line # | Download | only in s3c2xx0
s3c2800.c revision 1.7.8.1
      1  1.7.8.1     kent /*	$NetBSD: s3c2800.c,v 1.7.8.1 2005/04/29 11:28:03 kent Exp $ */
      2      1.1      bsh 
      3      1.1      bsh /*
      4      1.7      bsh  * Copyright (c) 2002, 2003 Fujitsu Component Limited
      5      1.7      bsh  * Copyright (c) 2002, 2003 Genetec Corporation
      6      1.1      bsh  * All rights reserved.
      7      1.1      bsh  *
      8      1.1      bsh  * Redistribution and use in source and binary forms, with or without
      9      1.1      bsh  * modification, are permitted provided that the following conditions
     10      1.1      bsh  * are met:
     11      1.1      bsh  * 1. Redistributions of source code must retain the above copyright
     12      1.1      bsh  *    notice, this list of conditions and the following disclaimer.
     13      1.1      bsh  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1      bsh  *    notice, this list of conditions and the following disclaimer in the
     15      1.1      bsh  *    documentation and/or other materials provided with the distribution.
     16      1.1      bsh  * 3. Neither the name of The Fujitsu Component Limited nor the name of
     17      1.1      bsh  *    Genetec corporation may not be used to endorse or promote products
     18      1.1      bsh  *    derived from this software without specific prior written permission.
     19      1.1      bsh  *
     20      1.1      bsh  * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
     21      1.1      bsh  * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     22      1.1      bsh  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     23      1.1      bsh  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24      1.1      bsh  * DISCLAIMED.  IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
     25      1.1      bsh  * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26      1.1      bsh  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27      1.1      bsh  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
     28      1.1      bsh  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     29      1.1      bsh  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     30      1.1      bsh  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     31      1.1      bsh  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32      1.1      bsh  * SUCH DAMAGE.
     33      1.1      bsh  */
     34      1.1      bsh 
     35      1.5    lukem #include <sys/cdefs.h>
     36  1.7.8.1     kent __KERNEL_RCSID(0, "$NetBSD: s3c2800.c,v 1.7.8.1 2005/04/29 11:28:03 kent Exp $");
     37      1.1      bsh 
     38      1.1      bsh #include <sys/param.h>
     39      1.1      bsh #include <sys/systm.h>
     40      1.1      bsh #include <sys/device.h>
     41      1.1      bsh #include <sys/kernel.h>
     42      1.1      bsh #include <sys/reboot.h>
     43      1.1      bsh 
     44      1.1      bsh #include <machine/cpu.h>
     45      1.1      bsh #include <machine/bus.h>
     46      1.1      bsh 
     47      1.1      bsh #include <arm/cpufunc.h>
     48      1.1      bsh #include <arm/mainbus/mainbus.h>
     49      1.1      bsh #include <arm/s3c2xx0/s3c2800reg.h>
     50      1.1      bsh #include <arm/s3c2xx0/s3c2800var.h>
     51      1.1      bsh 
     52      1.1      bsh #include "locators.h"
     53      1.4      bsh #include "opt_cpuoptions.h"
     54      1.1      bsh 
     55      1.1      bsh /* prototypes */
     56      1.1      bsh static int	s3c2800_match(struct device *, struct cfdata *, void *);
     57      1.1      bsh static void	s3c2800_attach(struct device *, struct device *, void *);
     58      1.1      bsh static int	s3c2800_search(struct device *, struct cfdata *, void *);
     59      1.1      bsh 
     60      1.1      bsh /* attach structures */
     61      1.1      bsh CFATTACH_DECL(ssio, sizeof(struct s3c2800_softc), s3c2800_match, s3c2800_attach,
     62      1.1      bsh     NULL, NULL);
     63      1.1      bsh 
     64      1.1      bsh extern struct bus_space s3c2xx0_bs_tag;
     65      1.1      bsh 
     66      1.1      bsh struct s3c2xx0_softc *s3c2xx0_softc;
     67      1.1      bsh 
     68      1.1      bsh static int
     69      1.1      bsh s3c2800_print(void *aux, const char *name)
     70      1.1      bsh {
     71      1.1      bsh 	struct s3c2xx0_attach_args *sa = (struct s3c2xx0_attach_args *) aux;
     72      1.1      bsh 
     73      1.1      bsh 	if (sa->sa_size)
     74      1.2  thorpej 		aprint_normal(" addr 0x%lx", sa->sa_addr);
     75      1.1      bsh 	if (sa->sa_size > 1)
     76      1.2  thorpej 		aprint_normal("-0x%lx", sa->sa_addr + sa->sa_size - 1);
     77      1.1      bsh 	if (sa->sa_intr != SSIOCF_INTR_DEFAULT)
     78      1.2  thorpej 		aprint_normal(" intr %d", sa->sa_intr);
     79      1.1      bsh 	if (sa->sa_index != SSIOCF_INDEX_DEFAULT)
     80      1.2  thorpej 		aprint_normal(" unit %d", sa->sa_index);
     81      1.1      bsh 
     82      1.1      bsh 	return (UNCONF);
     83      1.1      bsh }
     84      1.1      bsh 
     85      1.1      bsh int
     86      1.1      bsh s3c2800_match(struct device *parent, struct cfdata *match, void *aux)
     87      1.1      bsh {
     88      1.1      bsh 	return 1;
     89      1.1      bsh }
     90      1.1      bsh 
     91      1.1      bsh void
     92      1.1      bsh s3c2800_attach(struct device *parent, struct device *self, void *aux)
     93      1.1      bsh {
     94      1.1      bsh 	struct s3c2800_softc *sc = (struct s3c2800_softc *) self;
     95      1.1      bsh 	bus_space_tag_t iot;
     96      1.1      bsh 	const char *which_registers;	/* for panic message */
     97      1.1      bsh 
     98      1.1      bsh #define FAIL(which)  do { \
     99      1.1      bsh 	which_registers=(which); goto abort; }while(/*CONSTCOND*/0)
    100      1.1      bsh 
    101      1.1      bsh 	s3c2xx0_softc = &(sc->sc_sx);
    102      1.1      bsh 	sc->sc_sx.sc_iot = iot = &s3c2xx0_bs_tag;
    103      1.1      bsh 
    104      1.1      bsh 	if (bus_space_map(iot,
    105      1.1      bsh 		S3C2800_INTCTL_BASE, S3C2800_INTCTL_SIZE,
    106      1.1      bsh 		BUS_SPACE_MAP_LINEAR, &sc->sc_sx.sc_intctl_ioh))
    107      1.1      bsh 		FAIL("intc");
    108      1.1      bsh 	/* tell register addresses to interrupt handler */
    109      1.1      bsh 	s3c2800_intr_init(sc);
    110      1.1      bsh 
    111      1.1      bsh 	/* Map the GPIO registers */
    112      1.1      bsh 	if (bus_space_map(iot, S3C2800_GPIO_BASE, S3C2800_GPIO_SIZE,
    113      1.1      bsh 		0, &sc->sc_sx.sc_gpio_ioh))
    114      1.1      bsh 		FAIL("GPIO");
    115      1.1      bsh 
    116      1.1      bsh #if 0
    117      1.1      bsh 	/* Map the DMA controller registers */
    118      1.1      bsh 	if (bus_space_map(iot, S3C2800_DMAC_BASE, S3C2800_DMAC_SIZE,
    119      1.1      bsh 		0, &sc->sc_sx.sc_dmach))
    120      1.1      bsh 		FAIL("DMAC");
    121      1.1      bsh #endif
    122      1.1      bsh 
    123      1.1      bsh 	/* Memory controller */
    124      1.1      bsh 	if (bus_space_map(iot, S3C2800_MEMCTL_BASE,
    125      1.1      bsh 		S3C2800_MEMCTL_SIZE, 0, &sc->sc_sx.sc_memctl_ioh))
    126      1.1      bsh 		FAIL("MEMC");
    127      1.1      bsh 	/* Clock manager */
    128      1.1      bsh 	if (bus_space_map(iot, S3C2800_CLKMAN_BASE,
    129      1.1      bsh 		S3C2800_CLKMAN_SIZE, 0, &sc->sc_sx.sc_clkman_ioh))
    130      1.1      bsh 		FAIL("CLK");
    131      1.1      bsh 
    132      1.1      bsh #if 0
    133      1.1      bsh 	/* Real time clock */
    134      1.1      bsh 	if (bus_space_map(iot, S3C2800_RTC_BASE,
    135      1.1      bsh 		S3C2800_RTC_SIZE, 0, &sc->sc_sx.sc_rtc_ioh))
    136      1.1      bsh 		FAIL("RTC");
    137      1.1      bsh #endif
    138      1.1      bsh 
    139      1.1      bsh 	if (bus_space_map(iot, S3C2800_TIMER0_BASE,
    140      1.1      bsh 		S3C2800_TIMER_SIZE, 0, &sc->sc_tmr0_ioh))
    141      1.1      bsh 		FAIL("TIMER0");
    142      1.1      bsh 
    143      1.1      bsh 	if (bus_space_map(iot, S3C2800_TIMER1_BASE,
    144      1.1      bsh 		S3C2800_TIMER_SIZE, 0, &sc->sc_tmr1_ioh))
    145      1.3      bsh 		FAIL("TIMER1");
    146      1.1      bsh 
    147      1.4      bsh 	/* calculate current clock frequency */
    148      1.6      bsh 	s3c2800_clock_freq(&sc->sc_sx);
    149      1.7      bsh 	aprint_normal(": fclk %d MHz hclk %d MHz pclk %d MHz\n",
    150      1.4      bsh 	       sc->sc_sx.sc_fclk / 1000000, sc->sc_sx.sc_hclk / 1000000,
    151      1.4      bsh 	       sc->sc_sx.sc_pclk / 1000000);
    152      1.7      bsh 	aprint_naive("\n");
    153      1.1      bsh 
    154      1.1      bsh 	/*
    155      1.1      bsh 	 *  Attach devices.
    156      1.1      bsh 	 */
    157      1.1      bsh 	config_search(s3c2800_search, self, NULL);
    158      1.1      bsh 	return;
    159      1.1      bsh 
    160      1.1      bsh abort:
    161      1.1      bsh 	panic("%s: unable to map %s registers",
    162      1.1      bsh 	    self->dv_xname, which_registers);
    163      1.1      bsh 
    164      1.1      bsh #undef FAIL
    165      1.1      bsh }
    166      1.1      bsh 
    167      1.1      bsh int
    168      1.1      bsh s3c2800_search(struct device * parent, struct cfdata * cf, void *aux)
    169      1.1      bsh {
    170      1.1      bsh 	struct s3c2800_softc *sc = (struct s3c2800_softc *) parent;
    171      1.1      bsh 	struct s3c2xx0_attach_args aa;
    172      1.1      bsh 
    173      1.1      bsh 	aa.sa_sc = sc;
    174      1.1      bsh 	aa.sa_iot = sc->sc_sx.sc_iot;
    175      1.1      bsh 	aa.sa_addr = cf->cf_loc[SSIOCF_ADDR];
    176      1.1      bsh 	aa.sa_size = cf->cf_loc[SSIOCF_SIZE];
    177      1.1      bsh 	aa.sa_index = cf->cf_loc[SSIOCF_INDEX];
    178      1.1      bsh 	aa.sa_intr = cf->cf_loc[SSIOCF_INTR];
    179      1.1      bsh 
    180      1.1      bsh 	if (config_match(parent, cf, &aa))
    181      1.1      bsh 		config_attach(parent, cf, &aa, s3c2800_print);
    182      1.1      bsh 
    183      1.1      bsh 	return 0;
    184      1.1      bsh }
    185      1.1      bsh 
    186      1.4      bsh /*
    187      1.4      bsh  * Issue software reset command.
    188      1.4      bsh  * called with MMU off.
    189      1.4      bsh  */
    190      1.1      bsh void
    191      1.1      bsh s3c2800_softreset(void)
    192      1.1      bsh {
    193      1.4      bsh 	*(volatile unsigned int *)(S3C2800_CLKMAN_BASE + CLKMAN_SWRCON)
    194      1.4      bsh 	    = SWRCON_SWR;
    195      1.4      bsh }
    196      1.4      bsh 
    197      1.4      bsh /*
    198      1.4      bsh  * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
    199  1.7.8.1     kent  *
    200  1.7.8.1     kent  * s3c2800_clock_freq2() is meant to be called from kernel startup routines.
    201  1.7.8.1     kent  * s3c2800_clock_freq() is for after kernel initialization is done.
    202      1.4      bsh  */
    203      1.4      bsh void
    204  1.7.8.1     kent s3c2800_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, int *pclk)
    205      1.4      bsh {
    206  1.7.8.1     kent 	uint32_t pllcon, clkcon;
    207      1.4      bsh 	int mdiv, pdiv, sdiv;
    208  1.7.8.1     kent 	int f, h, p;
    209      1.4      bsh 
    210  1.7.8.1     kent 	pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_PLLCON);
    211  1.7.8.1     kent 	clkcon = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKCON);
    212      1.4      bsh 
    213      1.4      bsh 	mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT;
    214      1.4      bsh 	pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT;
    215      1.4      bsh 	sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT;
    216      1.4      bsh 
    217  1.7.8.1     kent 	f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv));
    218  1.7.8.1     kent 	h = f;
    219      1.4      bsh 	if (clkcon & CLKCON_HCLK)
    220  1.7.8.1     kent 		h /= 2;
    221  1.7.8.1     kent 	p = h;
    222      1.4      bsh 	if (clkcon & CLKCON_PCLK)
    223  1.7.8.1     kent 		p /= 2;
    224  1.7.8.1     kent 
    225  1.7.8.1     kent 	if (fclk) *fclk = f;
    226  1.7.8.1     kent 	if (hclk) *hclk = h;
    227  1.7.8.1     kent 	if (pclk) *pclk = p;
    228  1.7.8.1     kent }
    229  1.7.8.1     kent 
    230  1.7.8.1     kent void
    231  1.7.8.1     kent s3c2800_clock_freq(struct s3c2xx0_softc *sc)
    232  1.7.8.1     kent {
    233  1.7.8.1     kent 	s3c2800_clock_freq2(
    234  1.7.8.1     kent 		(vaddr_t)bus_space_vaddr(sc->sc_iot, sc->sc_clkman_ioh),
    235  1.7.8.1     kent 		&sc->sc_fclk, &sc->sc_hclk, &sc->sc_pclk);
    236      1.1      bsh }
    237      1.4      bsh 
    238