u-boot/board/bluewater/gurnard/gurnard.c
Simon Glass 20e442ab2d dm: Rename U_BOOT_DEVICE() to U_BOOT_DRVINFO()
The current macro is a misnomer since it does not declare a device
directly. Instead, it declares driver_info record which U-Boot uses at
runtime to create a device.

The distinction seems somewhat minor most of the time, but is becomes
quite confusing when we actually want to declare a device, with
of-platdata. We are left trying to distinguish between a device which
isn't actually device, and a device that is (perhaps an 'instance'?)

It seems better to rename this macro to describe what it actually is. The
macros is not widely used, since boards should use devicetree to declare
devices.

Rename it to U_BOOT_DRVINFO(), which indicates clearly that this is
declaring a new driver_info record, not a device.

Signed-off-by: Simon Glass <sjg@chromium.org>
2021-01-05 12:26:35 -07:00

426 lines
10 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Bluewater Systems Snapper 9260/9G20 modules
*
* (C) Copyright 2011 Bluewater Systems
* Author: Andre Renaud <andre@bluewatersys.com>
* Author: Ryan Mallon <ryan@bluewatersys.com>
*/
#include <common.h>
#include <atmel_lcd.h>
#include <atmel_lcdc.h>
#include <atmel_mci.h>
#include <dm.h>
#include <env.h>
#include <init.h>
#include <lcd.h>
#include <net.h>
#ifndef CONFIG_DM_ETH
#include <netdev.h>
#endif
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/arch/at91sam9g45_matrix.h>
#include <asm/arch/at91sam9_smc.h>
#include <asm/arch/at91_common.h>
#include <asm/arch/at91_emac.h>
#include <asm/arch/at91_rstc.h>
#include <asm/arch/at91_rtc.h>
#include <asm/arch/at91_sck.h>
#include <asm/arch/atmel_serial.h>
#include <asm/arch/clk.h>
#include <asm/arch/gpio.h>
#include <dm/uclass-internal.h>
#include <linux/delay.h>
#ifdef CONFIG_GURNARD_SPLASH
#include "splash_logo.h"
#endif
DECLARE_GLOBAL_DATA_PTR;
/* IO Expander pins */
#define IO_EXP_ETH_RESET (0 << 1)
#define IO_EXP_ETH_POWER (1 << 1)
#ifdef CONFIG_MACB
static void gurnard_macb_hw_init(void)
{
struct at91_port *pioa = (struct at91_port *)ATMEL_BASE_PIOA;
at91_periph_clk_enable(ATMEL_ID_EMAC);
/*
* Enable pull-up on:
* RXDV (PA12) => MODE0 - PHY also has pull-up
* ERX0 (PA13) => MODE1 - PHY also has pull-up
* ERX1 (PA15) => MODE2 - PHY also has pull-up
*/
writel(pin_to_mask(AT91_PIN_PA15) |
pin_to_mask(AT91_PIN_PA12) |
pin_to_mask(AT91_PIN_PA13),
&pioa->puer);
at91_phy_reset();
at91_macb_hw_init();
}
#endif
#ifdef CONFIG_CMD_NAND
static int gurnard_nand_hw_init(void)
{
struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
ulong flags;
int ret;
/* Enable CS3 as NAND/SmartMedia */
setbits_le32(&matrix->ebicsa, AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA);
/* Configure SMC CS3 for NAND/SmartMedia */
writel(AT91_SMC_SETUP_NWE(2) | AT91_SMC_SETUP_NCS_WR(0) |
AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(0),
&smc->cs[3].setup);
writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(4) |
AT91_SMC_PULSE_NRD(4) | AT91_SMC_PULSE_NCS_RD(4),
&smc->cs[3].pulse);
writel(AT91_SMC_CYCLE_NWE(7) | AT91_SMC_CYCLE_NRD(7),
&smc->cs[3].cycle);
#ifdef CONFIG_SYS_NAND_DBW_16
flags = AT91_SMC_MODE_DBW_16;
#else
flags = AT91_SMC_MODE_DBW_8;
#endif
writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE |
AT91_SMC_MODE_EXNW_DISABLE |
flags |
AT91_SMC_MODE_TDF_CYCLE(3),
&smc->cs[3].mode);
ret = gpio_request(CONFIG_SYS_NAND_READY_PIN, "nand_rdy");
if (ret)
return ret;
gpio_direction_input(CONFIG_SYS_NAND_READY_PIN);
/* Enable NandFlash */
ret = gpio_request(CONFIG_SYS_NAND_ENABLE_PIN, "nand_ce");
if (ret)
return ret;
gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1);
return 0;
}
#endif
#ifdef CONFIG_GURNARD_SPLASH
static void lcd_splash(int width, int height)
{
u16 colour;
int x, y;
u16 *base_addr = (u16 *)gd->video_bottom;
memset(base_addr, 0xff, width * height * 2);
/*
* Blit the logo to the center of the screen
*/
for (y = 0; y < BMP_LOGO_HEIGHT; y++) {
for (x = 0; x < BMP_LOGO_WIDTH; x++) {
int posx, posy;
colour = bmp_logo_palette[bmp_logo_bitmap[
y * BMP_LOGO_WIDTH + x]];
posx = x + (width - BMP_LOGO_WIDTH) / 2;
posy = y;
base_addr[posy * width + posx] = colour;
}
}
}
#endif
#ifdef CONFIG_DM_VIDEO
static void at91sam9g45_lcd_hw_init(void)
{
at91_set_A_periph(AT91_PIN_PE0, 0); /* LCDDPWR */
at91_set_A_periph(AT91_PIN_PE2, 0); /* LCDCC */
at91_set_A_periph(AT91_PIN_PE3, 0); /* LCDVSYNC */
at91_set_A_periph(AT91_PIN_PE4, 0); /* LCDHSYNC */
at91_set_A_periph(AT91_PIN_PE5, 0); /* LCDDOTCK */
at91_set_A_periph(AT91_PIN_PE7, 0); /* LCDD0 */
at91_set_A_periph(AT91_PIN_PE8, 0); /* LCDD1 */
at91_set_A_periph(AT91_PIN_PE9, 0); /* LCDD2 */
at91_set_A_periph(AT91_PIN_PE10, 0); /* LCDD3 */
at91_set_A_periph(AT91_PIN_PE11, 0); /* LCDD4 */
at91_set_A_periph(AT91_PIN_PE12, 0); /* LCDD5 */
at91_set_A_periph(AT91_PIN_PE13, 0); /* LCDD6 */
at91_set_A_periph(AT91_PIN_PE14, 0); /* LCDD7 */
at91_set_A_periph(AT91_PIN_PE15, 0); /* LCDD8 */
at91_set_A_periph(AT91_PIN_PE16, 0); /* LCDD9 */
at91_set_A_periph(AT91_PIN_PE17, 0); /* LCDD10 */
at91_set_A_periph(AT91_PIN_PE18, 0); /* LCDD11 */
at91_set_A_periph(AT91_PIN_PE19, 0); /* LCDD12 */
at91_set_B_periph(AT91_PIN_PE20, 0); /* LCDD13 */
at91_set_A_periph(AT91_PIN_PE21, 0); /* LCDD14 */
at91_set_A_periph(AT91_PIN_PE22, 0); /* LCDD15 */
at91_set_A_periph(AT91_PIN_PE23, 0); /* LCDD16 */
at91_set_A_periph(AT91_PIN_PE24, 0); /* LCDD17 */
at91_set_A_periph(AT91_PIN_PE25, 0); /* LCDD18 */
at91_set_A_periph(AT91_PIN_PE26, 0); /* LCDD19 */
at91_set_A_periph(AT91_PIN_PE27, 0); /* LCDD20 */
at91_set_B_periph(AT91_PIN_PE28, 0); /* LCDD21 */
at91_set_A_periph(AT91_PIN_PE29, 0); /* LCDD22 */
at91_set_A_periph(AT91_PIN_PE30, 0); /* LCDD23 */
at91_periph_clk_enable(ATMEL_ID_LCDC);
}
#endif
#ifdef CONFIG_GURNARD_FPGA
/**
* Initialise the memory bus settings so that we can talk to the
* memory mapped FPGA
*/
static int fpga_hw_init(void)
{
struct at91_matrix *matrix = (struct at91_matrix *)ATMEL_BASE_MATRIX;
struct at91_smc *smc = (struct at91_smc *)ATMEL_BASE_SMC;
int i;
setbits_le32(&matrix->ebicsa, AT91_MATRIX_EBI_CS1A_SDRAMC);
at91_set_a_periph(2, 4, 0); /* EBIA21 */
at91_set_a_periph(2, 5, 0); /* EBIA22 */
at91_set_a_periph(2, 6, 0); /* EBIA23 */
at91_set_a_periph(2, 7, 0); /* EBIA24 */
at91_set_a_periph(2, 12, 0); /* EBIA25 */
for (i = 15; i <= 31; i++) /* EBINWAIT & EBID16 - 31 */
at91_set_a_periph(2, i, 0);
/* configure SMC cs0 for FPGA access timing */
writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(2) |
AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(2),
&smc->cs[0].setup);
writel(AT91_SMC_PULSE_NWE(5) | AT91_SMC_PULSE_NCS_WR(4) |
AT91_SMC_PULSE_NRD(6) | AT91_SMC_PULSE_NCS_RD(4),
&smc->cs[0].pulse);
writel(AT91_SMC_CYCLE_NWE(6) | AT91_SMC_CYCLE_NRD(6),
&smc->cs[0].cycle);
writel(AT91_SMC_MODE_BAT |
AT91_SMC_MODE_EXNW_DISABLE |
AT91_SMC_MODE_DBW_32 |
AT91_SMC_MODE_TDF |
AT91_SMC_MODE_TDF_CYCLE(2),
&smc->cs[0].mode);
/* Do a write to within EBI_CS1 to enable the SDCK */
writel(0, ATMEL_BASE_CS1);
return 0;
}
#endif
#ifdef CONFIG_CMD_USB
#define USB0_ENABLE_PIN AT91_PIN_PB22
#define USB1_ENABLE_PIN AT91_PIN_PB23
void gurnard_usb_init(void)
{
at91_set_gpio_output(USB0_ENABLE_PIN, 1);
at91_set_gpio_value(USB0_ENABLE_PIN, 0);
at91_set_gpio_output(USB1_ENABLE_PIN, 1);
at91_set_gpio_value(USB1_ENABLE_PIN, 0);
}
#endif
#ifdef CONFIG_GENERIC_ATMEL_MCI
int cpu_mmc_init(struct bd_info *bis)
{
return atmel_mci_init((void *)ATMEL_BASE_MCI0);
}
#endif
static void gurnard_enable_console(int enable)
{
at91_set_gpio_output(AT91_PIN_PB14, 1);
at91_set_gpio_value(AT91_PIN_PB14, enable ? 0 : 1);
}
void at91sam9g45_slowclock_init(void)
{
/*
* On AT91SAM9G45 revC CPUs, the slow clock can be based on an
* internal impreciseRC oscillator or an external 32kHz oscillator.
* Switch to the latter.
*/
unsigned i, tmp;
ulong *reg = (ulong *)ATMEL_BASE_SCKCR;
tmp = readl(reg);
if ((tmp & AT91SAM9G45_SCKCR_OSCSEL) == AT91SAM9G45_SCKCR_OSCSEL_RC) {
timer_init();
tmp |= AT91SAM9G45_SCKCR_OSC32EN;
writel(tmp, reg);
for (i = 0; i < 1200; i++)
udelay(1000);
tmp |= AT91SAM9G45_SCKCR_OSCSEL_32;
writel(tmp, reg);
udelay(200);
tmp &= ~AT91SAM9G45_SCKCR_RCEN;
writel(tmp, reg);
}
}
int board_early_init_f(void)
{
at91_seriald_hw_init();
gurnard_enable_console(1);
return 0;
}
int board_init(void)
{
const char *rev_str;
#ifdef CONFIG_CMD_NAND
int ret;
#endif
at91_periph_clk_enable(ATMEL_ID_PIOA);
at91_periph_clk_enable(ATMEL_ID_PIOB);
at91_periph_clk_enable(ATMEL_ID_PIOC);
at91_periph_clk_enable(ATMEL_ID_PIODE);
at91sam9g45_slowclock_init();
/*
* Clear the RTC IDR to disable all IRQs. Avoid issues when Linux
* boots with spurious IRQs.
*/
writel(0xffffffff, AT91_RTC_IDR);
/* Make sure that the reset signal is attached properly */
setbits_le32(AT91_ASM_RSTC_MR, AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN);
gd->bd->bi_arch_number = MACH_TYPE_SNAPPER_9260;
/* Address of boot parameters */
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
#ifdef CONFIG_CMD_NAND
ret = gurnard_nand_hw_init();
if (ret)
return ret;
#endif
#ifdef CONFIG_ATMEL_SPI
at91_spi0_hw_init(1 << 4);
#endif
#ifdef CONFIG_MACB
gurnard_macb_hw_init();
#endif
#ifdef CONFIG_GURNARD_FPGA
fpga_hw_init();
#endif
#ifdef CONFIG_CMD_USB
gurnard_usb_init();
#endif
#ifdef CONFIG_CMD_MMC
at91_set_A_periph(AT91_PIN_PA12, 0);
at91_set_gpio_output(AT91_PIN_PA8, 1);
at91_set_gpio_value(AT91_PIN_PA8, 0);
at91_mci_hw_init();
#endif
#ifdef CONFIG_DM_VIDEO
at91sam9g45_lcd_hw_init();
at91_set_A_periph(AT91_PIN_PE6, 1); /* power up */
/* Select the second timing index for board rev 2 */
rev_str = env_get("board_rev");
if (rev_str && !strncmp(rev_str, "2", 1)) {
struct udevice *dev;
uclass_find_first_device(UCLASS_VIDEO, &dev);
if (dev) {
struct atmel_lcd_plat *plat = dev_get_plat(dev);
plat->timing_index = 1;
}
}
#endif
return 0;
}
int board_late_init(void)
{
u_int8_t env_enetaddr[8];
char *env_str;
char *end;
int i;
/*
* Set MAC address so we do not need to init Ethernet before Linux
* boot
*/
env_str = env_get("ethaddr");
if (env_str) {
struct at91_emac *emac = (struct at91_emac *)ATMEL_BASE_EMAC;
/* Parse MAC address */
for (i = 0; i < 6; i++) {
env_enetaddr[i] = env_str ?
simple_strtoul(env_str, &end, 16) : 0;
if (env_str)
env_str = (*end) ? end+1 : end;
}
/* Set hardware address */
writel(env_enetaddr[0] | env_enetaddr[1] << 8 |
env_enetaddr[2] << 16 | env_enetaddr[3] << 24,
&emac->sa2l);
writel((env_enetaddr[4] | env_enetaddr[5] << 8), &emac->sa2h);
printf("MAC: %s\n", env_get("ethaddr"));
} else {
/* Not set in environment */
printf("MAC: not set\n");
}
#ifdef CONFIG_GURNARD_SPLASH
lcd_splash(480, 272);
#endif
return 0;
}
#ifndef CONFIG_DM_ETH
int board_eth_init(struct bd_info *bis)
{
return macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0);
}
#endif
int dram_init(void)
{
gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
CONFIG_SYS_SDRAM_SIZE);
return 0;
}
void reset_phy(void)
{
}
static struct atmel_serial_plat at91sam9260_serial_plat = {
.base_addr = ATMEL_BASE_DBGU,
};
U_BOOT_DRVINFO(at91sam9260_serial) = {
.name = "serial_atmel",
.plat = &at91sam9260_serial_plat,
};