Home | History | Annotate | Line # | Download | only in xscale
pxa2x0.c revision 1.14
      1 /*	$NetBSD: pxa2x0.c,v 1.14 2006/12/16 03:37:03 ober Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2002, 2005  Genetec Corporation.  All rights reserved.
      5  * Written by Hiroyuki Bessho for Genetec Corporation.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed for the NetBSD Project by
     18  *	Genetec Corporation.
     19  * 4. The name of Genetec Corporation may not be used to endorse or
     20  *    promote products derived from this software without specific prior
     21  *    written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     25  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     26  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
     27  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     33  * POSSIBILITY OF SUCH DAMAGE.
     34  *
     35  *
     36  * Autoconfiguration support for the Intel PXA2[15]0 application
     37  * processor. This code is derived from arm/sa11x0/sa11x0.c
     38  */
     39 
     40 /*-
     41  * Copyright (c) 2001, The NetBSD Foundation, Inc.  All rights reserved.
     42  *
     43  * This code is derived from software contributed to The NetBSD Foundation
     44  * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
     45  *
     46  * Redistribution and use in source and binary forms, with or without
     47  * modification, are permitted provided that the following conditions
     48  * are met:
     49  * 1. Redistributions of source code must retain the above copyright
     50  *    notice, this list of conditions and the following disclaimer.
     51  * 2. Redistributions in binary form must reproduce the above copyright
     52  *    notice, this list of conditions and the following disclaimer in the
     53  *    documentation and/or other materials provided with the distribution.
     54  * 3. All advertising materials mentioning features or use of this software
     55  *    must display the following acknowledgement:
     56  *      This product includes software developed by the NetBSD
     57  *      Foundation, Inc. and its contributors.
     58  * 4. Neither the name of The NetBSD Foundation nor the names of its
     59  *    contributors may be used to endorse or promote products derived
     60  *    from this software without specific prior written permission.
     61  */
     62 /*-
     63  * Copyright (c) 1999
     64  *         Shin Takemura and PocketBSD Project. All rights reserved.
     65  *
     66  * Redistribution and use in source and binary forms, with or without
     67  * modification, are permitted provided that the following conditions
     68  * are met:
     69  * 1. Redistributions of source code must retain the above copyright
     70  *    notice, this list of conditions and the following disclaimer.
     71  * 2. Redistributions in binary form must reproduce the above copyright
     72  *    notice, this list of conditions and the following disclaimer in the
     73  *    documentation and/or other materials provided with the distribution.
     74  * 3. All advertising materials mentioning features or use of this software
     75  *    must display the following acknowledgement:
     76  *	This product includes software developed by the PocketBSD project
     77  *	and its contributors.
     78  * 4. Neither the name of the project nor the names of its contributors
     79  *    may be used to endorse or promote products derived from this software
     80  *    without specific prior written permission.
     81  *
     82  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     83  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     84  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     85  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     86  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     87  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     88  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     89  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     90  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     91  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     92  * SUCH DAMAGE.
     93  *
     94  */
     95 
     96 #include <sys/cdefs.h>
     97 __KERNEL_RCSID(0, "$NetBSD: pxa2x0.c,v 1.14 2006/12/16 03:37:03 ober Exp $");
     98 
     99 #include "pxaintc.h"
    100 #include "pxagpio.h"
    101 #if 0
    102 #include "pxadmac.h"	/* Not yet */
    103 #endif
    104 
    105 #include "locators.h"
    106 
    107 #include <sys/param.h>
    108 #include <sys/systm.h>
    109 #include <sys/device.h>
    110 #include <sys/kernel.h>
    111 #include <sys/reboot.h>
    112 
    113 #include <machine/cpu.h>
    114 #include <machine/bus.h>
    115 
    116 #include <arm/cpufunc.h>
    117 #include <arm/mainbus/mainbus.h>
    118 #include <arm/xscale/pxa2x0cpu.h>
    119 #include <arm/xscale/pxa2x0reg.h>
    120 #include <arm/xscale/pxa2x0var.h>
    121 #include <arm/xscale/xscalereg.h>
    122 
    123 struct pxaip_softc {
    124 	struct device sc_dev;
    125 	bus_space_tag_t sc_bust;
    126 	bus_dma_tag_t sc_dmat;
    127 	bus_space_handle_t sc_bush_clk;
    128 };
    129 
    130 /* prototypes */
    131 static int	pxaip_match(struct device *, struct cfdata *, void *);
    132 static void	pxaip_attach(struct device *, struct device *, void *);
    133 static int 	pxaip_search(struct device *, struct cfdata *,
    134 			     const int *, void *);
    135 static void	pxaip_attach_critical(struct pxaip_softc *);
    136 static int	pxaip_print(void *, const char *);
    137 
    138 static int	pxaip_measure_cpuclock(struct pxaip_softc *);
    139 
    140 #if defined(CPU_XSCALE_PXA250) && defined(CPU_XSCALE_PXA270)
    141 # define SUPPORTED_CPU	"PXA250 and PXA270"
    142 #elif defined(CPU_XSCALE_PXA250)
    143 # define SUPPORTED_CPU	"PXA250"
    144 #elif defined(CPU_XSCALE_PXA270)
    145 # define SUPPORTED_CPU	"PXA270"
    146 #else
    147 # define SUPPORTED_CPU	"none of PXA2xx"
    148 #endif
    149 
    150 /* attach structures */
    151 CFATTACH_DECL(pxaip, sizeof(struct pxaip_softc),
    152     pxaip_match, pxaip_attach, NULL, NULL);
    153 
    154 static struct pxaip_softc *pxaip_sc;
    155 static vaddr_t pxaclkman_regs;
    156 #define CLKMAN_BOOTSTRAP_REG(reg) \
    157 	(*((volatile uint32_t *)(pxaclkman_regs + (reg))))
    158 
    159 static int
    160 pxaip_match(struct device *parent, struct cfdata *match, void *aux)
    161 {
    162 
    163 #if	!defined(CPU_XSCALE_PXA270)
    164 	if (__CPU_IS_PXA270)
    165 		goto bad_config;
    166 #endif
    167 
    168 #if	!defined(CPU_XSCALE_PXA250)
    169 	if (__CPU_IS_PXA250)
    170 		goto bad_config;
    171 #endif
    172 
    173 	return 1;
    174 
    175 #if	defined(CPU_XSCALE_PXA250) + defined(CPU_XSCALE_PXA270) != 2
    176  bad_config:
    177 	aprint_error("Kernel is configured for %s, but CPU is %s\n",
    178 		     SUPPORTED_CPU, __CPU_IS_PXA270 ? "PXA270" : "PXA250");
    179 	return 0;
    180 #endif
    181 }
    182 
    183 static void
    184 pxaip_attach(struct device *parent, struct device *self, void *aux)
    185 {
    186 	struct pxaip_softc *sc = (struct pxaip_softc *)self;
    187 	int cpuclock;
    188 
    189 	pxaip_sc = sc;
    190 	sc->sc_bust = &pxa2x0_bs_tag;
    191 	sc->sc_dmat = &pxa2x0_bus_dma_tag;
    192 
    193 	aprint_normal(": PXA2x0 Onchip Peripheral Bus\n");
    194 
    195 	if (bus_space_map(sc->sc_bust, PXA2X0_CLKMAN_BASE, PXA2X0_CLKMAN_SIZE,
    196 	    0, &sc->sc_bush_clk))
    197 		panic("pxaip_attach: failed to map CLKMAN");
    198 
    199 	/*
    200 	 * Calculate clock speed
    201 	 * This takes 2 secs at most.
    202 	 */
    203 	cpuclock = pxaip_measure_cpuclock(sc) / 1000;
    204 	printf("%s: CPU clock = %d.%03d MHz\n", self->dv_xname,
    205 	    cpuclock/1000, cpuclock%1000 );
    206 
    207 	aprint_normal("%s: kernel is configured for " SUPPORTED_CPU
    208 		      ", cpu type is %s\n",
    209 		      self->dv_xname,
    210 		      __CPU_IS_PXA270 ? "PXA270" : "PXA250");
    211 
    212 	/*
    213 	 * Attach critical devices
    214 	 */
    215 	pxaip_attach_critical(sc);
    216 
    217 	/*
    218 	 * Attach all other devices
    219 	 */
    220 	config_search_ia(pxaip_search, self, "pxaip", sc);
    221 }
    222 
    223 static int
    224 pxaip_search(struct device *parent, struct cfdata *cf,
    225 	     const int *ldesc, void *aux)
    226 {
    227 	struct pxaip_softc *sc = aux;
    228 	struct pxaip_attach_args aa;
    229 
    230 	aa.pxa_iot = sc->sc_bust;
    231 	aa.pxa_dmat = sc->sc_dmat;
    232 	aa.pxa_addr = cf->cf_loc[PXAIPCF_ADDR];
    233 	aa.pxa_size = cf->cf_loc[PXAIPCF_SIZE];
    234 	aa.pxa_index = cf->cf_loc[PXAIPCF_INDEX];
    235 	aa.pxa_intr = cf->cf_loc[PXAIPCF_INTR];
    236 
    237 	if (config_match(parent, cf, &aa))
    238 		config_attach(parent, cf, &aa, pxaip_print);
    239 
    240 	return 0;
    241 }
    242 
    243 static void
    244 pxaip_attach_critical(struct pxaip_softc *sc)
    245 {
    246 	struct pxaip_attach_args aa;
    247 
    248 	aa.pxa_iot = sc->sc_bust;
    249 	aa.pxa_dmat = sc->sc_dmat;
    250 	aa.pxa_addr = PXA2X0_INTCTL_BASE;
    251 	aa.pxa_size = PXA2X0_INTCTL_SIZE;
    252 	aa.pxa_intr = PXAIPCF_INTR_DEFAULT;
    253 	if (config_found(&sc->sc_dev, &aa, pxaip_print) == NULL)
    254 		panic("pxaip_attach_critical: failed to attach INTC!");
    255 
    256 #if NPXAGPIO > 0
    257 	aa.pxa_iot = sc->sc_bust;
    258 	aa.pxa_dmat = sc->sc_dmat;
    259 	aa.pxa_addr = PXA2X0_GPIO_BASE;
    260 	aa.pxa_size = PXA2X0_GPIO_SIZE;
    261 	aa.pxa_intr = PXAIPCF_INTR_DEFAULT;
    262 	if (config_found(&sc->sc_dev, &aa, pxaip_print) == NULL)
    263 		panic("pxaip_attach_critical: failed to attach GPIO!");
    264 #endif
    265 
    266 #if NPXADMAC > 0
    267 	aa.pxa_iot = sc->sc_bust;
    268 	aa.pxa_dmat = sc->sc_dmat;
    269 	aa.pxa_addr = PXA2X0_DMAC_BASE;
    270 	aa.pxa_size = PXA2X0_DMAC_SIZE;
    271 	aa.pxa_intr = PXA2X0_INT_DMA;
    272 	if (config_found(&sc->sc_dev, &aa, pxaip_print) == NULL)
    273 		panic("pxaip_attach_critical: failed to attach DMAC!");
    274 #endif
    275 }
    276 
    277 static int
    278 pxaip_print(void *aux, const char *name)
    279 {
    280 	struct pxaip_attach_args *sa = (struct pxaip_attach_args*)aux;
    281 
    282 	if (sa->pxa_addr != PXAIPCF_ADDR_DEFAULT) {
    283 		aprint_normal(" addr 0x%lx", sa->pxa_addr);
    284 		if (sa->pxa_size > PXAIPCF_SIZE_DEFAULT)
    285 			aprint_normal("-0x%lx", sa->pxa_addr + sa->pxa_size-1);
    286 	}
    287 	if (sa->pxa_intr != PXAIPCF_INTR_DEFAULT)
    288 		aprint_normal(" intr %d", sa->pxa_intr);
    289 
    290 	return (UNCONF);
    291 }
    292 
    293 static inline uint32_t
    294 read_clock_counter_xsc1(void)
    295 {
    296 	uint32_t x;
    297 	__asm volatile("mrc	p14, 0, %0, c1, c0, 0" : "=r" (x) );
    298 
    299 	return x;
    300 }
    301 
    302 static inline uint32_t
    303 read_clock_counter_xsc2(void)
    304 {
    305 	uint32_t x;
    306 	__asm volatile("mrc	p14, 0, %0, c1, c1, 0" : "=r" (x) );
    307 
    308 	return x;
    309 }
    310 
    311 static int
    312 pxaip_measure_cpuclock(struct pxaip_softc *sc)
    313 {
    314 	uint32_t rtc0, rtc1, start, end;
    315 	uint32_t pmcr_save;
    316 	bus_space_handle_t ioh;
    317 	int irq;
    318 	int is_xsc2 = CPU_IS_PXA270;
    319 #define	read_clock_counter()	(is_xsc2 ? read_clock_counter_xsc2() : \
    320 					read_clock_counter_xsc1())
    321 
    322 	if (bus_space_map(sc->sc_bust, PXA2X0_RTC_BASE, PXA2X0_RTC_SIZE, 0,
    323 	    &ioh))
    324 		panic("pxaip_measure_cpuclock: can't map RTC");
    325 
    326 	irq = disable_interrupts(I32_bit|F32_bit);
    327 
    328 	if (is_xsc2) {
    329 		__asm volatile(
    330 			"mrc p14, 0, %0, c0, c1, 0" : "=r" (pmcr_save));
    331 		/* Enable clock counter */
    332 		__asm volatile(
    333 			"mcr p14, 0, %0, c0, c1, 0" : : "r" (PMNC_E|PMNC_C));
    334 	}
    335 	else {
    336 		__asm volatile(
    337 			"mrc p14, 0, %0, c0, c0, 0" : "=r" (pmcr_save));
    338 		/* Enable clock counter */
    339 		__asm volatile(
    340 			"mcr p14, 0, %0, c0, c0, 0" : : "r" (PMNC_E|PMNC_C));
    341 	}
    342 
    343 	rtc0 = bus_space_read_4(sc->sc_bust, ioh, RTC_RCNR);
    344 	/* Wait for next second starts */
    345 	while ((rtc1 = bus_space_read_4(sc->sc_bust, ioh, RTC_RCNR)) == rtc0)
    346 		;
    347 	start = read_clock_counter();
    348 	while(rtc1 == bus_space_read_4(sc->sc_bust, ioh, RTC_RCNR))
    349 		;		/* Wait for 1sec */
    350 	end = read_clock_counter();
    351 
    352 	if (is_xsc2)
    353 		__asm volatile(
    354 			"mcr p14, 0, %0, c0, c1, 0" : : "r" (pmcr_save));
    355 	else
    356 		__asm volatile(
    357 			"mcr p14, 0, %0, c0, c0, 0" : : "r" (pmcr_save));
    358 	restore_interrupts(irq);
    359 
    360 	bus_space_unmap(sc->sc_bust, ioh, PXA2X0_RTC_SIZE);
    361 
    362 	return end - start;
    363 }
    364 
    365 void
    366 pxa2x0_turbo_mode(int f)
    367 {
    368 	__asm volatile("mcr p14, 0, %0, c6, c0, 0" : : "r" (f));
    369 }
    370 
    371 void
    372 pxa2x0_probe_sdram(vaddr_t memctl_va, paddr_t *start, paddr_t *size)
    373 {
    374 	u_int32_t mdcnfg, dwid, dcac, drac, dnb;
    375 	int i;
    376 
    377 	mdcnfg = *((volatile u_int32_t *)(memctl_va + MEMCTL_MDCNFG));
    378 
    379 	/*
    380 	 * Scan all 4 SDRAM banks
    381 	 */
    382 	for (i = 0; i < PXA2X0_SDRAM_BANKS; i++) {
    383 		start[i] = 0;
    384 		size[i] = 0;
    385 
    386 		switch (i) {
    387 		case 0:
    388 		case 1:
    389 			if ((i == 0 && (mdcnfg & MDCNFG_DE0) == 0) ||
    390 			    (i == 1 && (mdcnfg & MDCNFG_DE1) == 0))
    391 				continue;
    392 			dwid = mdcnfg >> MDCNFD_DWID01_SHIFT;
    393 			dcac = mdcnfg >> MDCNFD_DCAC01_SHIFT;
    394 			drac = mdcnfg >> MDCNFD_DRAC01_SHIFT;
    395 			dnb = mdcnfg >> MDCNFD_DNB01_SHIFT;
    396 			break;
    397 
    398 		case 2:
    399 		case 3:
    400 			if ((i == 2 && (mdcnfg & MDCNFG_DE2) == 0) ||
    401 			    (i == 3 && (mdcnfg & MDCNFG_DE3) == 0))
    402 				continue;
    403 			dwid = mdcnfg >> MDCNFD_DWID23_SHIFT;
    404 			dcac = mdcnfg >> MDCNFD_DCAC23_SHIFT;
    405 			drac = mdcnfg >> MDCNFD_DRAC23_SHIFT;
    406 			dnb = mdcnfg >> MDCNFD_DNB23_SHIFT;
    407 			break;
    408 		default:
    409 			panic("pxa2x0_probe_sdram: impossible");
    410 		}
    411 
    412 		dwid = 2 << (1 - (dwid & MDCNFD_DWID_MASK));  /* 16/32 width */
    413 		dcac = 1 << ((dcac & MDCNFD_DCAC_MASK) + 8);  /* 8-11 columns */
    414 		drac = 1 << ((drac & MDCNFD_DRAC_MASK) + 11); /* 11-13 rows */
    415 		dnb = 2 << (dnb & MDCNFD_DNB_MASK);	      /* # of banks */
    416 
    417 		size[i] = (paddr_t)(dwid * dcac * drac * dnb);
    418 		start[i] = PXA2X0_SDRAM0_START + (i * PXA2X0_SDRAM_BANK_SIZE);
    419 	}
    420 }
    421 
    422 void
    423 pxa2x0_clkman_bootstrap(vaddr_t va)
    424 {
    425 
    426 	pxaclkman_regs = va;
    427 }
    428 
    429 void
    430 pxa2x0_clkman_config(u_int clk, boolean_t enable)
    431 {
    432 	struct pxaip_softc *sc;
    433 	bus_space_tag_t iot;
    434 	bus_space_handle_t ioh;
    435 	uint32_t rv;
    436 
    437 	if (__predict_true(pxaip_sc != NULL)) {
    438 		sc = pxaip_sc;
    439 		iot = sc->sc_bust;
    440 		ioh = sc->sc_bush_clk;
    441 
    442 		rv = bus_space_read_4(iot, ioh, CLKMAN_CKEN);
    443 		rv &= ~clk;
    444 		if (enable)
    445 			rv |= clk;
    446 		bus_space_write_4(iot, ioh, CLKMAN_CKEN, rv);
    447 		return;
    448 	}
    449 
    450 	if (__predict_true(pxaclkman_regs != 0)) {
    451 		rv = CLKMAN_BOOTSTRAP_REG(CLKMAN_CKEN);
    452 		rv &= ~clk;
    453 		if (enable)
    454 			rv |= clk;
    455 		CLKMAN_BOOTSTRAP_REG(CLKMAN_CKEN) = rv;
    456 		return;
    457 	}
    458 
    459 	panic("pxa2x0_clkman_config: not bootstrapped");
    460 }
    461