at91sam9g20.c revision 213496
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 213496 2010-10-06 22:25:21Z cognet $"); 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/at91_aicreg.h> 42#include <arm/at91/at91sam9g20reg.h> 43#include <arm/at91/at91_pmcreg.h> 44#include <arm/at91/at91_pmcvar.h> 45 46struct at91sam9_softc { 47 device_t dev; 48 bus_space_tag_t sc_st; 49 bus_space_handle_t sc_sh; 50 bus_space_handle_t sc_sys_sh; 51 bus_space_handle_t sc_aic_sh; 52 bus_space_handle_t sc_dbg_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_add_child(device_t dev, int prio, const char *name, int unit, 133 bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) 134{ 135 device_t kid; 136 struct at91_ivar *ivar; 137 138 kid = device_add_child_ordered(dev, prio, name, unit); 139 if (kid == NULL) { 140 printf("Can't add child %s%d ordered\n", name, unit); 141 return; 142 } 143 ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 144 if (ivar == NULL) { 145 device_delete_child(dev, kid); 146 printf("Can't add alloc ivar\n"); 147 return; 148 } 149 device_set_ivars(kid, ivar); 150 resource_list_init(&ivar->resources); 151 if (irq0 != -1) { 152 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); 153 if (irq0 != AT91SAM9G20_IRQ_SYSTEM) 154 at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); 155 } 156 if (irq1 != 0) 157 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); 158 if (irq2 != 0) 159 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); 160 if (addr != 0 && addr < AT91SAM9G20_BASE) 161 addr += AT91SAM9G20_BASE; 162 if (addr != 0) 163 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); 164} 165 166static void 167at91_cpu_add_builtin_children(device_t dev) 168{ 169 int i; 170 const struct cpu_devs *walker; 171 172 for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 173 at91_add_child(dev, i, walker->name, walker->unit, 174 walker->mem_base, walker->mem_len, walker->irq0, 175 walker->irq1, walker->irq2); 176 } 177} 178 179static void 180at91_identify(driver_t *drv, device_t parent) 181{ 182 183 if (at91_cpu_is(AT91_CPU_SAM9G20)) { 184 at91_add_child(parent, 0, "at91sam", 9, 0, 0, -1, 0, 0); 185 at91_cpu_add_builtin_children(parent); 186 } 187} 188 189static int 190at91_probe(device_t dev) 191{ 192 193 if (at91_cpu_is(AT91_CPU_SAM9G20)) { 194 device_set_desc(dev, "AT91SAM9G20"); 195 return (0); 196 } 197 return (ENXIO); 198} 199 200static int 201at91_attach(device_t dev) 202{ 203 struct at91_pmc_clock *clk; 204 struct at91sam9_softc *sc = device_get_softc(dev); 205 int i; 206 207 struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 208 209 sc->sc_st = at91sc->sc_st; 210 sc->sc_sh = at91sc->sc_sh; 211 sc->dev = dev; 212 213 /* 214 * XXX These values work for the RM9200, SAM926[01], and SAM9G20 215 * will have to fix this when we want to support anything else. XXX 216 */ 217 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_SYS_BASE, 218 AT91SAM9G20_SYS_SIZE, &sc->sc_sys_sh) != 0) 219 panic("Enable to map system registers"); 220 221 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_DBGU_BASE, 222 AT91SAM9G20_DBGU_SIZE, &sc->sc_dbg_sh) != 0) 223 panic("Enable to map DBGU registers"); 224 225 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9G20_AIC_BASE, 226 AT91SAM9G20_AIC_SIZE, &sc->sc_aic_sh) != 0) 227 panic("Enable to map system registers"); 228 229 /* XXX Hack to tell atmelarm about the AIC */ 230 at91sc->sc_aic_sh = sc->sc_aic_sh; 231 at91sc->sc_irq_system = AT91SAM9G20_IRQ_SYSTEM; 232 233 for (i = 0; i < 32; i++) { 234 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 235 i * 4, i); 236 /* Priority. */ 237 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 238 at91_irq_prio[i]); 239 if (i < 8) 240 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 241 1); 242 } 243 244 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 245 /* No debug. */ 246 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 247 /* Disable and clear all interrupts. */ 248 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 249 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 250 251 /* Disable all interrupts for DBGU */ 252 bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); 253 254 if (bus_space_subregion(sc->sc_st, sc->sc_sh, 255 AT91SAM9G20_MATRIX_BASE, AT91SAM9G20_MATRIX_SIZE, 256 &sc->sc_matrix_sh) != 0) 257 panic("Enable to map matrix registers"); 258 259 /* activate NAND*/ 260 i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh, 261 AT91SAM9G20_EBICSA); 262 bus_space_write_4(sc->sc_st, sc->sc_matrix_sh, 263 AT91SAM9G20_EBICSA, 264 i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); 265 266 267 /* Update USB device port clock info */ 268 clk = at91_pmc_clock_ref("udpck"); 269 clk->pmc_mask = PMC_SCER_UDP_SAM9; 270 at91_pmc_clock_deref(clk); 271 272 /* Update USB host port clock info */ 273 clk = at91_pmc_clock_ref("uhpck"); 274 clk->pmc_mask = PMC_SCER_UHP_SAM9; 275 at91_pmc_clock_deref(clk); 276 277 /* Each SOC has different PLL contraints */ 278 clk = at91_pmc_clock_ref("plla"); 279 clk->pll_min_in = SAM9G20_PLL_A_MIN_IN_FREQ; /* 2 MHz */ 280 clk->pll_max_in = SAM9G20_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 281 clk->pll_min_out = SAM9G20_PLL_A_MIN_OUT_FREQ; /* 400 MHz */ 282 clk->pll_max_out = SAM9G20_PLL_A_MAX_OUT_FREQ; /* 800 MHz */ 283 clk->pll_mul_shift = SAM9G20_PLL_A_MUL_SHIFT; 284 clk->pll_mul_mask = SAM9G20_PLL_A_MUL_MASK; 285 clk->pll_div_shift = SAM9G20_PLL_A_DIV_SHIFT; 286 clk->pll_div_mask = SAM9G20_PLL_A_DIV_MASK; 287 at91_pmc_clock_deref(clk); 288 289 clk = at91_pmc_clock_ref("pllb"); 290 clk->pll_min_in = SAM9G20_PLL_B_MIN_IN_FREQ; /* 2 MHz */ 291 clk->pll_max_in = SAM9G20_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 292 clk->pll_min_out = SAM9G20_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 293 clk->pll_max_out = SAM9G20_PLL_B_MAX_OUT_FREQ; /* 100 MHz */ 294 clk->pll_mul_shift = SAM9G20_PLL_B_MUL_SHIFT; 295 clk->pll_mul_mask = SAM9G20_PLL_B_MUL_MASK; 296 clk->pll_div_shift = SAM9G20_PLL_B_DIV_SHIFT; 297 clk->pll_div_mask = SAM9G20_PLL_B_DIV_MASK; 298 at91_pmc_clock_deref(clk); 299 return (0); 300} 301 302static device_method_t at91_methods[] = { 303 DEVMETHOD(device_probe, at91_probe), 304 DEVMETHOD(device_attach, at91_attach), 305 DEVMETHOD(device_identify, at91_identify), 306 {0, 0}, 307}; 308 309static driver_t at91sam9_driver = { 310 "at91sam", 311 at91_methods, 312 sizeof(struct at91sam9_softc), 313}; 314 315static devclass_t at91sam9_devclass; 316 317DRIVER_MODULE(at91sam, atmelarm, at91sam9_driver, at91sam9_devclass, 0, 0); 318