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
46struct 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 */
60static 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
104static 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
131static void
132at91_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
166static void
167at91_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
179static uint32_t
180at91_pll_outa(int freq)
181{
182
183	if (freq > 195000000)
184		return (0x20000000);
185	else
186		return (0x20008000);
187}
188
189static uint32_t
190at91_pll_outb(int freq)
191{
192
193	return (0x4000);
194}
195
196static void
197at91_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
211static int
212at91_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
236static int
237at91_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
344static 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
351static driver_t at91sam9260_driver = {
352	"at91sam9260",
353	at91sam9260_methods,
354	sizeof(struct at91sam9_softc),
355};
356
357static devclass_t at91sam9260_devclass;
358
359DRIVER_MODULE(at91sam9260, atmelarm, at91sam9260_driver, at91sam9260_devclass,
360    NULL, NULL);
361