]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/arm/at91/at91sam9260.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / arm / at91 / at91sam9260.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/at91_aicreg.h>
42 #include <arm/at91/at91sam9260reg.h>
43 #include <arm/at91/at91_pmcreg.h>
44 #include <arm/at91/at91_pmcvar.h>
45
46 struct at91sam9_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 /*
57  * Standard priority levels for the system.  0 is lowest and 7 is highest.
58  * These values are the ones Atmel uses for its Linux port
59  */
60 static const int at91_irq_prio[32] =
61 {
62         7,      /* Advanced Interrupt Controller */
63         7,      /* System Peripherals */
64         1,      /* Parallel IO Controller A */
65         1,      /* Parallel IO Controller B */
66         1,      /* Parallel IO Controller C */
67         0,      /* Analog-to-Digital Converter */
68         5,      /* USART 0 */
69         5,      /* USART 1 */
70         5,      /* USART 2 */
71         0,      /* Multimedia Card Interface */
72         2,      /* USB Device Port */
73         6,      /* Two-Wire Interface */
74         5,      /* Serial Peripheral Interface 0 */
75         5,      /* Serial Peripheral Interface 1 */
76         5,      /* Serial Synchronous Controller */
77         0,      /* (reserved) */
78         0,      /* (reserved) */
79         0,      /* Timer Counter 0 */
80         0,      /* Timer Counter 1 */
81         0,      /* Timer Counter 2 */
82         2,      /* USB Host port */
83         3,      /* Ethernet */
84         0,      /* Image Sensor Interface */
85         5,      /* USART 3 */
86         5,      /* USART 4 */
87         5,      /* USART 5 */
88         0,      /* Timer Counter 3 */
89         0,      /* Timer Counter 4 */
90         0,      /* Timer Counter 5 */
91         0,      /* Advanced Interrupt Controller IRQ0 */
92         0,      /* Advanced Interrupt Controller IRQ1 */
93         0,      /* Advanced Interrupt Controller IRQ2 */
94 };
95
96 #define DEVICE(_name, _id, _unit)               \
97         {                                       \
98                 _name, _unit,                   \
99                 AT91SAM9260_ ## _id ##_BASE,    \
100                 AT91SAM9260_ ## _id ## _SIZE,   \
101                 AT91SAM9260_IRQ_ ## _id         \
102         }
103
104 static const struct cpu_devs at91_devs[] =
105 {
106         DEVICE("at91_pmc", PMC,  0),
107         DEVICE("at91_wdt", WDT,  0),
108         DEVICE("at91_rst", RSTC, 0),
109         DEVICE("at91_pit", PIT,  0),
110         DEVICE("at91_pio", PIOA, 0),
111         DEVICE("at91_pio", PIOB, 1),
112         DEVICE("at91_pio", PIOC, 2),
113         DEVICE("at91_twi", TWI, 0),
114         DEVICE("at91_mci", MCI, 0),
115         DEVICE("uart", DBGU,   0),
116         DEVICE("uart", USART0, 1),
117         DEVICE("uart", USART1, 2),
118         DEVICE("uart", USART2, 3),
119         DEVICE("uart", USART3, 4),
120         DEVICE("uart", USART4, 5),
121         DEVICE("uart", USART5, 6),
122         DEVICE("spi",  SPI0,   0),
123         DEVICE("spi",  SPI1,   1),
124         DEVICE("ate",  EMAC,   0),
125         DEVICE("macb", EMAC,   0),
126         DEVICE("nand", NAND,   0),
127         DEVICE("ohci", OHCI,   0),
128         { 0, 0, 0, 0, 0 }
129 };
130
131 static void
132 at91_add_child(device_t dev, int prio, const char *name, int unit,
133     bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2)
134 {
135         device_t kid;
136         struct at91_ivar *ivar;
137
138         kid = device_add_child_ordered(dev, prio, name, unit);
139         if (kid == NULL) {
140             printf("Can't add child %s%d ordered\n", name, unit);
141             return;
142         }
143         ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
144         if (ivar == NULL) {
145                 device_delete_child(dev, kid);
146                 printf("Can't add alloc ivar\n");
147                 return;
148         }
149         device_set_ivars(kid, ivar);
150         resource_list_init(&ivar->resources);
151         if (irq0 != -1) {
152                 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1);
153                 if (irq0 != AT91SAM9260_IRQ_SYSTEM)
154                         at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0);
155         }
156         if (irq1 != 0)
157                 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1);
158         if (irq2 != 0)
159                 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1);
160         if (addr != 0 && addr < AT91SAM9260_BASE)
161                 addr += AT91SAM9260_BASE;
162         if (addr != 0)
163                 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size);
164 }
165
166 static void
167 at91_cpu_add_builtin_children(device_t dev)
168 {
169         int i;
170         const struct cpu_devs *walker;
171
172         for (i = 1, walker = at91_devs; walker->name; i++, walker++) {
173                 at91_add_child(dev, i, walker->name, walker->unit,
174                     walker->mem_base, walker->mem_len, walker->irq0,
175                     walker->irq1, walker->irq2);
176         }
177 }
178
179 static uint32_t
180 at91_pll_outa(int freq)
181 {
182
183         if (freq > 195000000)
184                 return (0x20000000);
185         else
186                 return (0x20008000);
187 }
188
189 static uint32_t
190 at91_pll_outb(int freq)
191 {
192
193         return (0x4000);
194 }
195
196 static void
197 at91_identify(driver_t *drv, device_t parent)
198 {
199
200         switch (AT91_CPU(at91_chip_id)) {
201         case AT91_CPU_SAM9260:
202         case AT91_CPU_SAM9XE128:
203         case AT91_CPU_SAM9XE256:
204         case AT91_CPU_SAM9XE512:
205                 at91_add_child(parent, 0, "at91sam9260", 0, 0, 0, -1, 0, 0);
206                 at91_cpu_add_builtin_children(parent);
207                 break;
208         }
209 }
210
211 static int
212 at91_probe(device_t dev)
213 {
214         const char *desc;
215
216         switch (AT91_CPU(at91_chip_id)) {
217         case AT91_CPU_SAM9260:
218                 desc = "AT91SAM9260";
219                 break;
220         case AT91_CPU_SAM9XE128:
221                 desc = "AT91SAM9XE128";
222                 break;
223         case AT91_CPU_SAM9XE256:
224                 desc = "AT91SAM9XE256";
225                 break;
226         case AT91_CPU_SAM9XE512:
227                 desc = "AT91SAM9XE512";
228                 break;
229         default:
230                 return (ENXIO);
231         }
232         device_set_desc(dev, desc);
233         return (0);
234 }
235
236 static int
237 at91_attach(device_t dev)
238 {
239         struct at91_pmc_clock *clk;
240         struct at91sam9_softc *sc = device_get_softc(dev);
241         int i;
242
243         struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));
244
245         sc->sc_st = at91sc->sc_st;
246         sc->sc_sh = at91sc->sc_sh;
247         sc->dev = dev;
248
249         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_SYS_BASE,
250             AT91SAM9260_SYS_SIZE, &sc->sc_sys_sh) != 0)
251                 panic("Enable to map system registers");
252
253         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_DBGU_BASE,
254             AT91SAM9260_DBGU_SIZE, &sc->sc_dbg_sh) != 0)
255                 panic("Enable to map DBGU registers");
256
257         if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_AIC_BASE,
258             AT91SAM9260_AIC_SIZE, &sc->sc_aic_sh) != 0)
259                 panic("Enable to map system registers");
260
261         /* XXX Hack to tell atmelarm about the AIC */
262         at91sc->sc_aic_sh = sc->sc_aic_sh;
263         at91sc->sc_irq_system = AT91SAM9260_IRQ_SYSTEM;
264
265         for (i = 0; i < 32; i++) {
266                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR +
267                     i * 4, i);
268                 /* Priority. */
269                 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
270                     at91_irq_prio[i]);
271                 if (i < 8)
272                         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
273                             1);
274         }
275
276         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
277         /* No debug. */
278         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
279         /* Disable and clear all interrupts. */
280         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
281         bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);
282
283         /* Disable all interrupts for DBGU */
284         bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff);
285
286         if (bus_space_subregion(sc->sc_st, sc->sc_sh,
287             AT91SAM9260_MATRIX_BASE, AT91SAM9260_MATRIX_SIZE,
288             &sc->sc_matrix_sh) != 0)
289                 panic("Enable to map matrix registers");
290
291         /* activate NAND*/
292         i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh,
293             AT91SAM9260_EBICSA);
294         bus_space_write_4(sc->sc_st, sc->sc_matrix_sh,
295             AT91SAM9260_EBICSA,
296             i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
297
298         /* Update USB device port clock info */
299         clk = at91_pmc_clock_ref("udpck");
300         clk->pmc_mask  = PMC_SCER_UDP_SAM9;
301         at91_pmc_clock_deref(clk);
302
303         /* Update USB host port clock info */
304         clk = at91_pmc_clock_ref("uhpck");
305         clk->pmc_mask  = PMC_SCER_UHP_SAM9;
306         at91_pmc_clock_deref(clk);
307
308         /* Each SOC has different PLL contraints */
309         clk = at91_pmc_clock_ref("plla");
310         clk->pll_min_in    = SAM9260_PLL_A_MIN_IN_FREQ;         /*   1 MHz */
311         clk->pll_max_in    = SAM9260_PLL_A_MAX_IN_FREQ;         /*  32 MHz */
312         clk->pll_min_out   = SAM9260_PLL_A_MIN_OUT_FREQ;        /*  80 MHz */
313         clk->pll_max_out   = SAM9260_PLL_A_MAX_OUT_FREQ;        /* 240 MHz */
314         clk->pll_mul_shift = SAM9260_PLL_A_MUL_SHIFT;
315         clk->pll_mul_mask  = SAM9260_PLL_A_MUL_MASK;
316         clk->pll_div_shift = SAM9260_PLL_A_DIV_SHIFT;
317         clk->pll_div_mask  = SAM9260_PLL_A_DIV_MASK;
318         clk->set_outb      = at91_pll_outa;
319         at91_pmc_clock_deref(clk);
320
321         /*
322          * Fudge MAX pll in frequence down below 3.0 MHz to ensure
323          * PMC alogrithm choose the divisor that causes the input clock
324          * to be near the optimal 2 MHz per datasheet.  We know
325          * we are going to be using this for the USB clock at 96 MHz.
326          * Causes no extra frequency deviation for all recomended crystal
327          * values.
328          */
329         clk = at91_pmc_clock_ref("pllb");
330         clk->pll_min_in    = SAM9260_PLL_B_MIN_IN_FREQ;         /*   1 MHz */
331         clk->pll_max_in    = SAM9260_PLL_B_MAX_IN_FREQ;         /*   5 MHz */
332         clk->pll_max_in    = 2999999;                           /*  ~3 MHz */
333         clk->pll_min_out   = SAM9260_PLL_B_MIN_OUT_FREQ;        /*  70 MHz */
334         clk->pll_max_out   = SAM9260_PLL_B_MAX_OUT_FREQ;        /* 130 MHz */
335         clk->pll_mul_shift = SAM9260_PLL_B_MUL_SHIFT;
336         clk->pll_mul_mask  = SAM9260_PLL_B_MUL_MASK;
337         clk->pll_div_shift = SAM9260_PLL_B_DIV_SHIFT;
338         clk->pll_div_mask  = SAM9260_PLL_B_DIV_MASK;
339         clk->set_outb      = at91_pll_outb;
340         at91_pmc_clock_deref(clk);
341         return (0);
342 }
343
344 static device_method_t at91sam9260_methods[] = {
345         DEVMETHOD(device_probe, at91_probe),
346         DEVMETHOD(device_attach, at91_attach),
347         DEVMETHOD(device_identify, at91_identify),
348         DEVMETHOD_END
349 };
350
351 static driver_t at91sam9260_driver = {
352         "at91sam9260",
353         at91sam9260_methods,
354         sizeof(struct at91sam9_softc),
355 };
356
357 static devclass_t at91sam9260_devclass;
358
359 DRIVER_MODULE(at91sam9260, atmelarm, at91sam9260_driver, at91sam9260_devclass,
360     NULL, NULL);