at91rm9200.c revision 266277
1213496Scognet/*- 2213496Scognet * Copyright (c) 2005 Olivier Houchard. All rights reserved. 3213496Scognet * Copyright (c) 2010 Greg Ansley. All rights reserved. 4213496Scognet * 5213496Scognet * Redistribution and use in source and binary forms, with or without 6213496Scognet * modification, are permitted provided that the following conditions 7213496Scognet * are met: 8213496Scognet * 1. Redistributions of source code must retain the above copyright 9213496Scognet * notice, this list of conditions and the following disclaimer. 10213496Scognet * 2. Redistributions in binary form must reproduce the above copyright 11213496Scognet * notice, this list of conditions and the following disclaimer in the 12213496Scognet * documentation and/or other materials provided with the distribution. 13213496Scognet * 14213496Scognet * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15213496Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16213496Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17213496Scognet * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 18213496Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19213496Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20213496Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21213496Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22213496Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23213496Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24213496Scognet * SUCH DAMAGE. 25213496Scognet */ 26213496Scognet 27213496Scognet#include <sys/cdefs.h> 28213496Scognet__FBSDID("$FreeBSD: stable/10/sys/arm/at91/at91rm9200.c 266277 2014-05-17 00:53:12Z ian $"); 29213496Scognet 30213496Scognet#include <sys/param.h> 31213496Scognet#include <sys/systm.h> 32213496Scognet#include <sys/bus.h> 33213496Scognet#include <sys/kernel.h> 34213496Scognet#include <sys/malloc.h> 35213496Scognet#include <sys/module.h> 36213496Scognet 37213496Scognet#define _ARM32_BUS_DMA_PRIVATE 38213496Scognet#include <machine/bus.h> 39213496Scognet 40213496Scognet#include <arm/at91/at91var.h> 41238331Simp#include <arm/at91/at91reg.h> 42213496Scognet#include <arm/at91/at91rm92reg.h> 43213496Scognet#include <arm/at91/at91_aicreg.h> 44213496Scognet#include <arm/at91/at91_pmcreg.h> 45238376Simp#include <arm/at91/at91_streg.h> 46213496Scognet#include <arm/at91/at91_pmcvar.h> 47238376Simp#include <arm/at91/at91soc.h> 48213496Scognet 49213496Scognet/* 50213496Scognet * Standard priority levels for the system. 0 is lowest and 7 is highest. 51213496Scognet * These values are the ones Atmel uses for its Linux port, which differ 52213496Scognet * a little form the ones that are in the standard distribution. Also, 53213496Scognet * the ones marked with 'TWEEK' are different based on experience. 54213496Scognet */ 55213496Scognetstatic const int at91_irq_prio[32] = 56213496Scognet{ 57213496Scognet 7, /* Advanced Interrupt Controller (FIQ) */ 58213496Scognet 7, /* System Peripherals */ 59213496Scognet 1, /* Parallel IO Controller A */ 60213496Scognet 1, /* Parallel IO Controller B */ 61213496Scognet 1, /* Parallel IO Controller C */ 62213496Scognet 1, /* Parallel IO Controller D */ 63213496Scognet 5, /* USART 0 */ 64213496Scognet 5, /* USART 1 */ 65213496Scognet 5, /* USART 2 */ 66213496Scognet 5, /* USART 3 */ 67213496Scognet 0, /* Multimedia Card Interface */ 68213496Scognet 2, /* USB Device Port */ 69213496Scognet 4, /* Two-Wire Interface */ /* TWEEK */ 70213496Scognet 5, /* Serial Peripheral Interface */ 71213496Scognet 4, /* Serial Synchronous Controller 0 */ 72213496Scognet 6, /* Serial Synchronous Controller 1 */ /* TWEEK */ 73213496Scognet 4, /* Serial Synchronous Controller 2 */ 74213496Scognet 0, /* Timer Counter 0 */ 75213496Scognet 6, /* Timer Counter 1 */ /* TWEEK */ 76213496Scognet 0, /* Timer Counter 2 */ 77213496Scognet 0, /* Timer Counter 3 */ 78213496Scognet 0, /* Timer Counter 4 */ 79213496Scognet 0, /* Timer Counter 5 */ 80213496Scognet 2, /* USB Host port */ 81213496Scognet 3, /* Ethernet MAC */ 82213496Scognet 0, /* Advanced Interrupt Controller (IRQ0) */ 83213496Scognet 0, /* Advanced Interrupt Controller (IRQ1) */ 84213496Scognet 0, /* Advanced Interrupt Controller (IRQ2) */ 85213496Scognet 0, /* Advanced Interrupt Controller (IRQ3) */ 86213496Scognet 0, /* Advanced Interrupt Controller (IRQ4) */ 87213496Scognet 0, /* Advanced Interrupt Controller (IRQ5) */ 88213496Scognet 0 /* Advanced Interrupt Controller (IRQ6) */ 89213496Scognet}; 90213496Scognet 91266087Sianstatic const uint32_t at91_pio_base[] = { 92266087Sian AT91RM92_PIOA_BASE, 93266087Sian AT91RM92_PIOB_BASE, 94266087Sian AT91RM92_PIOC_BASE, 95266087Sian AT91RM92_PIOD_BASE, 96266087Sian}; 97266087Sian 98213496Scognet#define DEVICE(_name, _id, _unit) \ 99213496Scognet { \ 100213496Scognet _name, _unit, \ 101213496Scognet AT91RM92_ ## _id ##_BASE, \ 102213496Scognet AT91RM92_ ## _id ## _SIZE, \ 103213496Scognet AT91RM92_IRQ_ ## _id \ 104213496Scognet } 105213496Scognet 106213496Scognetstatic const struct cpu_devs at91_devs[] = 107213496Scognet{ 108266277Sian DEVICE("at91_aic", AIC, 0), 109213496Scognet DEVICE("at91_pmc", PMC, 0), 110213496Scognet DEVICE("at91_st", ST, 0), 111213496Scognet DEVICE("at91_pio", PIOA, 0), 112213496Scognet DEVICE("at91_pio", PIOB, 1), 113213496Scognet DEVICE("at91_pio", PIOC, 2), 114213496Scognet DEVICE("at91_pio", PIOD, 3), 115213496Scognet DEVICE("at91_rtc", RTC, 0), 116213496Scognet 117213496Scognet DEVICE("at91_mci", MCI, 0), 118213496Scognet DEVICE("at91_twi", TWI, 0), 119213496Scognet DEVICE("at91_udp", UDP, 0), 120213496Scognet DEVICE("ate", EMAC, 0), 121213496Scognet DEVICE("at91_ssc", SSC0, 0), 122213496Scognet DEVICE("at91_ssc", SSC1, 1), 123213496Scognet DEVICE("at91_ssc", SSC2, 2), 124213496Scognet DEVICE("spi", SPI, 0), 125213496Scognet 126213496Scognet DEVICE("uart", DBGU, 0), 127213496Scognet DEVICE("uart", USART0, 1), 128213496Scognet DEVICE("uart", USART1, 2), 129213496Scognet DEVICE("uart", USART2, 3), 130213496Scognet DEVICE("uart", USART3, 4), 131213496Scognet DEVICE("at91_aic", AIC, 0), 132213496Scognet DEVICE("at91_mc", MC, 0), 133213496Scognet DEVICE("at91_tc", TC0, 0), 134213496Scognet DEVICE("at91_tc", TC1, 1), 135213496Scognet DEVICE("ohci", OHCI, 0), 136248944Sian DEVICE("at91_cfata", CF, 0), 137213496Scognet { 0, 0, 0, 0, 0 } 138213496Scognet}; 139213496Scognet 140213496Scognetstatic uint32_t 141213496Scognetat91_pll_outb(int freq) 142213496Scognet{ 143213496Scognet 144213496Scognet if (freq > 155000000) 145213496Scognet return (0x0000); 146236989Simp else 147213496Scognet return (0x8000); 148213496Scognet} 149213496Scognet 150238397Simp#if 0 151238397Simp/* -- XXX are these needed? */ 152213496Scognet /* Disable all interrupts for RTC (0xe24 == RTC_IDR) */ 153213496Scognet bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xe24, 0xffffffff); 154213496Scognet 155213496Scognet /* Disable all interrupts for the SDRAM controller */ 156213496Scognet bus_space_write_4(sc->sc_st, sc->sc_sys_sh, 0xfa8, 0xffffffff); 157238397Simp#endif 158213496Scognet 159238397Simpstatic void 160238397Simpat91_clock_init(void) 161238397Simp{ 162238397Simp struct at91_pmc_clock *clk; 163238397Simp 164213496Scognet /* Update USB device port clock info */ 165213496Scognet clk = at91_pmc_clock_ref("udpck"); 166213496Scognet clk->pmc_mask = PMC_SCER_UDP; 167213496Scognet at91_pmc_clock_deref(clk); 168213496Scognet 169213496Scognet /* Update USB host port clock info */ 170213496Scognet clk = at91_pmc_clock_ref("uhpck"); 171213496Scognet clk->pmc_mask = PMC_SCER_UHP; 172213496Scognet at91_pmc_clock_deref(clk); 173213496Scognet 174213496Scognet /* Each SOC has different PLL contraints */ 175213496Scognet clk = at91_pmc_clock_ref("plla"); 176213496Scognet clk->pll_min_in = RM9200_PLL_A_MIN_IN_FREQ; /* 1 MHz */ 177213496Scognet clk->pll_max_in = RM9200_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 178213496Scognet clk->pll_min_out = RM9200_PLL_A_MIN_OUT_FREQ; /* 80 MHz */ 179213496Scognet clk->pll_max_out = RM9200_PLL_A_MAX_OUT_FREQ; /* 180 MHz */ 180213496Scognet clk->pll_mul_shift = RM9200_PLL_A_MUL_SHIFT; 181213496Scognet clk->pll_mul_mask = RM9200_PLL_A_MUL_MASK; 182213496Scognet clk->pll_div_shift = RM9200_PLL_A_DIV_SHIFT; 183213496Scognet clk->pll_div_mask = RM9200_PLL_A_DIV_MASK; 184213496Scognet clk->set_outb = at91_pll_outb; 185213496Scognet at91_pmc_clock_deref(clk); 186213496Scognet 187213496Scognet clk = at91_pmc_clock_ref("pllb"); 188213496Scognet clk->pll_min_in = RM9200_PLL_B_MIN_IN_FREQ; /* 100 KHz */ 189213496Scognet clk->pll_max_in = RM9200_PLL_B_MAX_IN_FREQ; /* 32 MHz */ 190213496Scognet clk->pll_min_out = RM9200_PLL_B_MIN_OUT_FREQ; /* 30 MHz */ 191213496Scognet clk->pll_max_out = RM9200_PLL_B_MAX_OUT_FREQ; /* 240 MHz */ 192213496Scognet clk->pll_mul_shift = RM9200_PLL_B_MUL_SHIFT; 193213496Scognet clk->pll_mul_mask = RM9200_PLL_B_MUL_MASK; 194213496Scognet clk->pll_div_shift = RM9200_PLL_B_DIV_SHIFT; 195213496Scognet clk->pll_div_mask = RM9200_PLL_B_DIV_MASK; 196213496Scognet clk->set_outb = at91_pll_outb; 197213496Scognet at91_pmc_clock_deref(clk); 198213496Scognet} 199213496Scognet 200238376Simpstatic struct at91_soc_data soc_data = { 201238376Simp .soc_delay = at91_st_delay, 202238389Simp .soc_reset = at91_st_cpu_reset, 203238397Simp .soc_clock_init = at91_clock_init, 204238389Simp .soc_irq_prio = at91_irq_prio, 205238390Simp .soc_children = at91_devs, 206266087Sian .soc_pio_base = at91_pio_base, 207266087Sian .soc_pio_count = nitems(at91_pio_base), 208238376Simp}; 209238376Simp 210238376SimpAT91_SOC(AT91_T_RM9200, &soc_data); 211