at91rm9200.c revision 238354
1178172Simp/*- 2178172Simp * Copyright (c) 2005 Olivier Houchard. All rights reserved. 3178172Simp * Copyright (c) 2010 Greg Ansley. All rights reserved. 4178172Simp * 5178172Simp * Redistribution and use in source and binary forms, with or without 6178172Simp * modification, are permitted provided that the following conditions 7178172Simp * are met: 8178172Simp * 1. Redistributions of source code must retain the above copyright 9178172Simp * notice, this list of conditions and the following disclaimer. 10178172Simp * 2. Redistributions in binary form must reproduce the above copyright 11178172Simp * notice, this list of conditions and the following disclaimer in the 12178172Simp * documentation and/or other materials provided with the distribution. 13178172Simp * 14178172Simp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24178172Simp * SUCH DAMAGE. 25178172Simp */ 26178172Simp 27178172Simp#include <sys/cdefs.h> 28178172Simp__FBSDID("$FreeBSD: head/sys/arm/at91/at91rm9200.c 238354 2012-07-10 19:48:42Z imp $"); 29178172Simp 30178172Simp#include <sys/param.h> 31178172Simp#include <sys/systm.h> 32178172Simp#include <sys/bus.h> 33178172Simp#include <sys/kernel.h> 34178172Simp#include <sys/malloc.h> 35178172Simp#include <sys/module.h> 36178172Simp 37178172Simp#define _ARM32_BUS_DMA_PRIVATE 38178172Simp#include <machine/bus.h> 39178172Simp 40178172Simp#include <arm/at91/at91var.h> 41178172Simp#include <arm/at91/at91reg.h> 42202031Simp#include <arm/at91/at91rm92reg.h> 43178172Simp#include <arm/at91/at91_aicreg.h> 44178172Simp#include <arm/at91/at91_pmcreg.h> 45214903Sgonzo#include <arm/at91/at91_pmcvar.h> 46214903Sgonzo 47178172Simpstruct at91rm92_softc { 48178172Simp device_t dev; 49202909Sgonzo bus_space_tag_t sc_st; 50178172Simp bus_space_handle_t sc_sh; 51178172Simp bus_space_handle_t sc_sys_sh; 52178172Simp bus_space_handle_t sc_aic_sh; 53178172Simp bus_space_handle_t sc_matrix_sh; 54202031Simp}; 55202031Simp/* 56178172Simp * Standard priority levels for the system. 0 is lowest and 7 is highest. 57217345Sjchandra * These values are the ones Atmel uses for its Linux port, which differ 58202830Simp * a little form the ones that are in the standard distribution. Also, 59226517Sjchandra * the ones marked with 'TWEEK' are different based on experience. 60178172Simp */ 61178172Simpstatic const int at91_irq_prio[32] = 62178172Simp{ 63178172Simp 7, /* Advanced Interrupt Controller (FIQ) */ 64178172Simp 7, /* System Peripherals */ 65178172Simp 1, /* Parallel IO Controller A */ 66178172Simp 1, /* Parallel IO Controller B */ 67178172Simp 1, /* Parallel IO Controller C */ 68178172Simp 1, /* Parallel IO Controller D */ 69178172Simp 5, /* USART 0 */ 70178172Simp 5, /* USART 1 */ 71202031Simp 5, /* USART 2 */ 72178172Simp 5, /* USART 3 */ 73202909Sgonzo 0, /* Multimedia Card Interface */ 74178172Simp 2, /* USB Device Port */ 75178172Simp 4, /* Two-Wire Interface */ /* TWEEK */ 76178172Simp 5, /* Serial Peripheral Interface */ 77178172Simp 4, /* Serial Synchronous Controller 0 */ 78202031Simp 6, /* Serial Synchronous Controller 1 */ /* TWEEK */ 79212532Sjchandra 4, /* Serial Synchronous Controller 2 */ 80214903Sgonzo 0, /* Timer Counter 0 */ 81216148Sjchandra 6, /* Timer Counter 1 */ /* TWEEK */ 82216148Sjchandra 0, /* Timer Counter 2 */ 83216148Sjchandra 0, /* Timer Counter 3 */ 84216148Sjchandra 0, /* Timer Counter 4 */ 85178172Simp 0, /* Timer Counter 5 */ 86 2, /* USB Host port */ 87 3, /* Ethernet MAC */ 88 0, /* Advanced Interrupt Controller (IRQ0) */ 89 0, /* Advanced Interrupt Controller (IRQ1) */ 90 0, /* Advanced Interrupt Controller (IRQ2) */ 91 0, /* Advanced Interrupt Controller (IRQ3) */ 92 0, /* Advanced Interrupt Controller (IRQ4) */ 93 0, /* Advanced Interrupt Controller (IRQ5) */ 94 0 /* Advanced Interrupt Controller (IRQ6) */ 95}; 96 97#define DEVICE(_name, _id, _unit) \ 98 { \ 99 _name, _unit, \ 100 AT91RM92_ ## _id ##_BASE, \ 101 AT91RM92_ ## _id ## _SIZE, \ 102 AT91RM92_IRQ_ ## _id \ 103 } 104 105static const struct cpu_devs at91_devs[] = 106{ 107 DEVICE("at91_pmc", PMC, 0), 108 DEVICE("at91_st", ST, 0), 109 DEVICE("at91_pio", PIOA, 0), 110 DEVICE("at91_pio", PIOB, 1), 111 DEVICE("at91_pio", PIOC, 2), 112 DEVICE("at91_pio", PIOD, 3), 113 DEVICE("at91_rtc", RTC, 0), 114 115 DEVICE("at91_mci", MCI, 0), 116 DEVICE("at91_twi", TWI, 0), 117 DEVICE("at91_udp", UDP, 0), 118 DEVICE("ate", EMAC, 0), 119 DEVICE("at91_ssc", SSC0, 0), 120 DEVICE("at91_ssc", SSC1, 1), 121 DEVICE("at91_ssc", SSC2, 2), 122 DEVICE("spi", SPI, 0), 123 124 DEVICE("uart", DBGU, 0), 125 DEVICE("uart", USART0, 1), 126 DEVICE("uart", USART1, 2), 127 DEVICE("uart", USART2, 3), 128 DEVICE("uart", USART3, 4), 129 DEVICE("at91_aic", AIC, 0), 130 DEVICE("at91_mc", MC, 0), 131 DEVICE("at91_tc", TC0, 0), 132 DEVICE("at91_tc", TC1, 1), 133 DEVICE("ohci", OHCI, 0), 134 DEVICE("af91_cfata", CF, 0), 135 { 0, 0, 0, 0, 0 } 136}; 137 138static void 139at91_cpu_add_builtin_children(device_t dev) 140{ 141 int i; 142 const struct cpu_devs *walker; 143 144 for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 145 at91_add_child(dev, i, walker->name, walker->unit, 146 walker->mem_base, walker->mem_len, walker->irq0, 147 walker->irq1, walker->irq2); 148 } 149} 150 151static uint32_t 152at91_pll_outb(int freq) 153{ 154 155 if (freq > 155000000) 156 return (0x0000); 157 else 158 return (0x8000); 159} 160 161static void 162at91_identify(driver_t *drv, device_t parent) 163{ 164 165 if (at91_cpu_is(AT91_T_RM9200)) { 166 at91_add_child(parent, 0, "at91rm920", 0, 0, 0, -1, 0, 0); 167 at91_cpu_add_builtin_children(parent); 168 } 169} 170 171static int 172at91_probe(device_t dev) 173{ 174 175 device_set_desc(dev, soc_data.name); 176 return (0); 177} 178 179static int 180at91_attach(device_t dev) 181{ 182 struct at91_pmc_clock *clk; 183 struct at91rm92_softc *sc = device_get_softc(dev); 184 int i; 185 186 struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 187 188 sc->sc_st = at91sc->sc_st; 189 sc->sc_sh = at91sc->sc_sh; 190 sc->dev = dev; 191 192 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_SYS_BASE, 193 AT91RM92_SYS_SIZE, &sc->sc_sys_sh) != 0) 194 panic("Enable to map system registers"); 195 196 if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91RM92_AIC_BASE, 197 AT91RM92_AIC_SIZE, &sc->sc_aic_sh) != 0) 198 panic("Enable to map system registers"); 199 200 /* XXX Hack to tell atmelarm about the AIC */ 201 at91sc->sc_aic_sh = sc->sc_aic_sh; 202 203 for (i = 0; i < 32; i++) { 204 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 205 i * 4, i); 206 /* Priority. */ 207 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 208 at91_irq_prio[i]); 209 if (i < 8) 210 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 211 1); 212 } 213 214 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 215 /* No debug. */ 216 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 217 /* Disable and clear all interrupts. */ 218 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 219 bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 220 221 /* Disable all interrupts for RTC (0xe24 == RTC_IDR) */ 222 bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff); 223 224 /* Disable all interrupts for the SDRAM controller */ 225 bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff); 226 227 /* Update USB device port clock info */ 228 clk = at91_pmc_clock_ref("udpck"); 229 clk->pmc_mask = PMC_SCER_UDP; 230 at91_pmc_clock_deref(clk); 231 232 /* Update USB host port clock info */ 233 clk = at91_pmc_clock_ref("uhpck"); 234 clk->pmc_mask = PMC_SCER_UHP; 235 at91_pmc_clock_deref(clk); 236 237 /* Each SOC has different PLL contraints */ 238 clk = at91_pmc_clock_ref("plla"); 239 clk->pll_min_in = RM9200_PLL_A_MIN_IN_FREQ; /* 1 MHz */ 240 clk->pll_max_in = RM9200_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 241 clk->pll_min_out = RM9200_PLL_A_MIN_OUT_FREQ; /* 80 MHz */ 242 clk->pll_max_out = RM9200_PLL_A_MAX_OUT_FREQ; /* 180 MHz */ 243 clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT; 244 clk->pll_mul_mask = RM9200_PLL_A_MUL_MASK; 245 clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT; 246 clk->pll_div_mask = RM9200_PLL_A_DIV_MASK; 247 clk->set_outb = at91_pll_outb; 248 at91_pmc_clock_deref(clk); 249 250 clk = at91_pmc_clock_ref("pllb"); 251 clk->pll_min_in = RM9200_PLL_B_MIN_IN_FREQ; /* 100 KHz */ 252 clk->pll_max_in = RM9200_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 253 clk->pll_min_out = RM9200_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 254 clk->pll_max_out = RM9200_PLL_B_MAX_OUT_FREQ; /* 240 MHz */ 255 clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT; 256 clk->pll_mul_mask = RM9200_PLL_B_MUL_MASK; 257 clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT; 258 clk->pll_div_mask = RM9200_PLL_B_DIV_MASK; 259 clk->set_outb = at91_pll_outb; 260 at91_pmc_clock_deref(clk); 261 262 return (0); 263} 264 265static device_method_t at91_methods[] = { 266 DEVMETHOD(device_probe, at91_probe), 267 DEVMETHOD(device_attach, at91_attach), 268 DEVMETHOD(device_identify, at91_identify), 269 {0, 0}, 270}; 271 272static driver_t at91rm92_driver = { 273 "at91rm920", 274 at91_methods, 275 sizeof(struct at91rm92_softc), 276}; 277 278static devclass_t at91rm92_devclass; 279 280DRIVER_MODULE(at91rm920, atmelarm, at91rm92_driver, at91rm92_devclass, 0, 0); 281