at91sam9x5.c revision 238389
1237742Simp/*-
2237742Simp * Copyright (c) 2005 Olivier Houchard.  All rights reserved.
3237742Simp * Copyright (c) 2010 Greg Ansley.  All rights reserved.
4237742Simp * Copyright (c) 2012 M. Warner Losh..  All rights reserved.
5237742Simp *
6237742Simp * Redistribution and use in source and binary forms, with or without
7237742Simp * modification, are permitted provided that the following conditions
8237742Simp * are met:
9237742Simp * 1. Redistributions of source code must retain the above copyright
10237742Simp *    notice, this list of conditions and the following disclaimer.
11237742Simp * 2. Redistributions in binary form must reproduce the above copyright
12237742Simp *    notice, this list of conditions and the following disclaimer in the
13237742Simp *    documentation and/or other materials provided with the distribution.
14237742Simp *
15237742Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16237742Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17237742Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18237742Simp * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
19237742Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20237742Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21237742Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22237742Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23237742Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24237742Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25237742Simp * SUCH DAMAGE.
26237742Simp */
27237742Simp
28237742Simp#include <sys/cdefs.h>
29237742Simp__FBSDID("$FreeBSD: head/sys/arm/at91/at91sam9x25.c 238389 2012-07-12 02:58:45Z imp $");
30237742Simp
31237742Simp#include <sys/param.h>
32237742Simp#include <sys/systm.h>
33237742Simp#include <sys/bus.h>
34237742Simp#include <sys/kernel.h>
35237742Simp#include <sys/malloc.h>
36237742Simp#include <sys/module.h>
37237742Simp
38237742Simp#include <machine/bus.h>
39237742Simp
40237742Simp#include <arm/at91/at91var.h>
41238331Simp#include <arm/at91/at91reg.h>
42238376Simp#include <arm/at91/at91soc.h>
43237742Simp#include <arm/at91/at91_aicreg.h>
44237742Simp#include <arm/at91/at91sam9x25reg.h>
45238376Simp#include <arm/at91/at91_pitreg.h>
46237742Simp#include <arm/at91/at91_pmcreg.h>
47237742Simp#include <arm/at91/at91_pmcvar.h>
48238376Simp#include <arm/at91/at91_rstreg.h>
49237742Simp
50237742Simpstruct at91sam9x25_softc {
51237742Simp	device_t dev;
52237742Simp	bus_space_tag_t sc_st;
53237742Simp	bus_space_handle_t sc_sh;
54237742Simp};
55237742Simp
56237742Simp/*
57237742Simp * Standard priority levels for the system.  0 is lowest and 7 is highest.
58237742Simp * These values are the ones Atmel uses for its Linux port
59237742Simp */
60237742Simpstatic const int at91_irq_prio[32] =
61237742Simp{
62237743Simp	7,	/* Advanced Interrupt Controller (FIQ) */
63237742Simp	7,	/* System Peripherals */
64237743Simp	1,	/* Parallel IO Controller A and B */
65237743Simp	1,	/* Parallel IO Controller C and D */
66237743Simp	4,	/* Soft Modem */
67237742Simp	5,	/* USART 0 */
68237742Simp	5,	/* USART 1 */
69237742Simp	5,	/* USART 2 */
70237743Simp	5,	/* USART 3 */
71237743Simp	6,	/* Two-Wire Interface 0 */
72237743Simp	6,	/* Two-Wire Interface 1 */
73237743Simp	6,	/* Two-Wire Interface 2 */
74237743Simp	0,	/* Multimedia Card Interface 0 */
75237742Simp	5,	/* Serial Peripheral Interface 0 */
76237742Simp	5,	/* Serial Peripheral Interface 1 */
77237743Simp	5,	/* UART 0 */
78237743Simp	5,	/* UART 1 */
79237743Simp	0,	/* Timer Counter 0, 1, 2, 3, 4 and 5 */
80237743Simp	0,	/* Pulse Width Modulation Controller */
81237743Simp	0,	/* ADC Controller */
82237743Simp	0,	/* DMA Controller 0 */
83237743Simp	0,	/* DMA Controller 1 */
84237743Simp	2,	/* USB Host High Speed port */
85237743Simp	2,	/* USB Device High speed port */
86237743Simp	3,	/* Ethernet MAC 0 */
87237743Simp	3,	/* LDC Controller or Image Sensor Interface */
88237743Simp	0,	/* Multimedia Card Interface 1 */
89237743Simp	3,	/* Ethernet MAC 1 */
90237743Simp	4,	/* Synchronous Serial Interface */
91237743Simp	4,	/* CAN Controller 0 */
92237743Simp	4,	/* CAN Controller 1 */
93237743Simp	0,	/* Advanced Interrupt Controller (IRQ0) */
94237742Simp};
95237742Simp
96237742Simp#define DEVICE(_name, _id, _unit)		\
97237742Simp	{					\
98237742Simp		_name, _unit,			\
99237742Simp		AT91SAM9X25_ ## _id ##_BASE,	\
100237742Simp		AT91SAM9X25_ ## _id ## _SIZE,	\
101237742Simp		AT91SAM9X25_IRQ_ ## _id		\
102237742Simp	}
103237742Simp
104237742Simpstatic const struct cpu_devs at91_devs[] =
105237742Simp{
106237742Simp	DEVICE("at91_pmc", PMC,  0),
107237742Simp	DEVICE("at91_wdt", WDT,  0),
108237742Simp	DEVICE("at91_rst", RSTC, 0),
109237742Simp	DEVICE("at91_pit", PIT,  0),
110237742Simp	DEVICE("at91_pio", PIOA, 0),
111237742Simp	DEVICE("at91_pio", PIOB, 1),
112237742Simp	DEVICE("at91_pio", PIOC, 2),
113237744Simp	DEVICE("at91_pio", PIOD, 3),
114237742Simp	DEVICE("at91_twi", TWI0, 0),
115237742Simp	DEVICE("at91_twi", TWI1, 1),
116237742Simp	DEVICE("at91_twi", TWI2, 2),
117237742Simp	DEVICE("at91_mci", HSMCI0, 0),
118237742Simp	DEVICE("at91_mci", HSMCI1, 1),
119237742Simp	DEVICE("uart", DBGU,   0),
120237742Simp	DEVICE("uart", USART0, 1),
121237742Simp	DEVICE("uart", USART1, 2),
122237742Simp	DEVICE("uart", USART2, 3),
123237742Simp	DEVICE("uart", USART3, 4),
124237742Simp	DEVICE("spi",  SPI0,   0),
125237742Simp	DEVICE("spi",  SPI1,   1),
126237742Simp	DEVICE("macb", EMAC0,  0),
127237742Simp	DEVICE("macb", EMAC1,  0),
128237742Simp	DEVICE("nand", NAND,   0),
129237742Simp	DEVICE("ohci", OHCI,   0),
130237742Simp	DEVICE("ehci", EHCI,   0),
131237742Simp	{ 0, 0, 0, 0, 0 }
132237742Simp};
133237742Simp
134237742Simpstatic void
135237742Simpat91_cpu_add_builtin_children(device_t dev)
136237742Simp{
137237742Simp	int i;
138237742Simp	const struct cpu_devs *walker;
139237742Simp
140237742Simp	for (i = 1, walker = at91_devs; walker->name; i++, walker++) {
141237742Simp		at91_add_child(dev, i, walker->name, walker->unit,
142237742Simp		    walker->mem_base, walker->mem_len, walker->irq0,
143237742Simp		    walker->irq1, walker->irq2);
144237742Simp	}
145237742Simp}
146237742Simp
147237742Simpstatic uint32_t
148237742Simpat91_pll_outa(int freq)
149237742Simp{
150237742Simp
151237742Simp	switch (freq / 10000000) {
152237742Simp		case 747 ... 801: return ((1 << 29) | (0 << 14));
153237742Simp		case 697 ... 746: return ((1 << 29) | (1 << 14));
154237742Simp		case 647 ... 696: return ((1 << 29) | (2 << 14));
155237742Simp		case 597 ... 646: return ((1 << 29) | (3 << 14));
156237742Simp		case 547 ... 596: return ((1 << 29) | (1 << 14));
157237742Simp		case 497 ... 546: return ((1 << 29) | (2 << 14));
158237742Simp		case 447 ... 496: return ((1 << 29) | (3 << 14));
159237742Simp		case 397 ... 446: return ((1 << 29) | (4 << 14));
160237742Simp		default: return (1 << 29);
161237742Simp	}
162237742Simp}
163237742Simp
164237742Simpstatic uint32_t
165237742Simpat91_pll_outb(int freq)
166237742Simp{
167237742Simp
168237742Simp	return (0);
169237742Simp}
170237742Simp
171237742Simpstatic void
172237742Simpat91_identify(driver_t *drv, device_t parent)
173237742Simp{
174237742Simp
175238376Simp	if (soc_info.type == AT91_T_SAM9X5 && soc_info.subtype == AT91_ST_SAM9X25) {
176237742Simp		at91_add_child(parent, 0, "at91sam9x25", 0, 0, 0, -1, 0, 0);
177237742Simp		at91_cpu_add_builtin_children(parent);
178237742Simp	}
179237742Simp}
180237742Simp
181237742Simpstatic int
182237742Simpat91_probe(device_t dev)
183237742Simp{
184237742Simp
185237742Simp	device_set_desc(dev, "AT91SAM9X25");
186237742Simp	return (0);
187237742Simp}
188237742Simp
189237742Simpstatic int
190237742Simpat91_attach(device_t dev)
191237742Simp{
192237742Simp	struct at91_pmc_clock *clk;
193237742Simp	struct at91sam9x25_softc *sc = device_get_softc(dev);
194237742Simp	struct at91_softc *at91sc = device_get_softc(device_get_parent(dev));
195237742Simp
196237742Simp	sc->sc_st = at91sc->sc_st;
197237742Simp	sc->sc_sh = at91sc->sc_sh;
198237742Simp	sc->dev = dev;
199237742Simp
200237742Simp	/* Update USB device port clock info */
201237742Simp	clk = at91_pmc_clock_ref("udpck");
202237742Simp	clk->pmc_mask  = PMC_SCER_UDP_SAM9;
203237742Simp	at91_pmc_clock_deref(clk);
204237742Simp
205237742Simp	/* Update USB host port clock info */
206237742Simp	clk = at91_pmc_clock_ref("uhpck");
207237742Simp	clk->pmc_mask  = PMC_SCER_UHP_SAM9;
208237742Simp	at91_pmc_clock_deref(clk);
209237742Simp
210237742Simp	/* Each SOC has different PLL contraints */
211237742Simp	clk = at91_pmc_clock_ref("plla");
212237742Simp	clk->pll_min_in    = SAM9X25_PLL_A_MIN_IN_FREQ;		/*   2 MHz */
213237742Simp	clk->pll_max_in    = SAM9X25_PLL_A_MAX_IN_FREQ;		/*  32 MHz */
214237742Simp	clk->pll_min_out   = SAM9X25_PLL_A_MIN_OUT_FREQ;	/* 400 MHz */
215237742Simp	clk->pll_max_out   = SAM9X25_PLL_A_MAX_OUT_FREQ;	/* 800 MHz */
216237742Simp	clk->pll_mul_shift = SAM9X25_PLL_A_MUL_SHIFT;
217237742Simp	clk->pll_mul_mask  = SAM9X25_PLL_A_MUL_MASK;
218237742Simp	clk->pll_div_shift = SAM9X25_PLL_A_DIV_SHIFT;
219237742Simp	clk->pll_div_mask  = SAM9X25_PLL_A_DIV_MASK;
220237742Simp	clk->set_outb      = at91_pll_outa;
221237742Simp	at91_pmc_clock_deref(clk);
222237742Simp
223237742Simp	clk = at91_pmc_clock_ref("pllb");
224237742Simp	clk->pll_min_in    = SAM9X25_PLL_B_MIN_IN_FREQ;		/*   2 MHz */
225237742Simp	clk->pll_max_in    = SAM9X25_PLL_B_MAX_IN_FREQ;		/*  32 MHz */
226237742Simp	clk->pll_min_out   = SAM9X25_PLL_B_MIN_OUT_FREQ;	/*  30 MHz */
227237742Simp	clk->pll_max_out   = SAM9X25_PLL_B_MAX_OUT_FREQ;	/* 100 MHz */
228237742Simp	clk->pll_mul_shift = SAM9X25_PLL_B_MUL_SHIFT;
229237742Simp	clk->pll_mul_mask  = SAM9X25_PLL_B_MUL_MASK;
230237742Simp	clk->pll_div_shift = SAM9X25_PLL_B_DIV_SHIFT;
231237742Simp	clk->pll_div_mask  = SAM9X25_PLL_B_DIV_MASK;
232237742Simp	clk->set_outb      = at91_pll_outb;
233237742Simp	at91_pmc_clock_deref(clk);
234237742Simp	return (0);
235237742Simp}
236237742Simp
237237742Simpstatic device_method_t at91sam9x25_methods[] = {
238237742Simp	DEVMETHOD(device_probe, at91_probe),
239237742Simp	DEVMETHOD(device_attach, at91_attach),
240237742Simp	DEVMETHOD(device_identify, at91_identify),
241237742Simp	{0, 0},
242237742Simp};
243237742Simp
244237742Simpstatic driver_t at91sam9x25_driver = {
245237742Simp	"at91sam9x25",
246237742Simp	at91sam9x25_methods,
247237742Simp	sizeof(struct at91sam9x25_softc),
248237742Simp};
249237742Simp
250237742Simpstatic devclass_t at91sam9x25_devclass;
251237742Simp
252237742SimpDRIVER_MODULE(at91sam9x25, atmelarm, at91sam9x25_driver, at91sam9x25_devclass, 0, 0);
253238376Simp
254238376Simpstatic struct at91_soc_data soc_data = {
255238376Simp	.soc_delay = at91_pit_delay,
256238389Simp	.soc_reset = at91_rst_cpu_reset,
257238389Simp	.soc_irq_prio = at91_irq_prio,
258238376Simp};
259238376Simp
260238376SimpAT91_SOC_SUB(AT91_T_SAM9X5, AT91_ST_SAM9X25, &soc_data);
261