11844Swollman/*- 250476Speter * Copyright (c) 2005 Olivier Houchard. All rights reserved. 31844Swollman * Copyright (c) 2010 Greg Ansley. All rights reserved. 41638Srgrimes * 594940Sru * Redistribution and use in source and binary forms, with or without 61638Srgrimes * modification, are permitted provided that the following conditions 71844Swollman * are met: 81844Swollman * 1. Redistributions of source code must retain the above copyright 938655Sjb * notice, this list of conditions and the following disclaimer. 101844Swollman * 2. Redistributions in binary form must reproduce the above copyright 111844Swollman * notice, this list of conditions and the following disclaimer in the 1228945Speter * documentation and/or other materials provided with the distribution. 131844Swollman * 1442915Sjdp * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1542915Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1642915Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1742915Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 1842915Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1942915Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2042915Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2142915Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2242915Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2342915Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2442915Sjdp * SUCH DAMAGE. 2542915Sjdp */ 2629141Speter 2742915Sjdp#include <sys/cdefs.h> 2842915Sjdp__FBSDID("$FreeBSD$"); 2942915Sjdp 3042915Sjdp#include <sys/param.h> 3142915Sjdp#include <sys/systm.h> 3242915Sjdp#include <sys/bus.h> 3342915Sjdp#include <sys/kernel.h> 3429141Speter#include <sys/malloc.h> 352827Sjkh#include <sys/module.h> 362827Sjkh 372827Sjkh#define _ARM32_BUS_DMA_PRIVATE 382827Sjkh#include <machine/bus.h> 392827Sjkh 401638Srgrimes#include <arm/at91/at91var.h> 412827Sjkh#include <arm/at91/at91_aicreg.h> 421638Srgrimes#include <arm/at91/at91sam9260reg.h> 4343055Sjdp#include <arm/at91/at91_pmcreg.h> 4418529Sbde#include <arm/at91/at91_pmcvar.h> 4531809Sbde 4618529Sbdestruct at91sam9_softc { 471638Srgrimes device_t dev; 4842450Sjdp bus_space_tag_t sc_st; 491638Srgrimes bus_space_handle_t sc_sh; 5095064Sobrien bus_space_handle_t sc_sys_sh; 511638Srgrimes bus_space_handle_t sc_aic_sh; 5292491Smarkm bus_space_handle_t sc_dbg_sh; 5392491Smarkm bus_space_handle_t sc_matrix_sh; 5492553Sru}; 5592491Smarkm 5692491Smarkm/* 5792553Sru * Standard priority levels for the system. 0 is lowest and 7 is highest. 5892553Sru * These values are the ones Atmel uses for its Linux port 5992491Smarkm */ 601638Srgrimesstatic const int at91_irq_prio[32] = 611844Swollman{ 6238186Speter 7, /* Advanced Interrupt Controller */ 6338186Speter 7, /* System Peripherals */ 641638Srgrimes 1, /* Parallel IO Controller A */ 651638Srgrimes 1, /* Parallel IO Controller B */ 6624761Sjdp 1, /* Parallel IO Controller C */ 6738186Speter 0, /* Analog-to-Digital Converter */ 6838186Speter 5, /* USART 0 */ 691638Srgrimes 5, /* USART 1 */ 7042450Sjdp 5, /* USART 2 */ 711844Swollman 0, /* Multimedia Card Interface */ 7238186Speter 2, /* USB Device Port */ 7338186Speter 6, /* Two-Wire Interface */ 741844Swollman 5, /* Serial Peripheral Interface 0 */ 7536673Sdt 5, /* Serial Peripheral Interface 1 */ 761844Swollman 5, /* Serial Synchronous Controller */ 7738186Speter 0, /* (reserved) */ 7838186Speter 0, /* (reserved) */ 791844Swollman 0, /* Timer Counter 0 */ 8036673Sdt 0, /* Timer Counter 1 */ 8124761Sjdp 0, /* Timer Counter 2 */ 8238186Speter 2, /* USB Host port */ 8338186Speter 3, /* Ethernet */ 841844Swollman 0, /* Image Sensor Interface */ 8542450Sjdp 5, /* USART 3 */ 861844Swollman 5, /* USART 4 */ 8738186Speter 5, /* USART 5 */ 8838186Speter 0, /* Timer Counter 3 */ 891844Swollman 0, /* Timer Counter 4 */ 901844Swollman 0, /* Timer Counter 5 */ 911844Swollman 0, /* Advanced Interrupt Controller IRQ0 */ 9238186Speter 0, /* Advanced Interrupt Controller IRQ1 */ 9338186Speter 0, /* Advanced Interrupt Controller IRQ2 */ 941844Swollman}; 951844Swollman 9624761Sjdp#define DEVICE(_name, _id, _unit) \ 9738186Speter { \ 9838186Speter _name, _unit, \ 991844Swollman AT91SAM9260_ ## _id ##_BASE, \ 10042450Sjdp AT91SAM9260_ ## _id ## _SIZE, \ 1011844Swollman AT91SAM9260_IRQ_ ## _id \ 10238186Speter } 10338186Speter 1041844Swollmanstatic const struct cpu_devs at91_devs[] = 10536054Sbde{ 10636054Sbde DEVICE("at91_pmc", PMC, 0), 10738186Speter DEVICE("at91_wdt", WDT, 0), 10838186Speter DEVICE("at91_rst", RSTC, 0), 10936054Sbde DEVICE("at91_pit", PIT, 0), 11036054Sbde DEVICE("at91_pio", PIOA, 0), 11136054Sbde DEVICE("at91_pio", PIOB, 1), 11238186Speter DEVICE("at91_pio", PIOC, 2), 11338186Speter DEVICE("at91_twi", TWI, 0), 11436054Sbde DEVICE("at91_mci", MCI, 0), 11542450Sjdp DEVICE("uart", DBGU, 0), 11636054Sbde DEVICE("uart", USART0, 1), 11738186Speter DEVICE("uart", USART1, 2), 11838186Speter DEVICE("uart", USART2, 3), 11936054Sbde DEVICE("uart", USART3, 4), 12095251Sru DEVICE("uart", USART4, 5), 12126715Sasami DEVICE("uart", USART5, 6), 12217510Speter DEVICE("spi", SPI0, 0), 12338186Speter DEVICE("spi", SPI1, 1), 12438186Speter DEVICE("ate", EMAC, 0), 1251638Srgrimes DEVICE("macb", EMAC, 0), 12695251Sru DEVICE("nand", NAND, 0), 12726715Sasami DEVICE("ohci", OHCI, 0), 12817510Speter { 0, 0, 0, 0, 0 } 12938186Speter}; 13038186Speter 1311638Srgrimesstatic void 13295251Sruat91_add_child(device_t dev, int prio, const char *name, int unit, 13395216Smarkm bus_addr_t addr, bus_size_t size, int irq0, int irq1, int irq2) 13495216Smarkm{ 13538186Speter device_t kid; 13638186Speter struct at91_ivar *ivar; 1371638Srgrimes 1381844Swollman kid = device_add_child_ordered(dev, prio, name, unit); 13926715Sasami if (kid == NULL) { 14038186Speter printf("Can't add child %s%d ordered\n", name, unit); 14138186Speter return; 1421844Swollman } 1431844Swollman ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 14426715Sasami if (ivar == NULL) { 14538186Speter device_delete_child(dev, kid); 14638186Speter printf("Can't add alloc ivar\n"); 1471844Swollman return; 14842450Sjdp } 14995216Smarkm device_set_ivars(kid, ivar); 15095216Smarkm resource_list_init(&ivar->resources); 15138186Speter if (irq0 != -1) { 15238186Speter bus_set_resource(kid, SYS_RES_IRQ, 0, irq0, 1); 1531844Swollman if (irq0 != AT91SAM9260_IRQ_SYSTEM) 1542870Swollman at91_pmc_clock_add(device_get_nameunit(kid), irq0, 0); 1552868Swollman } 1561638Srgrimes if (irq1 != 0) 1571638Srgrimes bus_set_resource(kid, SYS_RES_IRQ, 1, irq1, 1); 1581638Srgrimes if (irq2 != 0) 1591638Srgrimes bus_set_resource(kid, SYS_RES_IRQ, 2, irq2, 1); 1602870Swollman if (addr != 0 && addr < AT91SAM9260_BASE) 1611638Srgrimes addr += AT91SAM9260_BASE; 16242915Sjdp if (addr != 0) 16342915Sjdp bus_set_resource(kid, SYS_RES_MEMORY, 0, addr, size); 1641638Srgrimes} 1651844Swollman 1661844Swollmanstatic void 1671844Swollmanat91_cpu_add_builtin_children(device_t dev) 1681638Srgrimes{ 1691844Swollman int i; 17092128Sobrien const struct cpu_devs *walker; 17192128Sobrien 17292128Sobrien for (i = 1, walker = at91_devs; walker->name; i++, walker++) { 1731844Swollman at91_add_child(dev, i, walker->name, walker->unit, 1741844Swollman walker->mem_base, walker->mem_len, walker->irq0, 17592128Sobrien walker->irq1, walker->irq2); 1761638Srgrimes } 17795114Sobrien} 17895114Sobrien 17995114Sobrienstatic uint32_t 18095114Sobrienat91_pll_outa(int freq) 18195114Sobrien{ 18295114Sobrien 18395114Sobrien if (freq > 195000000) 18495306Sru return (0x20000000); 18595306Sru else 18674805Sru return (0x20008000); 18795306Sru} 18874805Sru 1891844Swollmanstatic uint32_t 1901844Swollmanat91_pll_outb(int freq) 1911844Swollman{ 19242915Sjdp 19366534Speter return (0x4000); 1941638Srgrimes} 19542915Sjdp 1961844Swollmanstatic void 1971638Srgrimesat91_identify(driver_t *drv, device_t parent) 19842915Sjdp{ 1993859Sbde 2001638Srgrimes switch (AT91_CPU(at91_chip_id)) { 2012353Sbde case AT91_CPU_SAM9260: 2021638Srgrimes case AT91_CPU_SAM9XE128: 20317400Sjkh case AT91_CPU_SAM9XE256: 2041844Swollman case AT91_CPU_SAM9XE512: 2053859Sbde at91_add_child(parent, 0, "at91sam9260", 0, 0, 0, -1, 0, 0); 2061638Srgrimes at91_cpu_add_builtin_children(parent); 20742450Sjdp break; 20828945Speter } 20942915Sjdp} 21042915Sjdp 21142915Sjdpstatic int 21242915Sjdpat91_probe(device_t dev) 21342915Sjdp{ 21442915Sjdp const char *desc; 21542915Sjdp 21638655Sjb switch (AT91_CPU(at91_chip_id)) { 21791011Sru case AT91_CPU_SAM9260: 21842915Sjdp desc = "AT91SAM9260"; 21991011Sru break; 22028945Speter case AT91_CPU_SAM9XE128: 22191011Sru desc = "AT91SAM9XE128"; 22242915Sjdp break; 22391011Sru case AT91_CPU_SAM9XE256: 22428945Speter desc = "AT91SAM9XE256"; 22542915Sjdp break; 2261844Swollman case AT91_CPU_SAM9XE512: 22742915Sjdp desc = "AT91SAM9XE512"; 2281844Swollman break; 2292353Sbde default: 2301844Swollman return (ENXIO); 2315253Sache } 2321844Swollman device_set_desc(dev, desc); 2333859Sbde return (0); 2341844Swollman} 23592553Sru 23692491Smarkmstatic int 23792553Sruat91_attach(device_t dev) 23892491Smarkm{ 23992491Smarkm struct at91_pmc_clock *clk; 24092491Smarkm struct at91sam9_softc *sc = device_get_softc(dev); 2411638Srgrimes int i; 2421638Srgrimes 24395306Sru struct at91_softc *at91sc = device_get_softc(device_get_parent(dev)); 24442915Sjdp 24592553Sru sc->sc_st = at91sc->sc_st; 24638187Speter sc->sc_sh = at91sc->sc_sh; 24742450Sjdp sc->dev = dev; 24842915Sjdp 24942450Sjdp if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_SYS_BASE, 25092491Smarkm AT91SAM9260_SYS_SIZE, &sc->sc_sys_sh) != 0) 25116826Sphk panic("Enable to map system registers"); 25216437Sphk 2531638Srgrimes if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_DBGU_BASE, 25416437Sphk AT91SAM9260_DBGU_SIZE, &sc->sc_dbg_sh) != 0) 2551638Srgrimes panic("Enable to map DBGU registers"); 25634179Sbde 25724750Sbde if (bus_space_subregion(sc->sc_st, sc->sc_sh, AT91SAM9260_AIC_BASE, 25842450Sjdp AT91SAM9260_AIC_SIZE, &sc->sc_aic_sh) != 0) 25924750Sbde panic("Enable to map system registers"); 26024750Sbde 26142915Sjdp /* XXX Hack to tell atmelarm about the AIC */ 26238655Sjb at91sc->sc_aic_sh = sc->sc_aic_sh; 26342915Sjdp at91sc->sc_irq_system = AT91SAM9260_IRQ_SYSTEM; 26491011Sru 26525468Sjdp for (i = 0; i < 32; i++) { 26628945Speter bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR + 26731809Sbde i * 4, i); 26842915Sjdp /* Priority. */ 26927910Sasami bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4, 27028945Speter at91_irq_prio[i]); 27128945Speter if (i < 8) 2721638Srgrimes bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR, 2731638Srgrimes 1); 2741638Srgrimes } 27555954Srgrimes 2761638Srgrimes bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32); 2771638Srgrimes /* No debug. */ 27855954Srgrimes bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0); 27955954Srgrimes /* Disable and clear all interrupts. */ 28055954Srgrimes bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff); 28155954Srgrimes bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff); 28255954Srgrimes 28395216Smarkm /* Disable all interrupts for DBGU */ 28455954Srgrimes bus_space_write_4(sc->sc_st, sc->sc_dbg_sh, 0x0c, 0xffffffff); 28555954Srgrimes 28655954Srgrimes if (bus_space_subregion(sc->sc_st, sc->sc_sh, 28748204Sjmg AT91SAM9260_MATRIX_BASE, AT91SAM9260_MATRIX_SIZE, 2882298Swollman &sc->sc_matrix_sh) != 0) 2892298Swollman panic("Enable to map matrix registers"); 2902298Swollman 29149328Shoek /* activate NAND*/ 29249328Shoek i = bus_space_read_4(sc->sc_st, sc->sc_matrix_sh, 29349328Shoek AT91SAM9260_EBICSA); 29449328Shoek bus_space_write_4(sc->sc_st, sc->sc_matrix_sh, 29556971Sru AT91SAM9260_EBICSA, 29649328Shoek i | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); 29749328Shoek 29849328Shoek /* Update USB device port clock info */ 29949328Shoek clk = at91_pmc_clock_ref("udpck"); 3001638Srgrimes clk->pmc_mask = PMC_SCER_UDP_SAM9; 30195306Sru at91_pmc_clock_deref(clk); 30295306Sru 3032298Swollman /* Update USB host port clock info */ 30492980Sdes clk = at91_pmc_clock_ref("uhpck"); 30549328Shoek clk->pmc_mask = PMC_SCER_UHP_SAM9; 3061638Srgrimes at91_pmc_clock_deref(clk); 30792980Sdes 30849328Shoek /* Each SOC has different PLL contraints */ 3091638Srgrimes clk = at91_pmc_clock_ref("plla"); 3102298Swollman clk->pll_min_in = SAM9260_PLL_A_MIN_IN_FREQ; /* 1 MHz */ 31142915Sjdp clk->pll_max_in = SAM9260_PLL_A_MAX_IN_FREQ; /* 32 MHz */ 31248204Sjmg clk->pll_min_out = SAM9260_PLL_A_MIN_OUT_FREQ; /* 80 MHz */ 31349328Shoek clk->pll_max_out = SAM9260_PLL_A_MAX_OUT_FREQ; /* 240 MHz */ 31442915Sjdp clk->pll_mul_shift = SAM9260_PLL_A_MUL_SHIFT; 31542915Sjdp clk->pll_mul_mask = SAM9260_PLL_A_MUL_MASK; 31644946Sbde clk->pll_div_shift = SAM9260_PLL_A_DIV_SHIFT; 3171844Swollman clk->pll_div_mask = SAM9260_PLL_A_DIV_MASK; 31828945Speter clk->set_outb = at91_pll_outa; 3191844Swollman at91_pmc_clock_deref(clk); 3201844Swollman 32149328Shoek /* 3221844Swollman * Fudge MAX pll in frequence down below 3.0 MHz to ensure 3231638Srgrimes * PMC alogrithm choose the divisor that causes the input clock 3241638Srgrimes * to be near the optimal 2 MHz per datasheet. We know 3251638Srgrimes * we are going to be using this for the USB clock at 96 MHz. 3261638Srgrimes * Causes no extra frequency deviation for all recomended crystal 3271638Srgrimes * values. 3281638Srgrimes */ 3291638Srgrimes clk = at91_pmc_clock_ref("pllb"); 3302353Sbde clk->pll_min_in = SAM9260_PLL_B_MIN_IN_FREQ; /* 1 MHz */ 33144946Sbde clk->pll_max_in = SAM9260_PLL_B_MAX_IN_FREQ; /* 5 MHz */ 3321638Srgrimes clk->pll_max_in = 2999999; /* ~3 MHz */ 3331638Srgrimes clk->pll_min_out = SAM9260_PLL_B_MIN_OUT_FREQ; /* 70 MHz */ 33444946Sbde clk->pll_max_out = SAM9260_PLL_B_MAX_OUT_FREQ; /* 130 MHz */ 33544946Sbde clk->pll_mul_shift = SAM9260_PLL_B_MUL_SHIFT; 33644946Sbde clk->pll_mul_mask = SAM9260_PLL_B_MUL_MASK; 33744946Sbde clk->pll_div_shift = SAM9260_PLL_B_DIV_SHIFT; 33844946Sbde clk->pll_div_mask = SAM9260_PLL_B_DIV_MASK; 33944946Sbde clk->set_outb = at91_pll_outb; 34044946Sbde at91_pmc_clock_deref(clk); 34144946Sbde return (0); 34244946Sbde} 34344946Sbde 34444946Sbdestatic device_method_t at91sam9260_methods[] = { 34592553Sru DEVMETHOD(device_probe, at91_probe), 34692491Smarkm DEVMETHOD(device_attach, at91_attach), 34792491Smarkm DEVMETHOD(device_identify, at91_identify), 34892491Smarkm DEVMETHOD_END 3491638Srgrimes}; 35096162Sru 35196162Srustatic driver_t at91sam9260_driver = { 35296162Sru "at91sam9260", 35396162Sru at91sam9260_methods, 35495306Sru sizeof(struct at91sam9_softc), 35595306Sru}; 3561638Srgrimes 3571638Srgrimesstatic devclass_t at91sam9260_devclass; 3581638Srgrimes 35995306SruDRIVER_MODULE(at91sam9260, atmelarm, at91sam9260_driver, at91sam9260_devclass, 36092553Sru NULL, NULL); 3611638Srgrimes