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