at91sam9g20.c revision 238334
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: head/sys/arm/at91/at91sam9g20.c 238334 2012-07-10 04:17:49Z imp $"); 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/at91reg.h> 42#include <arm/at91/at91_aicreg.h> 43#include <arm/at91/at91sam9g20reg.h> 44#include <arm/at91/at91_pmcreg.h> 45#include <arm/at91/at91_pmcvar.h> 46 47struct at91sam9_softc { 48 device_t dev; 49 bus_space_tag_t sc_st; 50 bus_space_handle_t sc_sh; 51 bus_space_handle_t sc_sys_sh; 52 bus_space_handle_t sc_aic_sh; 53 bus_space_handle_t sc_dbg_sh; 54 bus_space_handle_t sc_matrix_sh; 55}; 56 57/* 58 * Standard priority levels for the system. 0 is lowest and 7 is highest. 59 * These values are the ones Atmel uses for its Linux port 60 */ 61static const int at91_irq_prio[32] = 62{ 63 7, /* Advanced Interrupt Controller */ 64 7, /* System Peripherals */ 65 1, /* Parallel IO Controller A */ 66 1, /* Parallel IO Controller B */ 67 1, /* Parallel IO Controller C */ 68 0, /* Analog-to-Digital Converter */ 69 5, /* USART 0 */ 70 5, /* USART 1 */ 71 5, /* USART 2 */ 72 0, /* Multimedia Card Interface */ 73 2, /* USB Device Port */ 74 6, /* Two-Wire Interface */ 75 5, /* Serial Peripheral Interface 0 */ 76 5, /* Serial Peripheral Interface 1 */ 77 5, /* Serial Synchronous Controller */ 78 0, /* (reserved) */ 79 0, /* (reserved) */ 80 0, /* Timer Counter 0 */ 81 0, /* Timer Counter 1 */ 82 0, /* Timer Counter 2 */ 83 2, /* USB Host port */ 84 3, /* Ethernet */ 85 0, /* Image Sensor Interface */ 86 5, /* USART 3 */ 87 5, /* USART 4 */ 88 5, /* USART 5 */ 89 0, /* Timer Counter 3 */ 90 0, /* Timer Counter 4 */ 91 0, /* Timer Counter 5 */ 92 0, /* Advanced Interrupt Controller IRQ0 */ 93 0, /* Advanced Interrupt Controller IRQ1 */ 94 0, /* Advanced Interrupt Controller IRQ2 */ 95}; 96 97#define DEVICE(_name, _id, _unit) \ 98 { \ 99 _name, _unit, \ 100 AT91SAM9G20_ ## _id ##_BASE, \ 101 AT91SAM9G20_ ## _id ## _SIZE, \ 102 AT91SAM9G20_IRQ_ ## _id \ 103 } 104 105static const struct cpu_devs at91_devs[] = 106{ 107 DEVICE("at91_pmc", PMC, 0), 108 DEVICE("at91_wdt", WDT, 0), 109 DEVICE("at91_rst", RSTC, 0), 110 DEVICE("at91_pit", PIT, 0), 111 DEVICE("at91_pio", PIOA, 0), 112 DEVICE("at91_pio", PIOB, 1), 113 DEVICE("at91_pio", PIOC, 2), 114 DEVICE("at91_twi", TWI, 0), 115 DEVICE("at91_mci", MCI, 0), 116 DEVICE("uart", DBGU, 0), 117 DEVICE("uart", USART0, 1), 118 DEVICE("uart", USART1, 2), 119 DEVICE("uart", USART2, 3), 120 DEVICE("uart", USART3, 4), 121 DEVICE("uart", USART4, 5), 122 DEVICE("uart", USART5, 6), 123 DEVICE("spi", SPI0, 0), 124 DEVICE("spi", SPI1, 1), 125 DEVICE("ate", EMAC, 0), 126 DEVICE("macb", EMAC, 0), 127 DEVICE("nand", NAND, 0), 128 DEVICE("ohci", OHCI, 0), 129 { 0, 0, 0, 0, 0 } 130}; 131 132static void 133at91_cpu_add_builtin_children(device_t dev) 134{ 135 int i; 136 const struct cpu_devs *walker; 137 138 for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 139 at91_add_child(dev, i, walker->name, walker->unit, 140 walker->mem_base, walker->mem_len, walker->irq0, 141 walker->irq1, walker->irq2); 142 } 143} 144 145static uint32_t 146at91_pll_outa(int freq) 147{ 148 149 switch (freq / 10000000) { 150 case 747 ... 801: return ((1 << 29) | (0 << 14)); 151 case 697 ... 746: return ((1 << 29) | (1 << 14)); 152 case 647 ... 696: return ((1 << 29) | (2 << 14)); 153 case 597 ... 646: return ((1 << 29) | (3 << 14)); 154 case 547 ... 596: return ((1 << 29) | (1 << 14)); 155 case 497 ... 546: return ((1 << 29) | (2 << 14)); 156 case 447 ... 496: return ((1 << 29) | (3 << 14)); 157 case 397 ... 446: return ((1 << 29) | (4 << 14)); 158 default: return (1 << 29); 159 } 160} 161 162static uint32_t 163at91_pll_outb(int freq) 164{ 165 166 return (0); 167} 168 169static void 170at91_identify(driver_t *drv, device_t parent) 171{ 172 173 if (at91_cpu_is(AT91_T_SAM9G20)) { 174 at91_add_child(parent, 0, "at91sam", 9, 0, 0, -1, 0, 0); 175 at91_cpu_add_builtin_children(parent); 176 } 177} 178 179static int 180at91_probe(device_t dev) 181{ 182 183 device_set_desc(dev, soc_data.name); 184 return (0); 185} 186 187static int 188at91_attach(device_t dev) 189{ 190 struct at91_pmc_clock *clk; 191 struct at91sam9_softc *sc = device_get_softc(dev); 192 int i; 193 194 struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 195 196 sc->sc_st = at91sc->sc_st; 197 sc->sc_sh = at91sc->sc_sh; 198 sc->dev = dev; 199 200 /* 201 * XXX These values work for the RM9200, SAM926[01], and SAM9G20 202 * will have to fix this when we want to support anything else. XXX 203 */ 204 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_SYS_BASE, 205 AT91SAM9G20_SYS_SIZE, &sc->sc_sys_sh) != 0) 206 panic("Enable to map system registers"); 207 208 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_DBGU_BASE, 209 AT91SAM9G20_DBGU_SIZE, &sc->sc_dbg_sh) != 0) 210 panic("Enable to map DBGU registers"); 211 212 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_AIC_BASE, 213 AT91SAM9G20_AIC_SIZE, &sc->sc_aic_sh) != 0) 214 panic("Enable to map system registers"); 215 216 /* XXX Hack to tell atmelarm about the AIC */ 217 at91sc->sc_aic_sh = sc->sc_aic_sh; 218 at91sc->sc_irq_system = AT91_IRQ_SYSTEM; 219 220 for (i = 0; i < 32; i++) { 221 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 222 i * 4, i); 223 /* Priority. */ 224 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 225 at91_irq_prio[i]); 226 if (i < 8) 227 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 228 1); 229 } 230 231 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 232 /* No debug. */ 233 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 234 /* Disable and clear all interrupts. */ 235 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 236 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 237 238 /* Disable all interrupts for DBGU */ 239 bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); 240 241 if (bus_space_subregion(sc->sc_st, sc->sc_sh, 242 AT91SAM9G20_MATRIX_BASE, AT91SAM9G20_MATRIX_SIZE, 243 &sc->sc_matrix_sh) != 0) 244 panic("Enable to map matrix registers"); 245 246 /* activate NAND*/ 247 i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh, 248 AT91SAM9G20_EBICSA); 249 bus_space_write_4(sc->sc_st, sc->sc_matrix_sh, 250 AT91SAM9G20_EBICSA, 251 i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); 252 253 254 /* Update USB device port clock info */ 255 clk = at91_pmc_clock_ref("udpck"); 256 clk->pmc_mask = PMC_SCER_UDP_SAM9; 257 at91_pmc_clock_deref(clk); 258 259 /* Update USB host port clock info */ 260 clk = at91_pmc_clock_ref("uhpck"); 261 clk->pmc_mask = PMC_SCER_UHP_SAM9; 262 at91_pmc_clock_deref(clk); 263 264 /* Each SOC has different PLL contraints */ 265 clk = at91_pmc_clock_ref("plla"); 266 clk->pll_min_in = SAM9G20_PLL_A_MIN_IN_FREQ; /* 2 MHz */ 267 clk->pll_max_in = SAM9G20_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 268 clk->pll_min_out = SAM9G20_PLL_A_MIN_OUT_FREQ; /* 400 MHz */ 269 clk->pll_max_out = SAM9G20_PLL_A_MAX_OUT_FREQ; /* 800 MHz */ 270 clk->pll_mul_shift = SAM9G20_PLL_A_MUL_SHIFT; 271 clk->pll_mul_mask = SAM9G20_PLL_A_MUL_MASK; 272 clk->pll_div_shift = SAM9G20_PLL_A_DIV_SHIFT; 273 clk->pll_div_mask = SAM9G20_PLL_A_DIV_MASK; 274 clk->set_outb = at91_pll_outa; 275 at91_pmc_clock_deref(clk); 276 277 clk = at91_pmc_clock_ref("pllb"); 278 clk->pll_min_in = SAM9G20_PLL_B_MIN_IN_FREQ; /* 2 MHz */ 279 clk->pll_max_in = SAM9G20_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 280 clk->pll_min_out = SAM9G20_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 281 clk->pll_max_out = SAM9G20_PLL_B_MAX_OUT_FREQ; /* 100 MHz */ 282 clk->pll_mul_shift = SAM9G20_PLL_B_MUL_SHIFT; 283 clk->pll_mul_mask = SAM9G20_PLL_B_MUL_MASK; 284 clk->pll_div_shift = SAM9G20_PLL_B_DIV_SHIFT; 285 clk->pll_div_mask = SAM9G20_PLL_B_DIV_MASK; 286 clk->set_outb = at91_pll_outb; 287 at91_pmc_clock_deref(clk); 288 return (0); 289} 290 291static device_method_t at91_methods[] = { 292 DEVMETHOD(device_probe, at91_probe), 293 DEVMETHOD(device_attach, at91_attach), 294 DEVMETHOD(device_identify, at91_identify), 295 {0, 0}, 296}; 297 298static driver_t at91sam9_driver = { 299 "at91sam", 300 at91_methods, 301 sizeof(struct at91sam9_softc), 302}; 303 304static devclass_t at91sam9_devclass; 305 306DRIVER_MODULE(at91sam, atmelarm, at91sam9_driver, at91sam9_devclass, 0, 0); 307