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);
Cache object: a1c284a7bb63440cfdef63c797ffa01c
|