at91rm9200.c revision 238331
1126385Smlaier/*- 2126385Smlaier * Copyright (c) 2005 Olivier Houchard. All rights reserved. 3240494Sglebius * Copyright (c) 2010 Greg Ansley. All rights reserved. 4240494Sglebius * 5126385Smlaier * Redistribution and use in source and binary forms, with or without 6126385Smlaier * modification, are permitted provided that the following conditions 7240494Sglebius * are met: 8126385Smlaier * 1. Redistributions of source code must retain the above copyright 9126385Smlaier * notice, this list of conditions and the following disclaimer. 10126385Smlaier * 2. Redistributions in binary form must reproduce the above copyright 11145841Smlaier * notice, this list of conditions and the following disclaimer in the 12171173Smlaier * documentation and/or other materials provided with the distribution. 13126385Smlaier * 14198236Sru * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15126385Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16240494Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17240494Sglebius * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18126385Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19126385Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20126385Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21126385Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22157721Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23126385Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24126385Smlaier * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/arm/at91/at91rm9200.c 238331 2012-07-10 02:39:03Z 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/at91rm92reg.h> 43#include <arm/at91/at91_aicreg.h> 44#include <arm/at91/at91_pmcreg.h> 45#include <arm/at91/at91_pmcvar.h> 46 47struct at91rm92_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 * 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, which differ 59 * a little form the ones that are in the standard distribution. Also, 60 * the ones marked with 'TWEEK' are different based on experience. 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 */ 67 1, /* Parallel IO Controller B */ 68 1, /* Parallel IO Controller C */ 69 1, /* Parallel IO Controller D */ 70 5, /* USART 0 */ 71 5, /* USART 1 */ 72 5, /* USART 2 */ 73 5, /* USART 3 */ 74 0, /* Multimedia Card Interface */ 75 2, /* USB Device Port */ 76 4, /* Two-Wire Interface */ /* TWEEK */ 77 5, /* Serial Peripheral Interface */ 78 4, /* Serial Synchronous Controller 0 */ 79 6, /* Serial Synchronous Controller 1 */ /* TWEEK */ 80 4, /* Serial Synchronous Controller 2 */ 81 0, /* Timer Counter 0 */ 82 6, /* Timer Counter 1 */ /* TWEEK */ 83 0, /* Timer Counter 2 */ 84 0, /* Timer Counter 3 */ 85 0, /* Timer Counter 4 */ 86 0, /* Timer Counter 5 */ 87 2, /* USB Host port */ 88 3, /* Ethernet MAC */ 89 0, /* Advanced Interrupt Controller (IRQ0) */ 90 0, /* Advanced Interrupt Controller (IRQ1) */ 91 0, /* Advanced Interrupt Controller (IRQ2) */ 92 0, /* Advanced Interrupt Controller (IRQ3) */ 93 0, /* Advanced Interrupt Controller (IRQ4) */ 94 0, /* Advanced Interrupt Controller (IRQ5) */ 95 0 /* Advanced Interrupt Controller (IRQ6) */ 96}; 97 98#define DEVICE(_name, _id, _unit) \ 99 { \ 100 _name, _unit, \ 101 AT91RM92_ ## _id ##_BASE, \ 102 AT91RM92_ ## _id ## _SIZE, \ 103 AT91RM92_IRQ_ ## _id \ 104 } 105 106static const struct cpu_devs at91_devs[] = 107{ 108 DEVICE("at91_pmc", PMC, 0), 109 DEVICE("at91_st", ST, 0), 110 DEVICE("at91_pio", PIOA, 0), 111 DEVICE("at91_pio", PIOB, 1), 112 DEVICE("at91_pio", PIOC, 2), 113 DEVICE("at91_pio", PIOD, 3), 114 DEVICE("at91_rtc", RTC, 0), 115 116 DEVICE("at91_mci", MCI, 0), 117 DEVICE("at91_twi", TWI, 0), 118 DEVICE("at91_udp", UDP, 0), 119 DEVICE("ate", EMAC, 0), 120 DEVICE("at91_ssc", SSC0, 0), 121 DEVICE("at91_ssc", SSC1, 1), 122 DEVICE("at91_ssc", SSC2, 2), 123 DEVICE("spi", SPI, 0), 124 125 DEVICE("uart", DBGU, 0), 126 DEVICE("uart", USART0, 1), 127 DEVICE("uart", USART1, 2), 128 DEVICE("uart", USART2, 3), 129 DEVICE("uart", USART3, 4), 130 DEVICE("at91_aic", AIC, 0), 131 DEVICE("at91_mc", MC, 0), 132 DEVICE("at91_tc", TC0, 0), 133 DEVICE("at91_tc", TC1, 1), 134 DEVICE("ohci", OHCI, 0), 135 DEVICE("af91_cfata", CF, 0), 136 { 0, 0, 0, 0, 0 } 137}; 138 139static void 140at91_add_child(device_t dev, int prio, const char *name, int unit, 141 bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) 142{ 143 device_t kid; 144 struct at91_ivar *ivar; 145 146 kid = device_add_child_ordered(dev, prio, name, unit); 147 if (kid == NULL) { 148 printf("Can't add child %s%d ordered\n", name, unit); 149 return; 150 } 151 ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 152 if (ivar == NULL) { 153 device_delete_child(dev, kid); 154 printf("Can't add alloc ivar\n"); 155 return; 156 } 157 device_set_ivars(kid, ivar); 158 resource_list_init(&ivar->resources); 159 if (irq0 != -1) { 160 bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); 161 if (irq0 != AT91_IRQ_SYSTEM) 162 at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); 163 } 164 if (irq1 != 0) 165 bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); 166 if (irq2 != 0) 167 bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); 168 if (addr != 0 && addr < AT91_BASE) 169 addr += AT91_BASE; 170 if (addr != 0) 171 bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); 172} 173 174static void 175at91_cpu_add_builtin_children(device_t dev) 176{ 177 int i; 178 const struct cpu_devs *walker; 179 180 for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 181 at91_add_child(dev, i, walker->name, walker->unit, 182 walker->mem_base, walker->mem_len, walker->irq0, 183 walker->irq1, walker->irq2); 184 } 185} 186 187static uint32_t 188at91_pll_outb(int freq) 189{ 190 191 if (freq > 155000000) 192 return (0x0000); 193 else 194 return (0x8000); 195} 196 197static void 198at91_identify(driver_t *drv, device_t parent) 199{ 200 201 if (at91_cpu_is(AT91_T_RM9200)) { 202 at91_add_child(parent, 0, "at91rm920", 0, 0, 0, -1, 0, 0); 203 at91_cpu_add_builtin_children(parent); 204 } 205} 206 207static int 208at91_probe(device_t dev) 209{ 210 211 device_set_desc(dev, soc_data.name); 212 return (0); 213} 214 215static int 216at91_attach(device_t dev) 217{ 218 struct at91_pmc_clock *clk; 219 struct at91rm92_softc *sc = device_get_softc(dev); 220 int i; 221 222 struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 223 224 sc->sc_st = at91sc->sc_st; 225 sc->sc_sh = at91sc->sc_sh; 226 sc->dev = dev; 227 228 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE, 229 AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0) 230 panic("Enable to map system registers"); 231 232 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_DBGU_BASE, 233 AT91RM92_DBGU_SIZE, &sc->sc_dbg_sh) != 0) 234 panic("Enable to map DBGU registers"); 235 236 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_AIC_BASE, 237 AT91RM92_AIC_SIZE, &sc->sc_aic_sh) != 0) 238 panic("Enable to map system registers"); 239 240 /* XXX Hack to tell atmelarm about the AIC */ 241 at91sc->sc_aic_sh = sc->sc_aic_sh; 242 at91sc->sc_irq_system = AT91_IRQ_SYSTEM; 243 244 for (i = 0; i < 32; i++) { 245 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 246 i * 4, i); 247 /* Priority. */ 248 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 249 at91_irq_prio[i]); 250 if (i < 8) 251 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 252 1); 253 } 254 255 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 256 /* No debug. */ 257 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 258 /* Disable and clear all interrupts. */ 259 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 260 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 261 262 /* Disable all interrupts for RTC (0xe24 == RTC_IDR) */ 263 bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff); 264 265 /* Disable all interrupts for the SDRAM controller */ 266 bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff); 267 268 /* Disable all interrupts for DBGU */ 269 bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); 270 271 /* Update USB device port clock info */ 272 clk = at91_pmc_clock_ref("udpck"); 273 clk->pmc_mask = PMC_SCER_UDP; 274 at91_pmc_clock_deref(clk); 275 276 /* Update USB host port clock info */ 277 clk = at91_pmc_clock_ref("uhpck"); 278 clk->pmc_mask = PMC_SCER_UHP; 279 at91_pmc_clock_deref(clk); 280 281 /* Each SOC has different PLL contraints */ 282 clk = at91_pmc_clock_ref("plla"); 283 clk->pll_min_in = RM9200_PLL_A_MIN_IN_FREQ; /* 1 MHz */ 284 clk->pll_max_in = RM9200_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 285 clk->pll_min_out = RM9200_PLL_A_MIN_OUT_FREQ; /* 80 MHz */ 286 clk->pll_max_out = RM9200_PLL_A_MAX_OUT_FREQ; /* 180 MHz */ 287 clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT; 288 clk->pll_mul_mask = RM9200_PLL_A_MUL_MASK; 289 clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT; 290 clk->pll_div_mask = RM9200_PLL_A_DIV_MASK; 291 clk->set_outb = at91_pll_outb; 292 at91_pmc_clock_deref(clk); 293 294 clk = at91_pmc_clock_ref("pllb"); 295 clk->pll_min_in = RM9200_PLL_B_MIN_IN_FREQ; /* 100 KHz */ 296 clk->pll_max_in = RM9200_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 297 clk->pll_min_out = RM9200_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 298 clk->pll_max_out = RM9200_PLL_B_MAX_OUT_FREQ; /* 240 MHz */ 299 clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT; 300 clk->pll_mul_mask = RM9200_PLL_B_MUL_MASK; 301 clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT; 302 clk->pll_div_mask = RM9200_PLL_B_DIV_MASK; 303 clk->set_outb = at91_pll_outb; 304 at91_pmc_clock_deref(clk); 305 306 return (0); 307} 308 309static device_method_t at91_methods[] = { 310 DEVMETHOD(device_probe, at91_probe), 311 DEVMETHOD(device_attach, at91_attach), 312 DEVMETHOD(device_identify, at91_identify), 313 {0, 0}, 314}; 315 316static driver_t at91rm92_driver = { 317 "at91rm920", 318 at91_methods, 319 sizeof(struct at91rm92_softc), 320}; 321 322static devclass_t at91rm92_devclass; 323 324DRIVER_MODULE(at91rm920, atmelarm, at91rm92_driver, at91rm92_devclass, 0, 0); 325