uboot/board/bluewater/gurnard/gurnard.c
<<
>>
Prefs
   1/*
   2 * Bluewater Systems Snapper 9260/9G20 modules
   3 *
   4 * (C) Copyright 2011 Bluewater Systems
   5 *   Author: Andre Renaud <andre@bluewatersys.com>
   6 *   Author: Ryan Mallon <ryan@bluewatersys.com>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <atmel_lcd.h>
  13#include <atmel_lcdc.h>
  14#include <atmel_mci.h>
  15#include <dm.h>
  16#include <lcd.h>
  17#include <net.h>
  18#ifndef CONFIG_DM_ETH
  19#include <netdev.h>
  20#endif
  21#include <spi.h>
  22#include <asm/gpio.h>
  23#include <asm/io.h>
  24#include <asm/arch/at91sam9g45_matrix.h>
  25#include <asm/arch/at91sam9_smc.h>
  26#include <asm/arch/at91_common.h>
  27#include <asm/arch/at91_emac.h>
  28#include <asm/arch/at91_rstc.h>
  29#include <asm/arch/at91_rtc.h>
  30#include <asm/arch/at91_sck.h>
  31#include <asm/arch/atmel_serial.h>
  32#include <asm/arch/clk.h>
  33#include <asm/arch/gpio.h>
  34#include <dm/uclass-internal.h>
  35
  36#ifdef CONFIG_GURNARD_SPLASH
  37#include "splash_logo.h"
  38#endif
  39
  40DECLARE_GLOBAL_DATA_PTR;
  41
  42/* IO Expander pins */
  43#define IO_EXP_ETH_RESET        (0 << 1)
  44#define IO_EXP_ETH_POWER        (1 << 1)
  45
  46#ifdef CONFIG_MACB
  47static void gurnard_macb_hw_init(void)
  48{
  49        struct at91_port *pioa = (struct at91_port *)ATMEL_BASE_PIOA;
  50
  51        at91_periph_clk_enable(ATMEL_ID_EMAC);
  52
  53        /*
  54         * Enable pull-up on:
  55         *      RXDV (PA12) => MODE0 - PHY also has pull-up
  56         *      ERX0 (PA13) => MODE1 - PHY also has pull-up
  57         *      ERX1 (PA15) => MODE2 - PHY also has pull-up
  58         */
  59        writel(pin_to_mask(AT91_PIN_PA15) |
  60               pin_to_mask(AT91_PIN_PA12) |
  61               pin_to_mask(AT91_PIN_PA13),
  62               &pioa->puer);
  63
  64        at91_phy_reset();
  65
  66        at91_macb_hw_init();
  67}
  68#endif
  69
  70#ifdef CONFIG_CMD_NAND
  71static int gurnard_nand_hw_init(void)
  72{
  73        struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
  74        struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
  75        ulong flags;
  76        int ret;
  77
  78        /* Enable CS3 as NAND/SmartMedia */
  79        setbits_le32(&matrix->ebicsa, AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
  80
  81        /* Configure SMC CS3 for NAND/SmartMedia */
  82        writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(0) |
  83               AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(0),
  84               &smc->cs[3].setup);
  85        writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(4) |
  86               AT91_SMC_PULSE_NRD(4) | AT91_SMC_PULSE_NCS_RD(4),
  87               &smc->cs[3].pulse);
  88        writel(AT91_SMC_CYCLE_NWE(7) | AT91_SMC_CYCLE_NRD(7),
  89               &smc->cs[3].cycle);
  90#ifdef CONFIG_SYS_NAND_DBW_16
  91        flags = AT91_SMC_MODE_DBW_16;
  92#else
  93        flags = AT91_SMC_MODE_DBW_8;
  94#endif
  95        writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
  96               AT91_SMC_MODE_EXNW_DISABLE |
  97               flags |
  98               AT91_SMC_MODE_TDF_CYCLE(3),
  99               &smc->cs[3].mode);
 100
 101        ret = gpio_request(CONFIG_SYS_NAND_READY_PIN, "nand_rdy");
 102        if (ret)
 103                return ret;
 104        gpio_direction_input(CONFIG_SYS_NAND_READY_PIN);
 105
 106        /* Enable NandFlash */
 107        ret = gpio_request(CONFIG_SYS_NAND_ENABLE_PIN, "nand_ce");
 108        if (ret)
 109                return ret;
 110        gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
 111
 112        return 0;
 113}
 114#endif
 115
 116#ifdef CONFIG_GURNARD_SPLASH
 117static void lcd_splash(int width, int height)
 118{
 119        u16 colour;
 120        int x, y;
 121        u16 *base_addr = (u16 *)gd->video_bottom;
 122
 123        memset(base_addr, 0xff, width * height * 2);
 124        /*
 125         * Blit the logo to the center of the screen
 126         */
 127        for (y = 0; y < BMP_LOGO_HEIGHT; y++) {
 128                for (x = 0; x < BMP_LOGO_WIDTH; x++) {
 129                        int posx, posy;
 130                        colour = bmp_logo_palette[bmp_logo_bitmap[
 131                            y * BMP_LOGO_WIDTH + x]];
 132                        posx = x + (width - BMP_LOGO_WIDTH) / 2;
 133                        posy = y;
 134                        base_addr[posy * width + posx] = colour;
 135                }
 136        }
 137}
 138#endif
 139
 140#ifdef CONFIG_DM_VIDEO
 141static void at91sam9g45_lcd_hw_init(void)
 142{
 143        at91_set_A_periph(AT91_PIN_PE0, 0);     /* LCDDPWR */
 144        at91_set_A_periph(AT91_PIN_PE2, 0);     /* LCDCC */
 145        at91_set_A_periph(AT91_PIN_PE3, 0);     /* LCDVSYNC */
 146        at91_set_A_periph(AT91_PIN_PE4, 0);     /* LCDHSYNC */
 147        at91_set_A_periph(AT91_PIN_PE5, 0);     /* LCDDOTCK */
 148
 149        at91_set_A_periph(AT91_PIN_PE7, 0);     /* LCDD0 */
 150        at91_set_A_periph(AT91_PIN_PE8, 0);     /* LCDD1 */
 151        at91_set_A_periph(AT91_PIN_PE9, 0);     /* LCDD2 */
 152        at91_set_A_periph(AT91_PIN_PE10, 0);    /* LCDD3 */
 153        at91_set_A_periph(AT91_PIN_PE11, 0);    /* LCDD4 */
 154        at91_set_A_periph(AT91_PIN_PE12, 0);    /* LCDD5 */
 155        at91_set_A_periph(AT91_PIN_PE13, 0);    /* LCDD6 */
 156        at91_set_A_periph(AT91_PIN_PE14, 0);    /* LCDD7 */
 157        at91_set_A_periph(AT91_PIN_PE15, 0);    /* LCDD8 */
 158        at91_set_A_periph(AT91_PIN_PE16, 0);    /* LCDD9 */
 159        at91_set_A_periph(AT91_PIN_PE17, 0);    /* LCDD10 */
 160        at91_set_A_periph(AT91_PIN_PE18, 0);    /* LCDD11 */
 161        at91_set_A_periph(AT91_PIN_PE19, 0);    /* LCDD12 */
 162        at91_set_B_periph(AT91_PIN_PE20, 0);    /* LCDD13 */
 163        at91_set_A_periph(AT91_PIN_PE21, 0);    /* LCDD14 */
 164        at91_set_A_periph(AT91_PIN_PE22, 0);    /* LCDD15 */
 165        at91_set_A_periph(AT91_PIN_PE23, 0);    /* LCDD16 */
 166        at91_set_A_periph(AT91_PIN_PE24, 0);    /* LCDD17 */
 167        at91_set_A_periph(AT91_PIN_PE25, 0);    /* LCDD18 */
 168        at91_set_A_periph(AT91_PIN_PE26, 0);    /* LCDD19 */
 169        at91_set_A_periph(AT91_PIN_PE27, 0);    /* LCDD20 */
 170        at91_set_B_periph(AT91_PIN_PE28, 0);    /* LCDD21 */
 171        at91_set_A_periph(AT91_PIN_PE29, 0);    /* LCDD22 */
 172        at91_set_A_periph(AT91_PIN_PE30, 0);    /* LCDD23 */
 173
 174        at91_periph_clk_enable(ATMEL_ID_LCDC);
 175}
 176#endif
 177
 178#ifdef CONFIG_GURNARD_FPGA
 179/**
 180 * Initialise the memory bus settings so that we can talk to the
 181 * memory mapped FPGA
 182 */
 183static int fpga_hw_init(void)
 184{
 185        struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
 186        struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
 187        int i;
 188
 189        setbits_le32(&matrix->ebicsa, AT91_MATRIX_EBI_CS1A_SDRAMC);
 190
 191        at91_set_a_periph(2, 4, 0); /* EBIA21 */
 192        at91_set_a_periph(2, 5, 0); /* EBIA22 */
 193        at91_set_a_periph(2, 6, 0); /* EBIA23 */
 194        at91_set_a_periph(2, 7, 0); /* EBIA24 */
 195        at91_set_a_periph(2, 12, 0); /* EBIA25 */
 196        for (i = 15; i <= 31; i++) /* EBINWAIT & EBID16 - 31 */
 197                at91_set_a_periph(2, i, 0);
 198
 199        /* configure SMC cs0 for FPGA access timing */
 200        writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(2) |
 201               AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(2),
 202               &smc->cs[0].setup);
 203        writel(AT91_SMC_PULSE_NWE(5) | AT91_SMC_PULSE_NCS_WR(4) |
 204               AT91_SMC_PULSE_NRD(6) | AT91_SMC_PULSE_NCS_RD(4),
 205               &smc->cs[0].pulse);
 206        writel(AT91_SMC_CYCLE_NWE(6) | AT91_SMC_CYCLE_NRD(6),
 207               &smc->cs[0].cycle);
 208        writel(AT91_SMC_MODE_BAT |
 209               AT91_SMC_MODE_EXNW_DISABLE |
 210               AT91_SMC_MODE_DBW_32 |
 211               AT91_SMC_MODE_TDF |
 212               AT91_SMC_MODE_TDF_CYCLE(2),
 213               &smc->cs[0].mode);
 214
 215        /* Do a write to within EBI_CS1 to enable the SDCK */
 216        writel(0, ATMEL_BASE_CS1);
 217
 218        return 0;
 219}
 220#endif
 221
 222#ifdef CONFIG_CMD_USB
 223
 224#define USB0_ENABLE_PIN         AT91_PIN_PB22
 225#define USB1_ENABLE_PIN         AT91_PIN_PB23
 226
 227void gurnard_usb_init(void)
 228{
 229        at91_set_gpio_output(USB0_ENABLE_PIN, 1);
 230        at91_set_gpio_value(USB0_ENABLE_PIN, 0);
 231        at91_set_gpio_output(USB1_ENABLE_PIN, 1);
 232        at91_set_gpio_value(USB1_ENABLE_PIN, 0);
 233}
 234#endif
 235
 236#ifdef CONFIG_GENERIC_ATMEL_MCI
 237int cpu_mmc_init(bd_t *bis)
 238{
 239        return atmel_mci_init((void *)ATMEL_BASE_MCI0);
 240}
 241#endif
 242
 243static void gurnard_enable_console(int enable)
 244{
 245        at91_set_gpio_output(AT91_PIN_PB14, 1);
 246        at91_set_gpio_value(AT91_PIN_PB14, enable ? 0 : 1);
 247}
 248
 249void at91sam9g45_slowclock_init(void)
 250{
 251        /*
 252         * On AT91SAM9G45 revC CPUs, the slow clock can be based on an
 253         * internal impreciseRC oscillator or an external 32kHz oscillator.
 254         * Switch to the latter.
 255         */
 256        unsigned i, tmp;
 257        ulong *reg = (ulong *)ATMEL_BASE_SCKCR;
 258
 259        tmp = readl(reg);
 260        if ((tmp & AT91SAM9G45_SCKCR_OSCSEL) == AT91SAM9G45_SCKCR_OSCSEL_RC) {
 261                timer_init();
 262                tmp |= AT91SAM9G45_SCKCR_OSC32EN;
 263                writel(tmp, reg);
 264                for (i = 0; i < 1200; i++)
 265                        udelay(1000);
 266                tmp |= AT91SAM9G45_SCKCR_OSCSEL_32;
 267                writel(tmp, reg);
 268                udelay(200);
 269                tmp &= ~AT91SAM9G45_SCKCR_RCEN;
 270                writel(tmp, reg);
 271        }
 272}
 273
 274int board_early_init_f(void)
 275{
 276        at91_seriald_hw_init();
 277        gurnard_enable_console(1);
 278
 279        return 0;
 280}
 281
 282int board_init(void)
 283{
 284        const char *rev_str;
 285#ifdef CONFIG_CMD_NAND
 286        int ret;
 287#endif
 288
 289        at91_periph_clk_enable(ATMEL_ID_PIOA);
 290        at91_periph_clk_enable(ATMEL_ID_PIOB);
 291        at91_periph_clk_enable(ATMEL_ID_PIOC);
 292        at91_periph_clk_enable(ATMEL_ID_PIODE);
 293
 294        at91sam9g45_slowclock_init();
 295
 296        /*
 297         * Clear the RTC IDR to disable all IRQs. Avoid issues when Linux
 298         * boots with spurious IRQs.
 299         */
 300        writel(0xffffffff, AT91_RTC_IDR);
 301
 302        /* Make sure that the reset signal is attached properly */
 303        setbits_le32(AT91_ASM_RSTC_MR, AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN);
 304
 305        gd->bd->bi_arch_number = MACH_TYPE_SNAPPER_9260;
 306
 307        /* Address of boot parameters */
 308        gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 309
 310#ifdef CONFIG_CMD_NAND
 311        ret = gurnard_nand_hw_init();
 312        if (ret)
 313                return ret;
 314#endif
 315#ifdef CONFIG_ATMEL_SPI
 316        at91_spi0_hw_init(1 << 4);
 317#endif
 318
 319#ifdef CONFIG_MACB
 320        gurnard_macb_hw_init();
 321#endif
 322
 323#ifdef CONFIG_GURNARD_FPGA
 324        fpga_hw_init();
 325#endif
 326
 327#ifdef CONFIG_CMD_USB
 328        gurnard_usb_init();
 329#endif
 330
 331#ifdef CONFIG_CMD_MMC
 332        at91_set_A_periph(AT91_PIN_PA12, 0);
 333        at91_set_gpio_output(AT91_PIN_PA8, 1);
 334        at91_set_gpio_value(AT91_PIN_PA8, 0);
 335        at91_mci_hw_init();
 336#endif
 337
 338#ifdef CONFIG_DM_VIDEO
 339        at91sam9g45_lcd_hw_init();
 340        at91_set_A_periph(AT91_PIN_PE6, 1);     /* power up */
 341
 342        /* Select the second timing index for board rev 2 */
 343        rev_str = getenv("board_rev");
 344        if (rev_str && !strncmp(rev_str, "2", 1)) {
 345                struct udevice *dev;
 346
 347                uclass_find_first_device(UCLASS_VIDEO, &dev);
 348                if (dev) {
 349                        struct atmel_lcd_platdata *plat = dev_get_platdata(dev);
 350
 351                        plat->timing_index = 1;
 352                }
 353        }
 354#endif
 355
 356        return 0;
 357}
 358
 359int board_late_init(void)
 360{
 361        u_int8_t env_enetaddr[8];
 362        char *env_str;
 363        char *end;
 364        int i;
 365
 366        /*
 367         * Set MAC address so we do not need to init Ethernet before Linux
 368         * boot
 369         */
 370        env_str = getenv("ethaddr");
 371        if (env_str) {
 372                struct at91_emac *emac = (struct at91_emac *)ATMEL_BASE_EMAC;
 373                /* Parse MAC address */
 374                for (i = 0; i < 6; i++) {
 375                        env_enetaddr[i] = env_str ?
 376                                simple_strtoul(env_str, &end, 16) : 0;
 377                        if (env_str)
 378                                env_str = (*end) ? end+1 : end;
 379                }
 380
 381                /* Set hardware address */
 382                writel(env_enetaddr[0] | env_enetaddr[1] << 8 |
 383                       env_enetaddr[2] << 16 | env_enetaddr[3] << 24,
 384                       &emac->sa2l);
 385                writel((env_enetaddr[4] | env_enetaddr[5] << 8), &emac->sa2h);
 386
 387                printf("MAC:   %s\n", getenv("ethaddr"));
 388        } else {
 389                /* Not set in environment */
 390                printf("MAC:   not set\n");
 391        }
 392#ifdef CONFIG_GURNARD_SPLASH
 393        lcd_splash(480, 272);
 394#endif
 395
 396        return 0;
 397}
 398
 399#ifndef CONFIG_DM_ETH
 400int board_eth_init(bd_t *bis)
 401{
 402        return macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0);
 403}
 404#endif
 405
 406int dram_init(void)
 407{
 408        gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
 409                                    CONFIG_SYS_SDRAM_SIZE);
 410        return 0;
 411}
 412
 413void reset_phy(void)
 414{
 415}
 416
 417/* SPI chip select control - only used for FPGA programming */
 418#ifdef CONFIG_ATMEL_SPI
 419
 420int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 421{
 422        return bus == 0 && cs == 0;
 423}
 424
 425void spi_cs_activate(struct spi_slave *slave)
 426{
 427        /* We don't use chipselects for FPGA programming */
 428}
 429
 430void spi_cs_deactivate(struct spi_slave *slave)
 431{
 432        /* We don't use chipselects for FPGA programming */
 433}
 434#endif /* CONFIG_ATMEL_SPI */
 435
 436static struct atmel_serial_platdata at91sam9260_serial_plat = {
 437        .base_addr = ATMEL_BASE_DBGU,
 438};
 439
 440U_BOOT_DEVICE(at91sam9260_serial) = {
 441        .name   = "serial_atmel",
 442        .platdata = &at91sam9260_serial_plat,
 443};
 444