at91sam9g20.c revision 238354
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 238354 2012-07-10 19:48:42Z 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_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 AT91SAM9G20_ ## _id ##_BASE, \ 100 AT91SAM9G20_ ## _id ## _SIZE, \ 101 AT91SAM9G20_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_cpu_add_builtin_children(device_t dev) 133{ 134 int i; 135 const struct cpu_devs *walker; 136 137 for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 138 at91_add_child(dev, i, walker->name, walker->unit, 139 walker->mem_base, walker->mem_len, walker->irq0, 140 walker->irq1, walker->irq2); 141 } 142} 143 144static uint32_t 145at91_pll_outa(int freq) 146{ 147 148 switch (freq / 10000000) { 149 case 747 ... 801: return ((1 << 29) | (0 << 14)); 150 case 697 ... 746: return ((1 << 29) | (1 << 14)); 151 case 647 ... 696: return ((1 << 29) | (2 << 14)); 152 case 597 ... 646: return ((1 << 29) | (3 << 14)); 153 case 547 ... 596: return ((1 << 29) | (1 << 14)); 154 case 497 ... 546: return ((1 << 29) | (2 << 14)); 155 case 447 ... 496: return ((1 << 29) | (3 << 14)); 156 case 397 ... 446: return ((1 << 29) | (4 << 14)); 157 default: return (1 << 29); 158 } 159} 160 161static uint32_t 162at91_pll_outb(int freq) 163{ 164 165 return (0); 166} 167 168static void 169at91_identify(driver_t *drv, device_t parent) 170{ 171 172 if (at91_cpu_is(AT91_T_SAM9G20)) { 173 at91_add_child(parent, 0, "at91sam", 9, 0, 0, -1, 0, 0); 174 at91_cpu_add_builtin_children(parent); 175 } 176} 177 178static int 179at91_probe(device_t dev) 180{ 181 182 device_set_desc(dev, soc_data.name); 183 return (0); 184} 185 186static int 187at91_attach(device_t dev) 188{ 189 struct at91_pmc_clock *clk; 190 struct at91sam9_softc *sc = device_get_softc(dev); 191 int i; 192 193 struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 194 195 sc->sc_st = at91sc->sc_st; 196 sc->sc_sh = at91sc->sc_sh; 197 sc->dev = dev; 198 199 /* 200 * XXX These values work for the RM9200, SAM926[01], and SAM9G20 201 * will have to fix this when we want to support anything else. XXX 202 */ 203 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_SYS_BASE, 204 AT91SAM9G20_SYS_SIZE, &sc->sc_sys_sh) != 0) 205 panic("Enable to map system registers"); 206 207 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_AIC_BASE, 208 AT91SAM9G20_AIC_SIZE, &sc->sc_aic_sh) != 0) 209 panic("Enable to map system registers"); 210 211 /* XXX Hack to tell atmelarm about the AIC */ 212 at91sc->sc_aic_sh = sc->sc_aic_sh; 213 214 for (i = 0; i < 32; i++) { 215 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 216 i * 4, i); 217 /* Priority. */ 218 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 219 at91_irq_prio[i]); 220 if (i < 8) 221 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 222 1); 223 } 224 225 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 226 /* No debug. */ 227 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 228 /* Disable and clear all interrupts. */ 229 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 230 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 231 232 if (bus_space_subregion(sc->sc_st, sc->sc_sh, 233 AT91SAM9G20_MATRIX_BASE, AT91SAM9G20_MATRIX_SIZE, 234 &sc->sc_matrix_sh) != 0) 235 panic("Enable to map matrix registers"); 236 237 /* activate NAND*/ 238 i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh, 239 AT91SAM9G20_EBICSA); 240 bus_space_write_4(sc->sc_st, sc->sc_matrix_sh, 241 AT91SAM9G20_EBICSA, 242 i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); 243 244 245 /* Update USB device port clock info */ 246 clk = at91_pmc_clock_ref("udpck"); 247 clk->pmc_mask = PMC_SCER_UDP_SAM9; 248 at91_pmc_clock_deref(clk); 249 250 /* Update USB host port clock info */ 251 clk = at91_pmc_clock_ref("uhpck"); 252 clk->pmc_mask = PMC_SCER_UHP_SAM9; 253 at91_pmc_clock_deref(clk); 254 255 /* Each SOC has different PLL contraints */ 256 clk = at91_pmc_clock_ref("plla"); 257 clk->pll_min_in = SAM9G20_PLL_A_MIN_IN_FREQ; /* 2 MHz */ 258 clk->pll_max_in = SAM9G20_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 259 clk->pll_min_out = SAM9G20_PLL_A_MIN_OUT_FREQ; /* 400 MHz */ 260 clk->pll_max_out = SAM9G20_PLL_A_MAX_OUT_FREQ; /* 800 MHz */ 261 clk->pll_mul_shift = SAM9G20_PLL_A_MUL_SHIFT; 262 clk->pll_mul_mask = SAM9G20_PLL_A_MUL_MASK; 263 clk->pll_div_shift = SAM9G20_PLL_A_DIV_SHIFT; 264 clk->pll_div_mask = SAM9G20_PLL_A_DIV_MASK; 265 clk->set_outb = at91_pll_outa; 266 at91_pmc_clock_deref(clk); 267 268 clk = at91_pmc_clock_ref("pllb"); 269 clk->pll_min_in = SAM9G20_PLL_B_MIN_IN_FREQ; /* 2 MHz */ 270 clk->pll_max_in = SAM9G20_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 271 clk->pll_min_out = SAM9G20_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 272 clk->pll_max_out = SAM9G20_PLL_B_MAX_OUT_FREQ; /* 100 MHz */ 273 clk->pll_mul_shift = SAM9G20_PLL_B_MUL_SHIFT; 274 clk->pll_mul_mask = SAM9G20_PLL_B_MUL_MASK; 275 clk->pll_div_shift = SAM9G20_PLL_B_DIV_SHIFT; 276 clk->pll_div_mask = SAM9G20_PLL_B_DIV_MASK; 277 clk->set_outb = at91_pll_outb; 278 at91_pmc_clock_deref(clk); 279 return (0); 280} 281 282static device_method_t at91_methods[] = { 283 DEVMETHOD(device_probe, at91_probe), 284 DEVMETHOD(device_attach, at91_attach), 285 DEVMETHOD(device_identify, at91_identify), 286 {0, 0}, 287}; 288 289static driver_t at91sam9_driver = { 290 "at91sam", 291 at91_methods, 292 sizeof(struct at91sam9_softc), 293}; 294 295static devclass_t at91sam9_devclass; 296 297DRIVER_MODULE(at91sam, atmelarm, at91sam9_driver, at91sam9_devclass, 0, 0); 298