]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/arm/at91/at91rm9200.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / arm / at91 / at91rm9200.c
1 /*-
2  * Copyright (c) 2005 Olivier Houchard.  All rights reserved.
3  * Copyright (c) 2010 Greg Ansley.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36
37 #define _ARM32_BUS_DMA_PRIVATE
38 #include <machine/bus.h>
39
40 #include <arm/at91/at91var.h>
41 #include <arm/at91/at91rm92reg.h>
42 #include <arm/at91/at91_aicreg.h>
43 #include <arm/at91/at91_pmcreg.h>
44 #include <arm/at91/at91_pmcvar.h>
45
46 struct at91rm92_softc {
47         device_t dev;
48         bus_space_tag_t sc_st;
49         bus_space_handle_t sc_sh;
50         bus_space_handle_t sc_sys_sh;
51         bus_space_handle_t sc_aic_sh;
52         bus_space_handle_t sc_dbg_sh;
53         bus_space_handle_t sc_matrix_sh;
54 };
55 /*
56  * Standard priority levels for the system.  0 is lowest and 7 is highest.
57  * These values are the ones Atmel uses for its Linux port, which differ
58  * a little form the ones that are in the standard distribution.  Also,
59  * the ones marked with 'TWEEK' are different based on experience.
60  */
61 static const int at91_irq_prio[32] =
62 {
63         7,      /* Advanced Interrupt Controller (FIQ) */
64         7,      /* System Peripherals */
65         1,      /* Parallel IO Controller A */
66         1,      /* Parallel IO Controller B */
67         1,      /* Parallel IO Controller C */
68         1,      /* Parallel IO Controller D */
69         5,      /* USART 0 */
70         5,      /* USART 1 */
71         5,      /* USART 2 */
72         5,      /* USART 3 */
73         0,      /* Multimedia Card Interface */
74         2,      /* USB Device Port */
75         4,      /* Two-Wire Interface */                /* TWEEK */
76         5,      /* Serial Peripheral Interface */
77         4,      /* Serial Synchronous Controller 0 */
78         6,      /* Serial Synchronous Controller 1 */   /* TWEEK */
79         4,      /* Serial Synchronous Controller 2 */
80         0,      /* Timer Counter 0 */
81         6,      /* Timer Counter 1 */                   /* TWEEK */
82         0,      /* Timer Counter 2 */
83         0,      /* Timer Counter 3 */
84         0,      /* Timer Counter 4 */
85         0,      /* Timer Counter 5 */
86         2,      /* USB Host port */
87         3,      /* Ethernet MAC */
88         0,      /* Advanced Interrupt Controller (IRQ0) */
89         0,      /* Advanced Interrupt Controller (IRQ1) */
90         0,      /* Advanced Interrupt Controller (IRQ2) */
91         0,      /* Advanced Interrupt Controller (IRQ3) */
92         0,      /* Advanced Interrupt Controller (IRQ4) */
93         0,      /* Advanced Interrupt Controller (IRQ5) */
94         0       /* Advanced Interrupt Controller (IRQ6) */
95 };
96
97 #define DEVICE(_name, _id, _unit)               \
98         {                                       \
99                 _name, _unit,                   \
100                 AT91RM92_ ## _id ##_BASE,       \
101                 AT91RM92_ ## _id ## _SIZE,      \
102                 AT91RM92_IRQ_ ## _id            \
103         }
104
105 static const struct cpu_devs at91_devs[] =
106 {
107         DEVICE("at91_pmc",   PMC,    0),
108         DEVICE("at91_st",    ST,     0),
109         DEVICE("at91_pio",   PIOA,   0),
110         DEVICE("at91_pio",   PIOB,   1),
111         DEVICE("at91_pio",   PIOC,   2),
112         DEVICE("at91_pio",   PIOD,   3),
113         DEVICE("at91_rtc",   RTC,    0),
114
115         DEVICE("at91_mci",   MCI,    0),
116         DEVICE("at91_twi",   TWI,    0),
117         DEVICE("at91_udp",   UDP,    0),
118         DEVICE("ate",        EMAC,   0),
119         DEVICE("at91_ssc",   SSC0,   0),
120         DEVICE("at91_ssc",   SSC1,   1),
121         DEVICE("at91_ssc",   SSC2,   2),
122         DEVICE("spi",        SPI,    0),
123
124         DEVICE("uart",       DBGU,   0),
125         DEVICE("uart",       USART0, 1),
126         DEVICE("uart",       USART1, 2),
127         DEVICE("uart",       USART2, 3),
128         DEVICE("uart",       USART3, 4),
129         DEVICE("at91_aic",   AIC,    0),
130         DEVICE("at91_mc",    MC,     0),
131         DEVICE("at91_tc",    TC0,    0),
132         DEVICE("at91_tc",    TC1,    1),
133         DEVICE("ohci",       OHCI,   0),
134         DEVICE("af91_cfata", CF,     0),
135         {       0, 0, 0, 0, 0 }
136 };
137
138 static void
139 at91_add_child(device_t dev, int prio, const char *name, int unit,
140     bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
141 {
142         device_t kid;
143         struct at91_ivar *ivar;
144
145         kid = device_add_child_ordered(dev, prio, name, unit);
146         if (kid == NULL) {
147             printf("Can't add child %s%d ordered\n", name, unit);
148             return;
149         }
150         ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
151         if (ivar == NULL) {
152                 device_delete_child(dev, kid);
153                 printf("Can't add alloc ivar\n");
154                 return;
155         }
156         device_set_ivars(kid, ivar);
157         resource_list_init(&ivar->resources);
158         if (irq0 != -1) {
159                 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
160                 if (irq0 != AT91RM92_IRQ_SYSTEM)
161                         at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0);
162         }
163         if (irq1 != 0)
164                 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
165         if (irq2 != 0)
166                 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
167         if (addr != 0 && addr < AT91RM92_BASE) 
168                 addr += AT91RM92_BASE;
169         if (addr != 0)
170                 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
171 }
172
173 static void
174 at91_cpu_add_builtin_children(device_t dev)
175 {
176         int i;
177         const struct cpu_devs *walker;
178         
179         for (i = 1, walker = at91_devs; walker->name; i++, walker++) {
180                 at91_add_child(dev, i, walker->name, walker->unit,
181                     walker->mem_base, walker->mem_len, walker->irq0,
182                     walker->irq1, walker->irq2);
183         }
184 }
185
186 static uint32_t
187 at91_pll_outb(int freq)
188 {
189
190         if (freq > 155000000)
191                 return (0x0000);
192         else 
193                 return (0x8000);
194 }
195
196 static void
197 at91_identify(driver_t *drv, device_t parent)
198 {
199
200         if (at91_cpu_is(AT91_CPU_RM9200)) {
201                 at91_add_child(parent, 0, "at91rm920", 0, 0, 0, -1, 0, 0);
202                 at91_cpu_add_builtin_children(parent);
203         }
204 }
205
206 static int
207 at91_probe(device_t dev)
208 {
209
210         if (at91_cpu_is(AT91_CPU_RM9200)) {
211                 device_set_desc(dev, "AT91RM9200");
212                 return (0);
213         }
214         return (ENXIO);
215 }
216
217 static int
218 at91_attach(device_t dev)
219 {
220         struct at91_pmc_clock *clk;
221         struct at91rm92_softc *sc = device_get_softc(dev);
222         int i;
223
224         struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));
225
226         sc->sc_st = at91sc->sc_st;
227         sc->sc_sh = at91sc->sc_sh;
228         sc->dev = dev;
229
230         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE,
231             AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0)
232                 panic("Enable to map system registers");
233
234         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_DBGU_BASE,
235             AT91RM92_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
236                 panic("Enable to map DBGU registers");
237
238         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_AIC_BASE,
239             AT91RM92_AIC_SIZE, &sc->sc_aic_sh) != 0)
240                 panic("Enable to map system registers");
241
242         /* XXX Hack to tell atmelarm about the AIC */
243         at91sc->sc_aic_sh = sc->sc_aic_sh;
244         at91sc->sc_irq_system = AT91RM92_IRQ_SYSTEM;
245
246         for (i = 0; i < 32; i++) {
247                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 
248                     i * 4, i);
249                 /* Priority. */
250                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
251                     at91_irq_prio[i]);
252                 if (i < 8)
253                         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
254                             1);
255         }
256
257         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
258         /* No debug. */
259         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
260         /* Disable and clear all interrupts. */
261         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
262         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);
263
264         /* Disable all interrupts for RTC (0xe24 == RTC_IDR) */
265         bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff);
266
267         /* Disable all interrupts for the SDRAM controller */
268         bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff);
269
270         /* Disable all interrupts for DBGU */
271         bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);
272
273         /* Update USB device port clock info */
274         clk = at91_pmc_clock_ref("udpck");
275         clk->pmc_mask  = PMC_SCER_UDP;
276         at91_pmc_clock_deref(clk);
277
278         /* Update USB host port clock info */
279         clk = at91_pmc_clock_ref("uhpck");
280         clk->pmc_mask  = PMC_SCER_UHP;
281         at91_pmc_clock_deref(clk);
282
283         /* Each SOC has different PLL contraints */
284         clk = at91_pmc_clock_ref("plla");
285         clk->pll_min_in    = RM9200_PLL_A_MIN_IN_FREQ;          /*   1 MHz */
286         clk->pll_max_in    = RM9200_PLL_A_MAX_IN_FREQ;          /*  32 MHz */
287         clk->pll_min_out   = RM9200_PLL_A_MIN_OUT_FREQ;         /*  80 MHz */
288         clk->pll_max_out   = RM9200_PLL_A_MAX_OUT_FREQ;         /* 180 MHz */
289         clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT;
290         clk->pll_mul_mask  = RM9200_PLL_A_MUL_MASK;
291         clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT;
292         clk->pll_div_mask  = RM9200_PLL_A_DIV_MASK;
293         clk->set_outb      = at91_pll_outb;
294         at91_pmc_clock_deref(clk);
295
296         clk = at91_pmc_clock_ref("pllb");
297         clk->pll_min_in    = RM9200_PLL_B_MIN_IN_FREQ;          /* 100 KHz */
298         clk->pll_max_in    = RM9200_PLL_B_MAX_IN_FREQ;          /*  32 MHz */
299         clk->pll_min_out   = RM9200_PLL_B_MIN_OUT_FREQ;         /*  30 MHz */
300         clk->pll_max_out   = RM9200_PLL_B_MAX_OUT_FREQ;         /* 240 MHz */
301         clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT;
302         clk->pll_mul_mask  = RM9200_PLL_B_MUL_MASK;
303         clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT;
304         clk->pll_div_mask  = RM9200_PLL_B_DIV_MASK;
305         clk->set_outb      = at91_pll_outb;
306         at91_pmc_clock_deref(clk);
307
308         return (0);
309 }
310
311 static device_method_t at91_methods[] = {
312         DEVMETHOD(device_probe, at91_probe),
313         DEVMETHOD(device_attach, at91_attach),
314         DEVMETHOD(device_identify, at91_identify),
315         {0, 0},
316 };
317
318 static driver_t at91rm92_driver = {
319         "at91rm920",
320         at91_methods,
321         sizeof(struct at91rm92_softc),
322 };
323
324 static devclass_t at91rm92_devclass;
325
326 DRIVER_MODULE(at91rm920, atmelarm, at91rm92_driver, at91rm92_devclass, 0, 0);