at91sam9x5.c revision 238376
1/*- 2 * Copyright (c) 2005 Olivier Houchard. All rights reserved. 3 * Copyright (c) 2010 Greg Ansley. All rights reserved. 4 * Copyright (c) 2012 M. Warner Losh.. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/sys/arm/at91/at91sam9x25.c 238376 2012-07-11 20:17:14Z imp $"); 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/kernel.h> 35#include <sys/malloc.h> 36#include <sys/module.h> 37 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/at91sam9x25reg.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 at91sam9x25_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}; 57 58/* 59 * Standard priority levels for the system. 0 is lowest and 7 is highest. 60 * These values are the ones Atmel uses for its Linux port 61 */ 62static const int at91_irq_prio[32] = 63{ 64 7, /* Advanced Interrupt Controller (FIQ) */ 65 7, /* System Peripherals */ 66 1, /* Parallel IO Controller A and B */ 67 1, /* Parallel IO Controller C and D */ 68 4, /* Soft Modem */ 69 5, /* USART 0 */ 70 5, /* USART 1 */ 71 5, /* USART 2 */ 72 5, /* USART 3 */ 73 6, /* Two-Wire Interface 0 */ 74 6, /* Two-Wire Interface 1 */ 75 6, /* Two-Wire Interface 2 */ 76 0, /* Multimedia Card Interface 0 */ 77 5, /* Serial Peripheral Interface 0 */ 78 5, /* Serial Peripheral Interface 1 */ 79 5, /* UART 0 */ 80 5, /* UART 1 */ 81 0, /* Timer Counter 0, 1, 2, 3, 4 and 5 */ 82 0, /* Pulse Width Modulation Controller */ 83 0, /* ADC Controller */ 84 0, /* DMA Controller 0 */ 85 0, /* DMA Controller 1 */ 86 2, /* USB Host High Speed port */ 87 2, /* USB Device High speed port */ 88 3, /* Ethernet MAC 0 */ 89 3, /* LDC Controller or Image Sensor Interface */ 90 0, /* Multimedia Card Interface 1 */ 91 3, /* Ethernet MAC 1 */ 92 4, /* Synchronous Serial Interface */ 93 4, /* CAN Controller 0 */ 94 4, /* CAN Controller 1 */ 95 0, /* Advanced Interrupt Controller (IRQ0) */ 96}; 97 98#define DEVICE(_name, _id, _unit) \ 99 { \ 100 _name, _unit, \ 101 AT91SAM9X25_ ## _id ##_BASE, \ 102 AT91SAM9X25_ ## _id ## _SIZE, \ 103 AT91SAM9X25_IRQ_ ## _id \ 104 } 105 106static const struct cpu_devs at91_devs[] = 107{ 108 DEVICE("at91_pmc", PMC, 0), 109 DEVICE("at91_wdt", WDT, 0), 110 DEVICE("at91_rst", RSTC, 0), 111 DEVICE("at91_pit", PIT, 0), 112 DEVICE("at91_pio", PIOA, 0), 113 DEVICE("at91_pio", PIOB, 1), 114 DEVICE("at91_pio", PIOC, 2), 115 DEVICE("at91_pio", PIOD, 3), 116 DEVICE("at91_twi", TWI0, 0), 117 DEVICE("at91_twi", TWI1, 1), 118 DEVICE("at91_twi", TWI2, 2), 119 DEVICE("at91_mci", HSMCI0, 0), 120 DEVICE("at91_mci", HSMCI1, 1), 121 DEVICE("uart", DBGU, 0), 122 DEVICE("uart", USART0, 1), 123 DEVICE("uart", USART1, 2), 124 DEVICE("uart", USART2, 3), 125 DEVICE("uart", USART3, 4), 126 DEVICE("spi", SPI0, 0), 127 DEVICE("spi", SPI1, 1), 128 DEVICE("macb", EMAC0, 0), 129 DEVICE("macb", EMAC1, 0), 130 DEVICE("nand", NAND, 0), 131 DEVICE("ohci", OHCI, 0), 132 DEVICE("ehci", EHCI, 0), 133 { 0, 0, 0, 0, 0 } 134}; 135 136static void 137at91_cpu_add_builtin_children(device_t dev) 138{ 139 int i; 140 const struct cpu_devs *walker; 141 142 for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 143 at91_add_child(dev, i, walker->name, walker->unit, 144 walker->mem_base, walker->mem_len, walker->irq0, 145 walker->irq1, walker->irq2); 146 } 147} 148 149static uint32_t 150at91_pll_outa(int freq) 151{ 152 153 switch (freq / 10000000) { 154 case 747 ... 801: return ((1 << 29) | (0 << 14)); 155 case 697 ... 746: return ((1 << 29) | (1 << 14)); 156 case 647 ... 696: return ((1 << 29) | (2 << 14)); 157 case 597 ... 646: return ((1 << 29) | (3 << 14)); 158 case 547 ... 596: return ((1 << 29) | (1 << 14)); 159 case 497 ... 546: return ((1 << 29) | (2 << 14)); 160 case 447 ... 496: return ((1 << 29) | (3 << 14)); 161 case 397 ... 446: return ((1 << 29) | (4 << 14)); 162 default: return (1 << 29); 163 } 164} 165 166static uint32_t 167at91_pll_outb(int freq) 168{ 169 170 return (0); 171} 172 173static void 174at91_identify(driver_t *drv, device_t parent) 175{ 176 177 if (soc_info.type == AT91_T_SAM9X5 && soc_info.subtype == AT91_ST_SAM9X25) { 178 at91_add_child(parent, 0, "at91sam9x25", 0, 0, 0, -1, 0, 0); 179 at91_cpu_add_builtin_children(parent); 180 } 181} 182 183static int 184at91_probe(device_t dev) 185{ 186 187 device_set_desc(dev, "AT91SAM9X25"); 188 return (0); 189} 190 191static int 192at91_attach(device_t dev) 193{ 194 struct at91_pmc_clock *clk; 195 struct at91sam9x25_softc *sc = device_get_softc(dev); 196 int i; 197 198 struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 199 200 sc->sc_st = at91sc->sc_st; 201 sc->sc_sh = at91sc->sc_sh; 202 sc->dev = dev; 203 204 /* 205 * XXX These values work for the RM9200, SAM926[01], and SAM9X25 206 * will have to fix this when we want to support anything else. XXX 207 */ 208 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9X25_SYS_BASE, 209 AT91SAM9X25_SYS_SIZE, &sc->sc_sys_sh) != 0) 210 panic("Enable to map system registers"); 211 212 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9X25_AIC_BASE, 213 AT91SAM9X25_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 219 for (i = 0; i < 32; i++) { 220 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 221 i * 4, i); 222 /* Priority. */ 223 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 224 at91_irq_prio[i]); 225 if (i < 8) 226 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 227 1); 228 } 229 230 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 231 /* No debug. */ 232 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 233 /* Disable and clear all interrupts. */ 234 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 235 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 236 237 /* Update USB device port clock info */ 238 clk = at91_pmc_clock_ref("udpck"); 239 clk->pmc_mask = PMC_SCER_UDP_SAM9; 240 at91_pmc_clock_deref(clk); 241 242 /* Update USB host port clock info */ 243 clk = at91_pmc_clock_ref("uhpck"); 244 clk->pmc_mask = PMC_SCER_UHP_SAM9; 245 at91_pmc_clock_deref(clk); 246 247 /* Each SOC has different PLL contraints */ 248 clk = at91_pmc_clock_ref("plla"); 249 clk->pll_min_in = SAM9X25_PLL_A_MIN_IN_FREQ; /* 2 MHz */ 250 clk->pll_max_in = SAM9X25_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 251 clk->pll_min_out = SAM9X25_PLL_A_MIN_OUT_FREQ; /* 400 MHz */ 252 clk->pll_max_out = SAM9X25_PLL_A_MAX_OUT_FREQ; /* 800 MHz */ 253 clk->pll_mul_shift = SAM9X25_PLL_A_MUL_SHIFT; 254 clk->pll_mul_mask = SAM9X25_PLL_A_MUL_MASK; 255 clk->pll_div_shift = SAM9X25_PLL_A_DIV_SHIFT; 256 clk->pll_div_mask = SAM9X25_PLL_A_DIV_MASK; 257 clk->set_outb = at91_pll_outa; 258 at91_pmc_clock_deref(clk); 259 260 clk = at91_pmc_clock_ref("pllb"); 261 clk->pll_min_in = SAM9X25_PLL_B_MIN_IN_FREQ; /* 2 MHz */ 262 clk->pll_max_in = SAM9X25_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 263 clk->pll_min_out = SAM9X25_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 264 clk->pll_max_out = SAM9X25_PLL_B_MAX_OUT_FREQ; /* 100 MHz */ 265 clk->pll_mul_shift = SAM9X25_PLL_B_MUL_SHIFT; 266 clk->pll_mul_mask = SAM9X25_PLL_B_MUL_MASK; 267 clk->pll_div_shift = SAM9X25_PLL_B_DIV_SHIFT; 268 clk->pll_div_mask = SAM9X25_PLL_B_DIV_MASK; 269 clk->set_outb = at91_pll_outb; 270 at91_pmc_clock_deref(clk); 271 return (0); 272} 273 274static device_method_t at91sam9x25_methods[] = { 275 DEVMETHOD(device_probe, at91_probe), 276 DEVMETHOD(device_attach, at91_attach), 277 DEVMETHOD(device_identify, at91_identify), 278 {0, 0}, 279}; 280 281static driver_t at91sam9x25_driver = { 282 "at91sam9x25", 283 at91sam9x25_methods, 284 sizeof(struct at91sam9x25_softc), 285}; 286 287static devclass_t at91sam9x25_devclass; 288 289DRIVER_MODULE(at91sam9x25, atmelarm, at91sam9x25_driver, at91sam9x25_devclass, 0, 0); 290 291static struct at91_soc_data soc_data = { 292 .soc_delay = at91_pit_delay, 293 .soc_reset = at91_rst_cpu_reset 294}; 295 296AT91_SOC_SUB(AT91_T_SAM9X5, AT91_ST_SAM9X25, &soc_data); 297