1 /* $NetBSD: pxa2x0.c,v 1.17 2008/05/03 23:06:06 martin Exp $ */
4 * Copyright (c) 2002, 2005 Genetec Corporation. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
36 * Autoconfiguration support for the Intel PXA2[15]0 application
37 * processor. This code is derived from arm/sa11x0/sa11x0.c
41 * Copyright (c) 2001, The NetBSD Foundation, Inc. All rights reserved.
43 * This code is derived from software contributed to The NetBSD Foundation
44 * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
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.
55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 * POSSIBILITY OF SUCH DAMAGE.
69 * Shin Takemura and PocketBSD Project. All rights reserved.
71 * Redistribution and use in source and binary forms, with or without
72 * modification, are permitted provided that the following conditions
74 * 1. Redistributions of source code must retain the above copyright
75 * notice, this list of conditions and the following disclaimer.
76 * 2. Redistributions in binary form must reproduce the above copyright
77 * notice, this list of conditions and the following disclaimer in the
78 * documentation and/or other materials provided with the distribution.
79 * 3. All advertising materials mentioning features or use of this software
80 * must display the following acknowledgement:
81 * This product includes software developed by the PocketBSD project
82 * and its contributors.
83 * 4. Neither the name of the project nor the names of its contributors
84 * may be used to endorse or promote products derived from this software
85 * without specific prior written permission.
87 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
88 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
90 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
91 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
92 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
93 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
94 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
95 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
96 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
101 #include <sys/cdefs.h>
102 __KERNEL_RCSID(0, "$NetBSD: pxa2x0.c,v 1.17 2008/05/03 23:06:06 martin Exp $");
107 #include "pxadmac.h" /* Not yet */
110 #include "locators.h"
112 #include <sys/param.h>
113 #include <sys/systm.h>
114 #include <sys/device.h>
115 #include <sys/kernel.h>
116 #include <sys/reboot.h>
118 #include <machine/cpu.h>
119 #include <machine/bus.h>
121 #include <arm/cpufunc.h>
122 #include <arm/mainbus/mainbus.h>
123 #include <arm/xscale/pxa2x0cpu.h>
124 #include <arm/xscale/pxa2x0reg.h>
125 #include <arm/xscale/pxa2x0var.h>
126 #include <arm/xscale/xscalereg.h>
129 struct device sc_dev
;
130 bus_space_tag_t sc_bust
;
131 bus_dma_tag_t sc_dmat
;
132 bus_space_handle_t sc_bush_clk
;
133 bus_space_handle_t sc_bush_mem
;
137 static int pxaip_match(struct device
*, struct cfdata
*, void *);
138 static void pxaip_attach(struct device
*, struct device
*, void *);
139 static int pxaip_search(struct device
*, struct cfdata
*,
140 const int *, void *);
141 static void pxaip_attach_critical(struct pxaip_softc
*);
142 static int pxaip_print(void *, const char *);
144 static int pxaip_measure_cpuclock(struct pxaip_softc
*);
146 #if defined(CPU_XSCALE_PXA250) && defined(CPU_XSCALE_PXA270)
147 # define SUPPORTED_CPU "PXA250 and PXA270"
148 #elif defined(CPU_XSCALE_PXA250)
149 # define SUPPORTED_CPU "PXA250"
150 #elif defined(CPU_XSCALE_PXA270)
151 # define SUPPORTED_CPU "PXA270"
153 # define SUPPORTED_CPU "none of PXA2xx"
156 /* attach structures */
157 CFATTACH_DECL(pxaip
, sizeof(struct pxaip_softc
),
158 pxaip_match
, pxaip_attach
, NULL
, NULL
);
160 static struct pxaip_softc
*pxaip_sc
;
161 static vaddr_t pxamemctl_regs
;
162 #define MEMCTL_BOOTSTRAP_REG(reg) \
163 (*((volatile uint32_t *)(pxamemctl_regs + (reg))))
164 static vaddr_t pxaclkman_regs
;
165 #define CLKMAN_BOOTSTRAP_REG(reg) \
166 (*((volatile uint32_t *)(pxaclkman_regs + (reg))))
169 pxaip_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
172 #if !defined(CPU_XSCALE_PXA270)
177 #if !defined(CPU_XSCALE_PXA250)
184 #if defined(CPU_XSCALE_PXA250) + defined(CPU_XSCALE_PXA270) != 2
186 aprint_error("Kernel is configured for %s, but CPU is %s\n",
187 SUPPORTED_CPU
, __CPU_IS_PXA270
? "PXA270" : "PXA250");
193 pxaip_attach(struct device
*parent
, struct device
*self
, void *aux
)
195 struct pxaip_softc
*sc
= (struct pxaip_softc
*)self
;
199 sc
->sc_bust
= &pxa2x0_bs_tag
;
200 sc
->sc_dmat
= &pxa2x0_bus_dma_tag
;
202 aprint_normal(": PXA2x0 Onchip Peripheral Bus\n");
204 if (bus_space_map(sc
->sc_bust
, PXA2X0_CLKMAN_BASE
, PXA2X0_CLKMAN_SIZE
,
205 0, &sc
->sc_bush_clk
))
206 panic("pxaip_attach: failed to map CLKMAN");
208 if (bus_space_map(sc
->sc_bust
, PXA2X0_MEMCTL_BASE
, PXA2X0_MEMCTL_SIZE
,
209 0, &sc
->sc_bush_mem
))
210 panic("pxaip_attach: failed to map MEMCTL");
213 * Calculate clock speed
214 * This takes 2 secs at most.
216 cpuclock
= pxaip_measure_cpuclock(sc
) / 1000;
217 printf("%s: CPU clock = %d.%03d MHz\n", self
->dv_xname
,
218 cpuclock
/1000, cpuclock
%1000 );
220 aprint_normal("%s: kernel is configured for " SUPPORTED_CPU
221 ", cpu type is %s\n",
223 __CPU_IS_PXA270
? "PXA270" : "PXA250");
226 * Attach critical devices
228 pxaip_attach_critical(sc
);
231 * Attach all other devices
233 config_search_ia(pxaip_search
, self
, "pxaip", sc
);
237 pxaip_search(struct device
*parent
, struct cfdata
*cf
,
238 const int *ldesc
, void *aux
)
240 struct pxaip_softc
*sc
= aux
;
241 struct pxaip_attach_args aa
;
243 aa
.pxa_iot
= sc
->sc_bust
;
244 aa
.pxa_dmat
= sc
->sc_dmat
;
245 aa
.pxa_name
= cf
->cf_name
;
246 aa
.pxa_addr
= cf
->cf_loc
[PXAIPCF_ADDR
];
247 aa
.pxa_size
= cf
->cf_loc
[PXAIPCF_SIZE
];
248 aa
.pxa_index
= cf
->cf_loc
[PXAIPCF_INDEX
];
249 aa
.pxa_intr
= cf
->cf_loc
[PXAIPCF_INTR
];
251 if (config_match(parent
, cf
, &aa
))
252 config_attach(parent
, cf
, &aa
, pxaip_print
);
258 pxaip_attach_critical(struct pxaip_softc
*sc
)
260 struct pxaip_attach_args aa
;
262 aa
.pxa_iot
= sc
->sc_bust
;
263 aa
.pxa_dmat
= sc
->sc_dmat
;
264 aa
.pxa_name
= "pxaintc";
265 aa
.pxa_addr
= PXA2X0_INTCTL_BASE
;
266 aa
.pxa_size
= PXA2X0_INTCTL_SIZE
;
267 aa
.pxa_intr
= PXAIPCF_INTR_DEFAULT
;
268 if (config_found(&sc
->sc_dev
, &aa
, pxaip_print
) == NULL
)
269 panic("pxaip_attach_critical: failed to attach INTC!");
272 aa
.pxa_iot
= sc
->sc_bust
;
273 aa
.pxa_dmat
= sc
->sc_dmat
;
274 aa
.pxa_name
= "pxagpio";
275 aa
.pxa_addr
= PXA2X0_GPIO_BASE
;
276 aa
.pxa_size
= PXA2X0_GPIO_SIZE
;
277 aa
.pxa_intr
= PXAIPCF_INTR_DEFAULT
;
278 if (config_found(&sc
->sc_dev
, &aa
, pxaip_print
) == NULL
)
279 panic("pxaip_attach_critical: failed to attach GPIO!");
283 aa
.pxa_iot
= sc
->sc_bust
;
284 aa
.pxa_dmat
= sc
->sc_dmat
;
285 aa
.pxa_name
= "pxaidmac";
286 aa
.pxa_addr
= PXA2X0_DMAC_BASE
;
287 aa
.pxa_size
= PXA2X0_DMAC_SIZE
;
288 aa
.pxa_intr
= PXA2X0_INT_DMA
;
289 if (config_found(&sc
->sc_dev
, &aa
, pxaip_print
) == NULL
)
290 panic("pxaip_attach_critical: failed to attach DMAC!");
295 pxaip_print(void *aux
, const char *name
)
297 struct pxaip_attach_args
*sa
= (struct pxaip_attach_args
*)aux
;
299 if (sa
->pxa_addr
!= PXAIPCF_ADDR_DEFAULT
) {
300 aprint_normal(" addr 0x%lx", sa
->pxa_addr
);
301 if (sa
->pxa_size
> PXAIPCF_SIZE_DEFAULT
)
302 aprint_normal("-0x%lx", sa
->pxa_addr
+ sa
->pxa_size
-1);
304 if (sa
->pxa_intr
!= PXAIPCF_INTR_DEFAULT
)
305 aprint_normal(" intr %d", sa
->pxa_intr
);
310 static inline uint32_t
311 read_clock_counter_xsc1(void)
314 __asm
volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (x
) );
319 static inline uint32_t
320 read_clock_counter_xsc2(void)
323 __asm
volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (x
) );
329 pxaip_measure_cpuclock(struct pxaip_softc
*sc
)
331 uint32_t rtc0
, rtc1
, start
, end
;
333 bus_space_handle_t ioh
;
335 int is_xsc2
= CPU_IS_PXA270
;
336 #define read_clock_counter() (is_xsc2 ? read_clock_counter_xsc2() : \
337 read_clock_counter_xsc1())
339 if (bus_space_map(sc
->sc_bust
, PXA2X0_RTC_BASE
, PXA2X0_RTC_SIZE
, 0,
341 panic("pxaip_measure_cpuclock: can't map RTC");
343 irq
= disable_interrupts(I32_bit
|F32_bit
);
347 "mrc p14, 0, %0, c0, c1, 0" : "=r" (pmcr_save
));
348 /* Enable clock counter */
350 "mcr p14, 0, %0, c0, c1, 0" : : "r" (PMNC_E
|PMNC_C
));
354 "mrc p14, 0, %0, c0, c0, 0" : "=r" (pmcr_save
));
355 /* Enable clock counter */
357 "mcr p14, 0, %0, c0, c0, 0" : : "r" (PMNC_E
|PMNC_C
));
360 rtc0
= bus_space_read_4(sc
->sc_bust
, ioh
, RTC_RCNR
);
361 /* Wait for next second starts */
362 while ((rtc1
= bus_space_read_4(sc
->sc_bust
, ioh
, RTC_RCNR
)) == rtc0
)
364 start
= read_clock_counter();
365 while(rtc1
== bus_space_read_4(sc
->sc_bust
, ioh
, RTC_RCNR
))
366 ; /* Wait for 1sec */
367 end
= read_clock_counter();
371 "mcr p14, 0, %0, c0, c1, 0" : : "r" (pmcr_save
));
374 "mcr p14, 0, %0, c0, c0, 0" : : "r" (pmcr_save
));
375 restore_interrupts(irq
);
377 bus_space_unmap(sc
->sc_bust
, ioh
, PXA2X0_RTC_SIZE
);
383 pxa2x0_turbo_mode(int f
)
385 __asm
volatile("mcr p14, 0, %0, c6, c0, 0" : : "r" (f
));
389 pxa2x0_probe_sdram(vaddr_t memctl_va
, paddr_t
*start
, paddr_t
*size
)
391 u_int32_t mdcnfg
, dwid
, dcac
, drac
, dnb
;
394 mdcnfg
= *((volatile u_int32_t
*)(memctl_va
+ MEMCTL_MDCNFG
));
397 * Scan all 4 SDRAM banks
399 for (i
= 0; i
< PXA2X0_SDRAM_BANKS
; i
++) {
406 if ((i
== 0 && (mdcnfg
& MDCNFG_DE0
) == 0) ||
407 (i
== 1 && (mdcnfg
& MDCNFG_DE1
) == 0))
409 dwid
= mdcnfg
>> MDCNFD_DWID01_SHIFT
;
410 dcac
= mdcnfg
>> MDCNFD_DCAC01_SHIFT
;
411 drac
= mdcnfg
>> MDCNFD_DRAC01_SHIFT
;
412 dnb
= mdcnfg
>> MDCNFD_DNB01_SHIFT
;
417 if ((i
== 2 && (mdcnfg
& MDCNFG_DE2
) == 0) ||
418 (i
== 3 && (mdcnfg
& MDCNFG_DE3
) == 0))
420 dwid
= mdcnfg
>> MDCNFD_DWID23_SHIFT
;
421 dcac
= mdcnfg
>> MDCNFD_DCAC23_SHIFT
;
422 drac
= mdcnfg
>> MDCNFD_DRAC23_SHIFT
;
423 dnb
= mdcnfg
>> MDCNFD_DNB23_SHIFT
;
426 panic("pxa2x0_probe_sdram: impossible");
429 dwid
= 2 << (1 - (dwid
& MDCNFD_DWID_MASK
)); /* 16/32 width */
430 dcac
= 1 << ((dcac
& MDCNFD_DCAC_MASK
) + 8); /* 8-11 columns */
431 drac
= 1 << ((drac
& MDCNFD_DRAC_MASK
) + 11); /* 11-13 rows */
432 dnb
= 2 << (dnb
& MDCNFD_DNB_MASK
); /* # of banks */
434 size
[i
] = (paddr_t
)(dwid
* dcac
* drac
* dnb
);
435 start
[i
] = PXA2X0_SDRAM0_START
+ (i
* PXA2X0_SDRAM_BANK_SIZE
);
440 pxa2x0_memctl_bootstrap(vaddr_t va
)
447 pxa2x0_memctl_read(int reg
)
449 struct pxaip_softc
*sc
;
451 bus_space_handle_t ioh
;
453 if (__predict_true(pxaip_sc
!= NULL
)) {
456 ioh
= sc
->sc_bush_mem
;
457 return (bus_space_read_4(iot
, ioh
, reg
));
458 } else if (__predict_true(pxamemctl_regs
!= 0)) {
459 return (MEMCTL_BOOTSTRAP_REG(reg
));
461 panic("pxa2x0_memctl_read: not bootstrapped");
466 pxa2x0_memctl_write(int reg
, uint32_t val
)
468 struct pxaip_softc
*sc
;
470 bus_space_handle_t ioh
;
472 if (__predict_true(pxaip_sc
!= NULL
)) {
475 ioh
= sc
->sc_bush_mem
;
476 bus_space_write_4(iot
, ioh
, reg
, val
);
477 } else if (__predict_true(pxamemctl_regs
!= 0)) {
478 MEMCTL_BOOTSTRAP_REG(reg
) = val
;
480 panic("pxa2x0_memctl_write: not bootstrapped");
486 pxa2x0_clkman_bootstrap(vaddr_t va
)
493 pxa2x0_clkman_config(u_int clk
, bool enable
)
495 struct pxaip_softc
*sc
;
497 bus_space_handle_t ioh
;
500 if (__predict_true(pxaip_sc
!= NULL
)) {
503 ioh
= sc
->sc_bush_clk
;
505 rv
= bus_space_read_4(iot
, ioh
, CLKMAN_CKEN
);
509 bus_space_write_4(iot
, ioh
, CLKMAN_CKEN
, rv
);
511 } else if (__predict_true(pxaclkman_regs
!= 0)) {
512 rv
= CLKMAN_BOOTSTRAP_REG(CLKMAN_CKEN
);
516 CLKMAN_BOOTSTRAP_REG(CLKMAN_CKEN
) = rv
;
519 panic("pxa2x0_clkman_config: not bootstrapped");