1 /* $NetBSD: s3c2800.c,v 1.4.2.5 2005/11/10 13:55:16 skrll Exp $ */
4 * Copyright (c) 2002, 2003 Fujitsu Component Limited
5 * Copyright (c) 2002, 2003 Genetec Corporation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of The Fujitsu Component Limited nor the name of
17 * Genetec corporation may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY FUJITSU COMPONENT LIMITED AND GENETEC
21 * CORPORATION ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL FUJITSU COMPONENT LIMITED OR GENETEC
25 * CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: s3c2800.c,v 1.4.2.5 2005/11/10 13:55:16 skrll Exp $");
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 #include <sys/kernel.h>
42 #include <sys/reboot.h>
44 #include <machine/cpu.h>
45 #include <machine/bus.h>
47 #include <arm/cpufunc.h>
48 #include <arm/mainbus/mainbus.h>
49 #include <arm/s3c2xx0/s3c2800reg.h>
50 #include <arm/s3c2xx0/s3c2800var.h>
53 #include "opt_cpuoptions.h"
56 static int s3c2800_match(struct device
*, struct cfdata
*, void *);
57 static void s3c2800_attach(struct device
*, struct device
*, void *);
58 static int s3c2800_search(struct device
*, struct cfdata
*,
61 /* attach structures */
62 CFATTACH_DECL(ssio
, sizeof(struct s3c2800_softc
), s3c2800_match
, s3c2800_attach
,
65 extern struct bus_space s3c2xx0_bs_tag
;
67 struct s3c2xx0_softc
*s3c2xx0_softc
;
70 s3c2800_print(void *aux
, const char *name
)
72 struct s3c2xx0_attach_args
*sa
= (struct s3c2xx0_attach_args
*) aux
;
75 aprint_normal(" addr 0x%lx", sa
->sa_addr
);
77 aprint_normal("-0x%lx", sa
->sa_addr
+ sa
->sa_size
- 1);
78 if (sa
->sa_intr
!= SSIOCF_INTR_DEFAULT
)
79 aprint_normal(" intr %d", sa
->sa_intr
);
80 if (sa
->sa_index
!= SSIOCF_INDEX_DEFAULT
)
81 aprint_normal(" unit %d", sa
->sa_index
);
87 s3c2800_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
93 s3c2800_attach(struct device
*parent
, struct device
*self
, void *aux
)
95 struct s3c2800_softc
*sc
= (struct s3c2800_softc
*) self
;
97 const char *which_registers
; /* for panic message */
99 #define FAIL(which) do { \
100 which_registers=(which); goto abort; }while(/*CONSTCOND*/0)
102 s3c2xx0_softc
= &(sc
->sc_sx
);
103 sc
->sc_sx
.sc_iot
= iot
= &s3c2xx0_bs_tag
;
105 if (bus_space_map(iot
,
106 S3C2800_INTCTL_BASE
, S3C2800_INTCTL_SIZE
,
107 BUS_SPACE_MAP_LINEAR
, &sc
->sc_sx
.sc_intctl_ioh
))
109 /* tell register addresses to interrupt handler */
110 s3c2800_intr_init(sc
);
112 /* Map the GPIO registers */
113 if (bus_space_map(iot
, S3C2800_GPIO_BASE
, S3C2800_GPIO_SIZE
,
114 0, &sc
->sc_sx
.sc_gpio_ioh
))
118 /* Map the DMA controller registers */
119 if (bus_space_map(iot
, S3C2800_DMAC_BASE
, S3C2800_DMAC_SIZE
,
120 0, &sc
->sc_sx
.sc_dmach
))
124 /* Memory controller */
125 if (bus_space_map(iot
, S3C2800_MEMCTL_BASE
,
126 S3C2800_MEMCTL_SIZE
, 0, &sc
->sc_sx
.sc_memctl_ioh
))
129 if (bus_space_map(iot
, S3C2800_CLKMAN_BASE
,
130 S3C2800_CLKMAN_SIZE
, 0, &sc
->sc_sx
.sc_clkman_ioh
))
134 /* Real time clock */
135 if (bus_space_map(iot
, S3C2800_RTC_BASE
,
136 S3C2800_RTC_SIZE
, 0, &sc
->sc_sx
.sc_rtc_ioh
))
140 if (bus_space_map(iot
, S3C2800_TIMER0_BASE
,
141 S3C2800_TIMER_SIZE
, 0, &sc
->sc_tmr0_ioh
))
144 if (bus_space_map(iot
, S3C2800_TIMER1_BASE
,
145 S3C2800_TIMER_SIZE
, 0, &sc
->sc_tmr1_ioh
))
148 /* calculate current clock frequency */
149 s3c2800_clock_freq(&sc
->sc_sx
);
150 aprint_normal(": fclk %d MHz hclk %d MHz pclk %d MHz\n",
151 sc
->sc_sx
.sc_fclk
/ 1000000, sc
->sc_sx
.sc_hclk
/ 1000000,
152 sc
->sc_sx
.sc_pclk
/ 1000000);
158 config_search_ia(s3c2800_search
, self
, "ssio", NULL
);
162 panic("%s: unable to map %s registers",
163 self
->dv_xname
, which_registers
);
169 s3c2800_search(struct device
* parent
, struct cfdata
* cf
,
170 const int *ldesc
, void *aux
)
172 struct s3c2800_softc
*sc
= (struct s3c2800_softc
*) parent
;
173 struct s3c2xx0_attach_args aa
;
176 aa
.sa_iot
= sc
->sc_sx
.sc_iot
;
177 aa
.sa_addr
= cf
->cf_loc
[SSIOCF_ADDR
];
178 aa
.sa_size
= cf
->cf_loc
[SSIOCF_SIZE
];
179 aa
.sa_index
= cf
->cf_loc
[SSIOCF_INDEX
];
180 aa
.sa_intr
= cf
->cf_loc
[SSIOCF_INTR
];
182 if (config_match(parent
, cf
, &aa
))
183 config_attach(parent
, cf
, &aa
, s3c2800_print
);
189 * Issue software reset command.
190 * called with MMU off.
193 s3c2800_softreset(void)
195 *(volatile unsigned int *)(S3C2800_CLKMAN_BASE
+ CLKMAN_SWRCON
)
200 * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register.
202 * s3c2800_clock_freq2() is meant to be called from kernel startup routines.
203 * s3c2800_clock_freq() is for after kernel initialization is done.
206 s3c2800_clock_freq2(vaddr_t clkman_base
, int *fclk
, int *hclk
, int *pclk
)
208 uint32_t pllcon
, clkcon
;
209 int mdiv
, pdiv
, sdiv
;
212 pllcon
= *(volatile uint32_t *)(clkman_base
+ CLKMAN_PLLCON
);
213 clkcon
= *(volatile uint32_t *)(clkman_base
+ CLKMAN_CLKCON
);
215 mdiv
= (pllcon
& PLLCON_MDIV_MASK
) >> PLLCON_MDIV_SHIFT
;
216 pdiv
= (pllcon
& PLLCON_PDIV_MASK
) >> PLLCON_PDIV_SHIFT
;
217 sdiv
= (pllcon
& PLLCON_SDIV_MASK
) >> PLLCON_SDIV_SHIFT
;
219 f
= ((mdiv
+ 8) * S3C2XX0_XTAL_CLK
) / ((pdiv
+ 2) * (1 << sdiv
));
221 if (clkcon
& CLKCON_HCLK
)
224 if (clkcon
& CLKCON_PCLK
)
233 s3c2800_clock_freq(struct s3c2xx0_softc
*sc
)
236 (vaddr_t
)bus_space_vaddr(sc
->sc_iot
, sc
->sc_clkman_ioh
),
237 &sc
->sc_fclk
, &sc
->sc_hclk
, &sc
->sc_pclk
);