Merge branch 'master' of git://git.denx.de/u-boot-atmel

This commit is contained in:
Tom Rini 2016-06-13 08:50:58 -04:00
commit fd9102dafe
40 changed files with 5524 additions and 151 deletions

5
README
View File

@ -4824,6 +4824,11 @@ Low Level (hardware related) configuration options:
other boot loader or by a debugger which performs
these initializations itself.
- CONFIG_SKIP_LOWLEVEL_INIT_ONLY
[ARM926EJ-S only] This allows just the call to lowlevel_init()
to be skipped. The normal CPU15 init (such as enabling the
instruction cache) is still performed.
- CONFIG_SPL_BUILD
Modifies the behaviour of start.S when compiling a loader
that is executed before the actual U-Boot. E.g. when

View File

@ -82,6 +82,7 @@ cpu_init_crit:
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* Jump to board specific initialization... The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle wake up conditions.
@ -89,5 +90,6 @@ cpu_init_crit:
mov ip, lr /* persevere link reg across call */
bl lowlevel_init /* go setup pll,mux,memory */
mov lr, ip /* restore link */
#endif
mov pc, lr /* back to my caller */
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

View File

@ -135,6 +135,7 @@ cpu_init_crit:
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
@ -143,7 +144,7 @@ cpu_init_crit:
mov ip, lr
bl lowlevel_init
mov lr, ip
#endif
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

View File

@ -101,11 +101,13 @@ flush_dcache:
#endif
mcr p15, 0, r0, c1, c0, 0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* Go setup Memory and board specific bits prior to relocation.
*/
mov ip, lr /* perserve link reg across call */
bl lowlevel_init /* go setup pll,mux,memory */
mov lr, ip /* restore link */
#endif
mov pc, lr /* back to my caller */
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

View File

@ -90,11 +90,13 @@ cpu_init_crit:
orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
mcr p15, 0, r0, c1, c0, 0
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* Go setup Memory and board specific bits prior to relocation.
*/
mov ip, lr /* perserve link reg across call */
bl lowlevel_init /* go setup memory */
mov lr, ip /* restore link */
#endif
mov pc, lr /* back to my caller */
#endif

View File

@ -66,7 +66,9 @@ save_boot_params_ret:
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_cp15
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
bl cpu_init_crit
#endif
#endif
bl _main
@ -250,7 +252,8 @@ skip_errata_621766:
mov pc, r5 @ back to my caller
ENDPROC(cpu_init_cp15)
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) && \
!defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY)
/*************************************************************************
*
* CPU_init_critical registers

View File

@ -96,6 +96,7 @@ cpu_init_crit:
ldr r1, cpuspeed
str r1, [r0, #PPCR]
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
@ -104,6 +105,7 @@ cpu_init_crit:
mov ip, lr
bl lowlevel_init
mov lr, ip
#endif
/*
* disable MMU stuff and enable I-cache

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
dtb-$(CONFIG_AT91FAMILY) += at91sam9g45-gurnard.dtb
dtb-$(CONFIG_S5PC100) += s5pc1xx-smdkc100.dtb
dtb-$(CONFIG_S5PC110) += s5pc1xx-goni.dtb
dtb-$(CONFIG_EXYNOS4) += exynos4210-origen.dtb \

View File

@ -0,0 +1,157 @@
/*
* at91sam9g20ek.dts - Device Tree file for Atmel at91sam9g20ek board
*
* Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* Licensed under GPLv2.
*/
/dts-v1/;
#include "at91sam9g45.dtsi"
/ {
model = "Bluewater Systems Gurnard";
compatible = "atmel,at91sam9g45", "atmel,at91sam9";
chosen {
bootargs = "mem=64M root=/dev/mtdblock5 rw rootfstype=ubifs";
stdout-path = "serial0:115200n8";
};
memory {
reg = <0x20000000 0x8000000>;
};
clocks {
slow_xtal {
clock-frequency = <32768>;
};
main_xtal {
clock-frequency = <18432000>;
};
};
ahb {
u-boot,dm-pre-reloc;
fb@0x00500000 {
u-boot,dm-pre-reloc;
status = "okay";
display-timings {
rev1 {
clock-frequency = <4166666>;
hactive = <480>;
vactive = <272>;
hfront-porch = <1>;
hback-porch = <1>;
hsync-len = <1>;
vback-porch = <4>;
vfront-porch = <2>;
vsync-len = <1>;
hsync-active = <0>;
vsync-active = <0>;
};
rev2 {
clock-frequency = <4166666>;
hactive = <480>;
vactive = <272>;
hfront-porch = <2>;
hback-porch = <2>;
hsync-len = <10>;
vback-porch = <2>;
vfront-porch = <2>;
vsync-len = <10>;
hsync-active = <0>;
vsync-active = <0>;
};
};
};
apb {
pinctrl@fffff400 {
board {
pinctrl_pck0_as_mck: pck0_as_mck {
atmel,pins =
<AT91_PIOC 1 AT91_PERIPH_B AT91_PINCTRL_NONE>; /* PC1 periph B */
};
};
mmc0_slot1 {
pinctrl_board_mmc0_slot1: mmc0_slot1-board {
atmel,pins =
<AT91_PIOC 9 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PC9 gpio CD pin pull up and deglitch */
};
};
};
dbgu: serial@ffffee00 {
status = "okay";
};
macb0: ethernet@fffbc000 {
phy-mode = "rmii";
status = "okay";
};
mmc0: mmc@fff80000 {
pinctrl-0 = <
&pinctrl_board_mmc0_slot1
&pinctrl_mmc0_slot0_clk_cmd_dat0
&pinctrl_mmc0_slot0_dat1_3>;
status = "okay";
slot@1 {
reg = <1>;
bus-width = <4>;
cd-gpios = <&pioC 9 GPIO_ACTIVE_HIGH>;
};
};
ssc0: ssc@fff9c000 {
status = "okay";
pinctrl-0 = <&pinctrl_ssc0_tx>;
};
spi0: spi@fffa4000 {
cs-gpios = <0>, <&pioC 11 0>, <0>, <0>;
mtd_dataflash@0 {
compatible = "atmel,at45", "atmel,dataflash";
spi-max-frequency = <50000000>;
reg = <1>;
};
};
shdwc@fffffd10 {
atmel,wakeup-counter = <10>;
atmel,wakeup-rtt-timer;
};
rtc@fffffd20 {
atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
status = "okay";
};
watchdog@fffffd40 {
status = "okay";
};
gpbr: syscon@fffffd60 {
status = "okay";
};
};
nand0: nand@40000000 {
nand-bus-width = <8>;
nand-ecc-mode = "hardware";
nand-on-flash-bbt;
status = "okay";
};
usb1: ehci@00800000 {
atmel,vbus-gpio = <&pioC 5 GPIO_ACTIVE_HIGH>;
status = "okay";
};
};
};

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,14 @@ config TARGET_SNAPPER9260
select DM_SERIAL
select DM_GPIO
config TARGET_GURNARD
bool "Support gurnard"
select CPU_ARM926EJS
select DM
select DM_SERIAL
select DM_GPIO
select DM_ETH
config TARGET_AT91SAM9261EK
bool "Atmel at91sam9261 reference board"
select CPU_ARM926EJS
@ -149,6 +157,7 @@ source "board/atmel/sama5d3_xplained/Kconfig"
source "board/atmel/sama5d3xek/Kconfig"
source "board/atmel/sama5d4_xplained/Kconfig"
source "board/atmel/sama5d4ek/Kconfig"
source "board/bluewater/gurnard/Kconfig"
source "board/bluewater/snapper9260/Kconfig"
source "board/calao/usb_a9263/Kconfig"
source "board/denx/ma5d4evk/Kconfig"

View File

@ -10,8 +10,8 @@ obj-$(CONFIG_AT91SAM9M10G45) += mpddrc.o spl_at91.o
obj-$(CONFIG_AT91SAM9N12) += mpddrc.o spl_at91.o
obj-$(CONFIG_AT91SAM9X5) += mpddrc.o spl_at91.o
obj-$(CONFIG_SAMA5D2) += bootparams_atmel.o mpddrc.o spl_atmel.o matrix.o atmel_sfr.o
obj-$(CONFIG_SAMA5D3) += mpddrc.o spl_atmel.o
obj-$(CONFIG_SAMA5D4) += mpddrc.o spl_atmel.o matrix.o atmel_sfr.o
obj-$(CONFIG_SAMA5D3) += bootparams_atmel.o mpddrc.o spl_atmel.o
obj-$(CONFIG_SAMA5D4) += bootparams_atmel.o mpddrc.o spl_atmel.o matrix.o atmel_sfr.o
obj-y += spl.o
endif

View File

@ -7,6 +7,7 @@
*/
#include <common.h>
#include <dm.h>
#include <asm/arch/at91_common.h>
#include <asm/arch/clk.h>
#include <asm/arch/gpio.h>
@ -165,3 +166,20 @@ void at91_mci_hw_init(void)
at91_periph_clk_enable(ATMEL_ID_MCI0);
}
#endif
/* Platform data for the GPIOs */
static const struct at91_port_platdata at91sam9260_plat[] = {
{ ATMEL_BASE_PIOA, "PA" },
{ ATMEL_BASE_PIOB, "PB" },
{ ATMEL_BASE_PIOC, "PC" },
{ ATMEL_BASE_PIOD, "PD" },
{ ATMEL_BASE_PIOE, "PE" },
};
U_BOOT_DEVICES(at91sam9260_gpios) = {
{ "gpio_at91", &at91sam9260_plat[0] },
{ "gpio_at91", &at91sam9260_plat[1] },
{ "gpio_at91", &at91sam9260_plat[2] },
{ "gpio_at91", &at91sam9260_plat[3] },
{ "gpio_at91", &at91sam9260_plat[4] },
};

View File

@ -67,18 +67,18 @@ typedef struct at91_pmc {
#define AT91_PMC_MOR_MOSCEN 0x01
#define AT91_PMC_MOR_OSCBYPASS 0x02
#define AT91_PMC_MOR_MOSCRCEN 0x08
#define AT91_PMC_MOR_OSCOUNT(x) ((x & 0xff) << 8)
#define AT91_PMC_MOR_KEY(x) ((x & 0xff) << 16)
#define AT91_PMC_MOR_OSCOUNT(x) (((x) & 0xff) << 8)
#define AT91_PMC_MOR_KEY(x) (((x) & 0xff) << 16)
#define AT91_PMC_MOR_MOSCSEL (1 << 24)
#define AT91_PMC_PLLXR_DIV(x) (x & 0xFF)
#define AT91_PMC_PLLXR_PLLCOUNT(x) ((x & 0x3F) << 8)
#define AT91_PMC_PLLXR_OUT(x) ((x & 0x03) << 14)
#define AT91_PMC_PLLXR_DIV(x) ((x) & 0xFF)
#define AT91_PMC_PLLXR_PLLCOUNT(x) (((x) & 0x3F) << 8)
#define AT91_PMC_PLLXR_OUT(x) (((x) & 0x03) << 14)
#if defined(CONFIG_SAMA5D2) || defined(CONFIG_SAMA5D3) || \
defined(CONFIG_SAMA5D4)
#define AT91_PMC_PLLXR_MUL(x) ((x & 0x7F) << 18)
#define AT91_PMC_PLLXR_MUL(x) (((x) & 0x7F) << 18)
#else
#define AT91_PMC_PLLXR_MUL(x) ((x & 0x7FF) << 16)
#define AT91_PMC_PLLXR_MUL(x) (((x) & 0x7FF) << 16)
#endif
#define AT91_PMC_PLLAR_29 0x20000000
#define AT91_PMC_PLLBR_USBDIV_1 0x00000000
@ -158,7 +158,7 @@ typedef struct at91_pmc {
#define AT91_PMC_PCR_CMD_WRITE (0x1 << 12)
#define AT91_PMC_PCR_DIV (0x3 << 16)
#define AT91_PMC_PCR_GCKDIV (0xff << 20)
#define AT91_PMC_PCR_GCKDIV_(x) ((x & 0xff) << 20)
#define AT91_PMC_PCR_GCKDIV_(x) (((x) & 0xff) << 20)
#define AT91_PMC_PCR_GCKDIV_OFFSET 20
#define AT91_PMC_PCR_EN (0x1 << 28)
#define AT91_PMC_PCR_GCKEN (0x1 << 29)

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* Real Time Clock (RTC) - System peripheral registers.
* Based on AT91RM9200 datasheet revision E.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef AT91_RTC_H
#define AT91_RTC_H
/* Control Register */
#define AT91_RTC_CR (ATMEL_BASE_RTC + 0x00)
#define AT91_RTC_UPDTIM (1 << 0) /* Update Request Time */
#define AT91_RTC_UPDCAL (1 << 1) /* Update Request Calendar */
#define AT91_RTC_TIMEVSEL (3 << 8) /* Time Event Selection */
#define AT91_RTC_TIMEVSEL_MINUTE (0 << 8)
#define AT91_RTC_TIMEVSEL_HOUR (1 << 8)
#define AT91_RTC_TIMEVSEL_DAY24 (2 << 8)
#define AT91_RTC_TIMEVSEL_DAY12 (3 << 8)
#define AT91_RTC_CALEVSEL (3 << 16) /* Calendar Event Selection */
#define AT91_RTC_CALEVSEL_WEEK (0 << 16)
#define AT91_RTC_CALEVSEL_MONTH (1 << 16)
#define AT91_RTC_CALEVSEL_YEAR (2 << 16)
#define AT91_RTC_MR (ATMEL_BASE_RTC + 0x04) /* Mode Register */
#define AT91_RTC_HRMOD (1 << 0) /* 12/24 Hour Mode */
#define AT91_RTC_TIMR (ATMEL_BASE_RTC + 0x08) /* Time Register */
#define AT91_RTC_SEC (0x7f << 0) /* Current Second */
#define AT91_RTC_MIN (0x7f << 8) /* Current Minute */
#define AT91_RTC_HOUR (0x3f << 16) /* Current Hour */
#define AT91_RTC_AMPM (1 << 22) /* AM/PM */
#define AT91_RTC_CALR (ATMEL_BASE_RTC + 0x0c) /* Calendar Register */
#define AT91_RTC_CENT (0x7f << 0) /* Current Century */
#define AT91_RTC_YEAR (0xff << 8) /* Current Year */
#define AT91_RTC_MONTH (0x1f << 16) /* Current Month */
#define AT91_RTC_DAY (7 << 21) /* Current Day */
#define AT91_RTC_DATE (0x3f << 24) /* Current Date */
#define AT91_RTC_TIMALR (ATMEL_BASE_RTC + 0x10) /* Time Alarm */
#define AT91_RTC_SECEN (1 << 7) /* Second Alarm Enab */
#define AT91_RTC_MINEN (1 << 15) /* Minute Alarm Enab */
#define AT91_RTC_HOUREN (1 << 23) /* Hour Alarm Enable */
#define AT91_RTC_CALALR (ATMEL_BASE_RTC + 0x14) /* Calendar Alarm */
#define AT91_RTC_MTHEN (1 << 23) /* Month Alarm Enable */
#define AT91_RTC_DATEEN (1 << 31) /* Date Alarm Enable */
#define AT91_RTC_SR (ATMEL_BASE_RTC + 0x18) /* Status Register */
#define AT91_RTC_ACKUPD (1 << 0) /* Ack for Update */
#define AT91_RTC_ALARM (1 << 1) /* Alarm Flag */
#define AT91_RTC_SECEV (1 << 2) /* Second Event */
#define AT91_RTC_TIMEV (1 << 3) /* Time Event */
#define AT91_RTC_CALEV (1 << 4) /* Calendar Event */
#define AT91_RTC_SCCR (ATMEL_BASE_RTC + 0x1c) /* Status Clear Cmd */
#define AT91_RTC_IER (ATMEL_BASE_RTC + 0x20) /* Interrupt Enable */
#define AT91_RTC_IDR (ATMEL_BASE_RTC + 0x24) /* Interrupt Disable */
#define AT91_RTC_IMR (ATMEL_BASE_RTC + 0x28) /* Interrupt Mask */
#define AT91_RTC_VER (ATMEL_BASE_RTC + 0x2c) /* Valid Entry */
#define AT91_RTC_NVTIM (1 << 0) /* Non-valid Time */
#define AT91_RTC_NVCAL (1 << 1) /* Non-valid Calendar */
#define AT91_RTC_NVTIMALR (1 << 2) /* .. Time Alarm */
#define AT91_RTC_NVCALALR (1 << 3) /* .. Calendar Alarm */
#endif

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2016 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef AT91_SCK_H
#define AT91_SCK_H
/*
* SCKCR flags
*/
#define AT91SAM9G45_SCKCR_RCEN (1 << 0) /* RC Oscillator Enable */
#define AT91SAM9G45_SCKCR_OSC32EN (1 << 1) /* 32kHz Oscillator Enable */
#define AT91SAM9G45_SCKCR_OSC32BYP (1 << 2) /* 32kHz Oscillator Bypass */
#define AT91SAM9G45_SCKCR_OSCSEL (1 << 3) /* Slow Clock Selector */
#define AT91SAM9G45_SCKCR_OSCSEL_RC (0 << 3)
#define AT91SAM9G45_SCKCR_OSCSEL_32 (1 << 3)
#endif

View File

@ -109,6 +109,7 @@
#define ATMEL_BASE_RTT 0xfffffd20
#define ATMEL_BASE_PIT 0xfffffd30
#define ATMEL_BASE_WDT 0xfffffd40
#define ATMEL_BASE_SCKCR 0xfffffd50
#define ATMEL_BASE_GPBR 0xfffffd60
#define ATMEL_BASE_RTC 0xfffffdb0
/* Reserved: 0xfffffdc0 - 0xffffffff */

View File

@ -0,0 +1,25 @@
/*
* Boot mode definitions for the SAMA5Dx SoC
*
* Copyright (C) 2016 Marek Vasut <marex@denx.de>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __SAMA5_BOOT_H
#define __SAMA5_BOOT_H
/* Boot modes stored by BootROM in r4 */
#define ATMEL_SAMA5_BOOT_FROM_OFF 0
#define ATMEL_SAMA5_BOOT_FROM_MASK 0xf
#define ATMEL_SAMA5_BOOT_FROM_SPI (0 << 0)
#define ATMEL_SAMA5_BOOT_FROM_MCI (1 << 0)
#define ATMEL_SAMA5_BOOT_FROM_SMC (2 << 0)
#define ATMEL_SAMA5_BOOT_FROM_TWI (3 << 0)
#define ATMEL_SAMA5_BOOT_FROM_QSPI (4 << 0)
#define ATMEL_SAMA5_BOOT_FROM_SAMBA (7 << 0)
#define ATMEL_SAMA5_BOOT_DEV_ID_OFF 4
#define ATMEL_SAMA5_BOOT_DEV_ID_MASK 0xf
#endif /* __SAMA5_BOOT_H */

View File

@ -230,18 +230,6 @@
/* No PMECC Galois table in ROM */
#define NO_GALOIS_TABLE_IN_ROM
/* Boot modes stored by BootROM in r4 */
#define ATMEL_SAMA5D2_BOOT_FROM_OFF 0
#define ATMEL_SAMA5D2_BOOT_FROM_MASK 0xf
#define ATMEL_SAMA5D2_BOOT_FROM_SPI (0 << 0)
#define ATMEL_SAMA5D2_BOOT_FROM_MCI (1 << 0)
#define ATMEL_SAMA5D2_BOOT_FROM_SMC (2 << 0)
#define ATMEL_SAMA5D2_BOOT_FROM_TWI (3 << 0)
#define ATMEL_SAMA5D2_BOOT_FROM_QSPI (4 << 0)
#define ATMEL_SAMA5D2_BOOT_DEV_ID_OFF 4
#define ATMEL_SAMA5D2_BOOT_DEV_ID_MASK 0xf
#ifndef __ASSEMBLY__
unsigned int get_chip_id(void);
unsigned int get_extension_chip_id(void);

View File

@ -23,20 +23,22 @@ void at91_disable_wdt(void)
}
#endif
#if defined(CONFIG_SAMA5D2)
#if defined(CONFIG_SAMA5D2) || defined(CONFIG_SAMA5D3) || \
defined(CONFIG_SAMA5D4)
#include <asm/arch/sama5_boot.h>
struct {
u32 r4;
} bootrom_stash __attribute__((section(".data")));
u32 spl_boot_device(void)
{
u32 dev = (bootrom_stash.r4 >> ATMEL_SAMA5D2_BOOT_FROM_OFF) &
ATMEL_SAMA5D2_BOOT_FROM_MASK;
u32 off = (bootrom_stash.r4 >> ATMEL_SAMA5D2_BOOT_DEV_ID_OFF) &
ATMEL_SAMA5D2_BOOT_DEV_ID_MASK;
u32 dev = (bootrom_stash.r4 >> ATMEL_SAMA5_BOOT_FROM_OFF) &
ATMEL_SAMA5_BOOT_FROM_MASK;
u32 off = (bootrom_stash.r4 >> ATMEL_SAMA5_BOOT_DEV_ID_OFF) &
ATMEL_SAMA5_BOOT_DEV_ID_MASK;
#if defined(CONFIG_SYS_USE_MMC)
if (dev == ATMEL_SAMA5D2_BOOT_FROM_MCI) {
if (dev == ATMEL_SAMA5_BOOT_FROM_MCI) {
if (off == 0)
return BOOT_DEVICE_MMC1;
if (off == 1)
@ -47,10 +49,13 @@ u32 spl_boot_device(void)
#endif
#if defined(CONFIG_SYS_USE_SERIALFLASH) || defined(CONFIG_SYS_USE_SPIFLASH)
if (dev == ATMEL_SAMA5D2_BOOT_FROM_SPI)
if (dev == ATMEL_SAMA5_BOOT_FROM_SPI)
return BOOT_DEVICE_SPI;
#endif
if (dev == ATMEL_SAMA5_BOOT_FROM_SAMBA)
return BOOT_DEVICE_USB;
printf("ERROR: SMC/TWI/QSPI boot device not supported!\n"
" Boot device %i, controller number %i\n", dev, off);

View File

@ -0,0 +1,12 @@
if TARGET_GURNARD
config SYS_BOARD
default "gurnard"
config SYS_VENDOR
default "bluewater"
config SYS_CONFIG_NAME
default "snapper9g45"
endif

View File

@ -0,0 +1,6 @@
GURNARD BOARD
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/bluewater/gurnard/
F: include/configs/snapper9g45.h
F: configs/gurnard_defconfig

View File

@ -0,0 +1,11 @@
#
# (C) Copyright 2003-2008
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# (C) Copyright 2011 Bluewater Systems
# Ryan Mallon <ryan@bluewatersys.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += gurnard.o

View File

@ -0,0 +1,449 @@
/*
* Bluewater Systems Snapper 9260/9G20 modules
*
* (C) Copyright 2011 Bluewater Systems
* Author: Andre Renaud <andre@bluewatersys.com>
* Author: Ryan Mallon <ryan@bluewatersys.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <atmel_lcd.h>
#include <atmel_lcdc.h>
#include <atmel_mci.h>
#include <dm.h>
#include <lcd.h>
#include <net.h>
#ifndef CONFIG_DM_ETH
#include <netdev.h>
#endif
#include <spi.h>
#include <asm/gpio.h>
#include <asm/io.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>
#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(bd_t *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 = getenv("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_platdata *plat = dev_get_platdata(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 = getenv("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", getenv("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(bd_t *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)
{
}
/* This breaks the Ethernet MAC at present */
void enable_caches(void)
{
dcache_enable();
}
/* SPI chip select control - only used for FPGA programming */
#ifdef CONFIG_ATMEL_SPI
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
return bus == 0 && cs == 0;
}
void spi_cs_activate(struct spi_slave *slave)
{
/* We don't use chipselects for FPGA programming */
}
void spi_cs_deactivate(struct spi_slave *slave)
{
/* We don't use chipselects for FPGA programming */
}
#endif /* CONFIG_ATMEL_SPI */
static struct atmel_serial_platdata at91sam9260_serial_plat = {
.base_addr = ATMEL_BASE_DBGU,
};
U_BOOT_DEVICE(at91sam9260_serial) = {
.name = "serial_atmel",
.platdata = &at91sam9260_serial_plat,
};

File diff suppressed because it is too large Load Diff

View File

@ -445,7 +445,7 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
return err;
}
flush_cache(load, *load_end - load);
flush_cache(load, ALIGN(*load_end - load, ARCH_DMA_MINALIGN));
debug(" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end);
bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED);

20
configs/gurnard_defconfig Normal file
View File

@ -0,0 +1,20 @@
CONFIG_ARM=y
CONFIG_ARCH_AT91=y
CONFIG_TARGET_GURNARD=y
CONFIG_DEFAULT_DEVICE_TREE="at91sam9g45-gurnard"
CONFIG_FIT=y
CONFIG_SYS_EXTRA_OPTIONS="AT91SAM9G45"
CONFIG_BOOTDELAY=3
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_IMI is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_LOADS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
# CONFIG_CMD_SOURCE is not set
# CONFIG_CMD_SETEXPR is not set
CONFIG_OF_CONTROL=y
CONFIG_DM_VIDEO=y
CONFIG_CMD_DHRYSTONE=y
# CONFIG_EFI_LOADER is not set

View File

@ -59,6 +59,11 @@ int at91_set_pio_pullup(unsigned port, unsigned pin, int use_pullup)
{
struct at91_port *at91_port = at91_pio_get_port(port);
#if defined(CPU_HAS_PIO3)
if (use_pullup)
at91_set_pio_pulldown(port, pin, 0);
#endif
if (at91_port && (pin < GPIO_PER_BANK))
at91_set_port_pullup(at91_port, pin, use_pullup);
@ -305,10 +310,10 @@ int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on)
if (at91_port && (pin < GPIO_PER_BANK)) {
mask = 1 << pin;
writel(mask, &at91_port->pudr);
if (is_on)
if (is_on) {
at91_set_pio_pullup(port, pin, 0);
writel(mask, &at91_port->ppder);
else
} else
writel(mask, &at91_port->ppddr);
}

View File

@ -24,9 +24,9 @@
/* Register access macros */
#define ecc_readl(add, reg) \
readl(AT91_BASE_SYS + add + ATMEL_ECC_##reg)
readl(add + ATMEL_ECC_##reg)
#define ecc_writel(add, reg, value) \
writel((value), AT91_BASE_SYS + add + ATMEL_ECC_##reg)
writel((value), add + ATMEL_ECC_##reg)
#include "atmel_nand_ecc.h" /* Hardware ECC registers */
@ -1156,6 +1156,7 @@ int atmel_hwecc_nand_init_param(struct nand_chip *nand, struct mtd_info *mtd)
nand->ecc.hwctl = atmel_nand_hwctl;
nand->ecc.read_page = atmel_nand_read_page;
nand->ecc.bytes = 4;
nand->ecc.strength = 4;
if (nand->ecc.mode == NAND_ECC_HW) {
/* ECC is calculated for the whole page (1 step) */

View File

@ -4,6 +4,7 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
/*
* The u-boot networking stack is a little weird. It seems like the
@ -28,7 +29,9 @@
*/
#include <net.h>
#ifndef CONFIG_DM_ETH
#include <netdev.h>
#endif
#include <malloc.h>
#include <miiphy.h>
@ -84,6 +87,8 @@ struct macb_device {
unsigned int rx_tail;
unsigned int tx_head;
unsigned int tx_tail;
unsigned int next_rx_tail;
bool wrapped;
void *rx_buffer;
void *tx_buffer;
@ -98,11 +103,15 @@ struct macb_device {
unsigned long dummy_desc_dma;
const struct device *dev;
#ifndef CONFIG_DM_ETH
struct eth_device netdev;
#endif
unsigned short phy_addr;
struct mii_dev *bus;
};
#ifndef CONFIG_DM_ETH
#define to_macb(_nd) container_of(_nd, struct macb_device, netdev)
#endif
static int macb_is_gem(struct macb_device *macb)
{
@ -192,8 +201,13 @@ void __weak arch_get_mdio_control(const char *name)
int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
{
#ifdef CONFIG_DM_ETH
struct udevice *dev = eth_get_dev_by_name(devname);
struct macb_device *macb = dev_get_priv(dev);
#else
struct eth_device *dev = eth_get_dev_by_name(devname);
struct macb_device *macb = to_macb(dev);
#endif
if (macb->phy_addr != phy_adr)
return -1;
@ -206,8 +220,13 @@ int macb_miiphy_read(const char *devname, u8 phy_adr, u8 reg, u16 *value)
int macb_miiphy_write(const char *devname, u8 phy_adr, u8 reg, u16 value)
{
#ifdef CONFIG_DM_ETH
struct udevice *dev = eth_get_dev_by_name(devname);
struct macb_device *macb = dev_get_priv(dev);
#else
struct eth_device *dev = eth_get_dev_by_name(devname);
struct macb_device *macb = to_macb(dev);
#endif
if (macb->phy_addr != phy_adr)
return -1;
@ -255,9 +274,9 @@ static inline void macb_invalidate_rx_buffer(struct macb_device *macb)
#if defined(CONFIG_CMD_NET)
static int macb_send(struct eth_device *netdev, void *packet, int length)
static int _macb_send(struct macb_device *macb, const char *name, void *packet,
int length)
{
struct macb_device *macb = to_macb(netdev);
unsigned long paddr, ctrl;
unsigned int tx_head = macb->tx_head;
int i;
@ -278,7 +297,7 @@ static int macb_send(struct eth_device *netdev, void *packet, int length)
barrier();
macb_flush_ring_desc(macb, TX);
/* Do we need check paddr and length is dcache line aligned? */
flush_dcache_range(paddr, paddr + length);
flush_dcache_range(paddr, paddr + ALIGN(length, ARCH_DMA_MINALIGN));
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
/*
@ -298,12 +317,11 @@ static int macb_send(struct eth_device *netdev, void *packet, int length)
if (i <= MACB_TX_TIMEOUT) {
if (ctrl & TXBUF_UNDERRUN)
printf("%s: TX underrun\n", netdev->name);
printf("%s: TX underrun\n", name);
if (ctrl & TXBUF_EXHAUSTED)
printf("%s: TX buffers exhausted in mid frame\n",
netdev->name);
printf("%s: TX buffers exhausted in mid frame\n", name);
} else {
printf("%s: TX timeout\n", netdev->name);
printf("%s: TX timeout\n", name);
}
/* No one cares anyway */
@ -335,26 +353,25 @@ static void reclaim_rx_buffers(struct macb_device *macb,
macb->rx_tail = new_tail;
}
static int macb_recv(struct eth_device *netdev)
static int _macb_recv(struct macb_device *macb, uchar **packetp)
{
struct macb_device *macb = to_macb(netdev);
unsigned int rx_tail = macb->rx_tail;
unsigned int next_rx_tail = macb->next_rx_tail;
void *buffer;
int length;
int wrapped = 0;
u32 status;
macb->wrapped = false;
for (;;) {
macb_invalidate_ring_desc(macb, RX);
if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED))
return -1;
if (!(macb->rx_ring[next_rx_tail].addr & RXADDR_USED))
return -EAGAIN;
status = macb->rx_ring[rx_tail].ctrl;
status = macb->rx_ring[next_rx_tail].ctrl;
if (status & RXBUF_FRAME_START) {
if (rx_tail != macb->rx_tail)
reclaim_rx_buffers(macb, rx_tail);
wrapped = 0;
if (next_rx_tail != macb->rx_tail)
reclaim_rx_buffers(macb, next_rx_tail);
macb->wrapped = false;
}
if (status & RXBUF_FRAME_END) {
@ -362,7 +379,7 @@ static int macb_recv(struct eth_device *netdev)
length = status & RXBUF_FRMLEN_MASK;
macb_invalidate_rx_buffer(macb);
if (wrapped) {
if (macb->wrapped) {
unsigned int headlen, taillen;
headlen = 128 * (MACB_RX_RING_SIZE
@ -372,34 +389,33 @@ static int macb_recv(struct eth_device *netdev)
buffer, headlen);
memcpy((void *)net_rx_packets[0] + headlen,
macb->rx_buffer, taillen);
buffer = (void *)net_rx_packets[0];
*packetp = (void *)net_rx_packets[0];
} else {
*packetp = buffer;
}
net_process_received_packet(buffer, length);
if (++rx_tail >= MACB_RX_RING_SIZE)
rx_tail = 0;
reclaim_rx_buffers(macb, rx_tail);
if (++next_rx_tail >= MACB_RX_RING_SIZE)
next_rx_tail = 0;
macb->next_rx_tail = next_rx_tail;
return length;
} else {
if (++rx_tail >= MACB_RX_RING_SIZE) {
wrapped = 1;
rx_tail = 0;
if (++next_rx_tail >= MACB_RX_RING_SIZE) {
macb->wrapped = true;
next_rx_tail = 0;
}
}
barrier();
}
return 0;
}
static void macb_phy_reset(struct macb_device *macb)
static void macb_phy_reset(struct macb_device *macb, const char *name)
{
struct eth_device *netdev = &macb->netdev;
int i;
u16 status, adv;
adv = ADVERTISE_CSMA | ADVERTISE_ALL;
macb_mdio_write(macb, MII_ADVERTISE, adv);
printf("%s: Starting autonegotiation...\n", netdev->name);
printf("%s: Starting autonegotiation...\n", name);
macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
| BMCR_ANRESTART));
@ -411,10 +427,10 @@ static void macb_phy_reset(struct macb_device *macb)
}
if (status & BMSR_ANEGCOMPLETE)
printf("%s: Autonegotiation complete\n", netdev->name);
printf("%s: Autonegotiation complete\n", name);
else
printf("%s: Autonegotiation timed out (status=0x%04x)\n",
netdev->name, status);
name, status);
}
#ifdef CONFIG_MACB_SEARCH_PHY
@ -441,9 +457,8 @@ static int macb_phy_find(struct macb_device *macb)
#endif /* CONFIG_MACB_SEARCH_PHY */
static int macb_phy_init(struct macb_device *macb)
static int macb_phy_init(struct macb_device *macb, const char *name)
{
struct eth_device *netdev = &macb->netdev;
#ifdef CONFIG_PHYLIB
struct phy_device *phydev;
#endif
@ -452,7 +467,7 @@ static int macb_phy_init(struct macb_device *macb)
int media, speed, duplex;
int i;
arch_get_mdio_control(netdev->name);
arch_get_mdio_control(name);
#ifdef CONFIG_MACB_SEARCH_PHY
/* Auto-detect phy_addr */
if (!macb_phy_find(macb))
@ -462,13 +477,13 @@ static int macb_phy_init(struct macb_device *macb)
/* Check if the PHY is up to snuff... */
phy_id = macb_mdio_read(macb, MII_PHYSID1);
if (phy_id == 0xffff) {
printf("%s: No PHY present\n", netdev->name);
printf("%s: No PHY present\n", name);
return 0;
}
#ifdef CONFIG_PHYLIB
/* need to consider other phy interface mode */
phydev = phy_connect(macb->bus, macb->phy_addr, netdev,
phydev = phy_connect(macb->bus, macb->phy_addr, &macb->netdev,
PHY_INTERFACE_MODE_RGMII);
if (!phydev) {
printf("phy_connect failed\n");
@ -481,7 +496,7 @@ static int macb_phy_init(struct macb_device *macb)
status = macb_mdio_read(macb, MII_BMSR);
if (!(status & BMSR_LSTATUS)) {
/* Try to re-negotiate if we don't have link already. */
macb_phy_reset(macb);
macb_phy_reset(macb, name);
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
status = macb_mdio_read(macb, MII_BMSR);
@ -493,7 +508,7 @@ static int macb_phy_init(struct macb_device *macb)
if (!(status & BMSR_LSTATUS)) {
printf("%s: link down (status: 0x%04x)\n",
netdev->name, status);
name, status);
return 0;
}
@ -505,7 +520,7 @@ static int macb_phy_init(struct macb_device *macb)
duplex = ((lpa & LPA_1000FULL) ? 1 : 0);
printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n",
netdev->name,
name,
duplex ? "full" : "half",
lpa);
@ -530,7 +545,7 @@ static int macb_phy_init(struct macb_device *macb)
? 1 : 0);
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
netdev->name,
name,
speed ? "100" : "10",
duplex ? "full" : "half",
lpa);
@ -570,9 +585,8 @@ static int gmac_init_multi_queues(struct macb_device *macb)
return 0;
}
static int macb_init(struct eth_device *netdev, bd_t *bd)
static int _macb_init(struct macb_device *macb, const char *name)
{
struct macb_device *macb = to_macb(netdev);
unsigned long paddr;
int i;
@ -605,6 +619,7 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
macb->rx_tail = 0;
macb->tx_head = 0;
macb->tx_tail = 0;
macb->next_rx_tail = 0;
macb_writel(macb, RBQP, macb->rx_ring_dma);
macb_writel(macb, TBQP, macb->tx_ring_dma);
@ -641,7 +656,7 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
#endif /* CONFIG_RMII */
}
if (!macb_phy_init(macb))
if (!macb_phy_init(macb, name))
return -1;
/* Enable TX and RX */
@ -650,9 +665,8 @@ static int macb_init(struct eth_device *netdev, bd_t *bd)
return 0;
}
static void macb_halt(struct eth_device *netdev)
static void _macb_halt(struct macb_device *macb)
{
struct macb_device *macb = to_macb(netdev);
u32 ncr, tsr;
/* Halt the controller and wait for any ongoing transmission to end. */
@ -668,17 +682,16 @@ static void macb_halt(struct eth_device *netdev)
macb_writel(macb, NCR, MACB_BIT(CLRSTAT));
}
static int macb_write_hwaddr(struct eth_device *dev)
static int _macb_write_hwaddr(struct macb_device *macb, unsigned char *enetaddr)
{
struct macb_device *macb = to_macb(dev);
u32 hwaddr_bottom;
u16 hwaddr_top;
/* set hardware address */
hwaddr_bottom = dev->enetaddr[0] | dev->enetaddr[1] << 8 |
dev->enetaddr[2] << 16 | dev->enetaddr[3] << 24;
hwaddr_bottom = enetaddr[0] | enetaddr[1] << 8 |
enetaddr[2] << 16 | enetaddr[3] << 24;
macb_writel(macb, SA1B, hwaddr_bottom);
hwaddr_top = dev->enetaddr[4] | dev->enetaddr[5] << 8;
hwaddr_top = enetaddr[4] | enetaddr[5] << 8;
macb_writel(macb, SA1T, hwaddr_top);
return 0;
}
@ -739,21 +752,12 @@ static u32 macb_dbw(struct macb_device *macb)
}
}
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
static void _macb_eth_initialize(struct macb_device *macb)
{
struct macb_device *macb;
struct eth_device *netdev;
int id = 0; /* This is not used by functions we call */
u32 ncfgr;
macb = malloc(sizeof(struct macb_device));
if (!macb) {
printf("Error: Failed to allocate memory for MACB%d\n", id);
return -1;
}
memset(macb, 0, sizeof(struct macb_device));
netdev = &macb->netdev;
/* TODO: we need check the rx/tx_ring_dma is dcache line aligned */
macb->rx_buffer = dma_alloc_coherent(MACB_RX_BUFFER_SIZE,
&macb->rx_buffer_dma);
macb->rx_ring = dma_alloc_coherent(MACB_RX_DMA_DESC_SIZE,
@ -763,7 +767,81 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
macb->dummy_desc = dma_alloc_coherent(MACB_TX_DUMMY_DMA_DESC_SIZE,
&macb->dummy_desc_dma);
/* TODO: we need check the rx/tx_ring_dma is dcache line aligned */
/*
* Do some basic initialization so that we at least can talk
* to the PHY
*/
if (macb_is_gem(macb)) {
ncfgr = gem_mdc_clk_div(id, macb);
ncfgr |= macb_dbw(macb);
} else {
ncfgr = macb_mdc_clk_div(id, macb);
}
macb_writel(macb, NCFGR, ncfgr);
}
#ifndef CONFIG_DM_ETH
static int macb_send(struct eth_device *netdev, void *packet, int length)
{
struct macb_device *macb = to_macb(netdev);
return _macb_send(macb, netdev->name, packet, length);
}
static int macb_recv(struct eth_device *netdev)
{
struct macb_device *macb = to_macb(netdev);
uchar *packet;
int length;
macb->wrapped = false;
for (;;) {
macb->next_rx_tail = macb->rx_tail;
length = _macb_recv(macb, &packet);
if (length >= 0) {
net_process_received_packet(packet, length);
reclaim_rx_buffers(macb, macb->next_rx_tail);
} else if (length < 0) {
return length;
}
}
}
static int macb_init(struct eth_device *netdev, bd_t *bd)
{
struct macb_device *macb = to_macb(netdev);
return _macb_init(macb, netdev->name);
}
static void macb_halt(struct eth_device *netdev)
{
struct macb_device *macb = to_macb(netdev);
return _macb_halt(macb);
}
static int macb_write_hwaddr(struct eth_device *netdev)
{
struct macb_device *macb = to_macb(netdev);
return _macb_write_hwaddr(macb, netdev->enetaddr);
}
int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
{
struct macb_device *macb;
struct eth_device *netdev;
macb = malloc(sizeof(struct macb_device));
if (!macb) {
printf("Error: Failed to allocate memory for MACB%d\n", id);
return -1;
}
memset(macb, 0, sizeof(struct macb_device));
netdev = &macb->netdev;
macb->regs = regs;
macb->phy_addr = phy_addr;
@ -779,18 +857,7 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
netdev->recv = macb_recv;
netdev->write_hwaddr = macb_write_hwaddr;
/*
* Do some basic initialization so that we at least can talk
* to the PHY
*/
if (macb_is_gem(macb)) {
ncfgr = gem_mdc_clk_div(id, macb);
ncfgr |= macb_dbw(macb);
} else {
ncfgr = macb_mdc_clk_div(id, macb);
}
macb_writel(macb, NCFGR, ncfgr);
_macb_eth_initialize(macb);
eth_register(netdev);
@ -800,5 +867,106 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr)
#endif
return 0;
}
#endif /* !CONFIG_DM_ETH */
#ifdef CONFIG_DM_ETH
static int macb_start(struct udevice *dev)
{
struct macb_device *macb = dev_get_priv(dev);
return _macb_init(macb, dev->name);
}
static int macb_send(struct udevice *dev, void *packet, int length)
{
struct macb_device *macb = dev_get_priv(dev);
return _macb_send(macb, dev->name, packet, length);
}
static int macb_recv(struct udevice *dev, int flags, uchar **packetp)
{
struct macb_device *macb = dev_get_priv(dev);
macb->next_rx_tail = macb->rx_tail;
macb->wrapped = false;
return _macb_recv(macb, packetp);
}
static int macb_free_pkt(struct udevice *dev, uchar *packet, int length)
{
struct macb_device *macb = dev_get_priv(dev);
reclaim_rx_buffers(macb, macb->next_rx_tail);
return 0;
}
static void macb_stop(struct udevice *dev)
{
struct macb_device *macb = dev_get_priv(dev);
_macb_halt(macb);
}
static int macb_write_hwaddr(struct udevice *dev)
{
struct eth_pdata *plat = dev_get_platdata(dev);
struct macb_device *macb = dev_get_priv(dev);
return _macb_write_hwaddr(macb, plat->enetaddr);
}
static const struct eth_ops macb_eth_ops = {
.start = macb_start,
.send = macb_send,
.recv = macb_recv,
.stop = macb_stop,
.free_pkt = macb_free_pkt,
.write_hwaddr = macb_write_hwaddr,
};
static int macb_eth_probe(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
struct macb_device *macb = dev_get_priv(dev);
macb->regs = (void *)pdata->iobase;
_macb_eth_initialize(macb);
#if defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
miiphy_register(dev->name, macb_miiphy_read, macb_miiphy_write);
macb->bus = miiphy_get_dev_by_name(dev->name);
#endif
return 0;
}
static int macb_eth_ofdata_to_platdata(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_platdata(dev);
pdata->iobase = dev_get_addr(dev);
return 0;
}
static const struct udevice_id macb_eth_ids[] = {
{ .compatible = "cdns,macb" },
{ }
};
U_BOOT_DRIVER(eth_macb) = {
.name = "eth_macb",
.id = UCLASS_ETH,
.of_match = macb_eth_ids,
.ofdata_to_platdata = macb_eth_ofdata_to_platdata,
.probe = macb_eth_probe,
.ops = &macb_eth_ops,
.priv_auto_alloc_size = sizeof(struct macb_device),
.platdata_auto_alloc_size = sizeof(struct eth_pdata),
};
#endif
#endif

View File

@ -191,16 +191,35 @@ static int atmel_serial_probe(struct udevice *dev)
{
struct atmel_serial_platdata *plat = dev->platdata;
struct atmel_serial_priv *priv = dev_get_priv(dev);
#if CONFIG_IS_ENABLED(OF_CONTROL)
fdt_addr_t addr_base;
addr_base = dev_get_addr(dev);
if (addr_base == FDT_ADDR_T_NONE)
return -ENODEV;
plat->base_addr = (uint32_t)addr_base;
#endif
priv->usart = (atmel_usart3_t *)plat->base_addr;
atmel_serial_init_internal(priv->usart);
return 0;
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
static const struct udevice_id atmel_serial_ids[] = {
{ .compatible = "atmel,at91sam9260-usart" },
{ }
};
#endif
U_BOOT_DRIVER(serial_atmel) = {
.name = "serial_atmel",
.id = UCLASS_SERIAL,
#if CONFIG_IS_ENABLED(OF_CONTROL)
.of_match = atmel_serial_ids,
.platdata_auto_alloc_size = sizeof(struct atmel_serial_platdata),
#endif
.probe = atmel_serial_probe,
.ops = &atmel_serial_ops,
.flags = DM_FLAG_PRE_RELOC,

View File

@ -7,6 +7,10 @@
*/
#include <common.h>
#include <atmel_lcd.h>
#include <dm.h>
#include <fdtdec.h>
#include <video.h>
#include <asm/io.h>
#include <asm/arch/gpio.h>
#include <asm/arch/clk.h>
@ -14,6 +18,21 @@
#include <bmp_layout.h>
#include <atmel_lcdc.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_DM_VIDEO
enum {
/* Maximum LCD size we support */
LCD_MAX_WIDTH = 1366,
LCD_MAX_HEIGHT = 768,
LCD_MAX_LOG2_BPP = VIDEO_BPP16,
};
#endif
struct atmel_fb_priv {
struct display_timing timing;
};
/* configurable parameters */
#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
#define ATMEL_LCDC_DMA_BURST_LEN 8
@ -30,6 +49,7 @@
#define lcdc_readl(mmio, reg) __raw_readl((mmio)+(reg))
#define lcdc_writel(mmio, reg, val) __raw_writel((val), (mmio)+(reg))
#ifndef CONFIG_DM_VIDEO
ushort *configuration_get_cmap(void)
{
return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0));
@ -90,40 +110,43 @@ void lcd_set_cmap(struct bmp_image *bmp, unsigned colors)
lcd_setcolreg(i, cte.red, cte.green, cte.blue);
}
}
#endif
void lcd_ctrl_init(void *lcdbase)
static void atmel_fb_init(ulong addr, struct display_timing *timing, int bpix,
bool tft, bool cont_pol_low, ulong lcdbase)
{
unsigned long value;
void *reg = (void *)addr;
/* Turn off the LCD controller and the DMA controller */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_PWRCON,
lcdc_writel(reg, ATMEL_LCDC_PWRCON,
ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET);
/* Wait for the LCDC core to become idle */
while (lcdc_readl(panel_info.mmio, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
while (lcdc_readl(reg, ATMEL_LCDC_PWRCON) & ATMEL_LCDC_BUSY)
udelay(10);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMACON, 0);
lcdc_writel(reg, ATMEL_LCDC_DMACON, 0);
/* Reset LCDC DMA */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMARST);
lcdc_writel(reg, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMARST);
/* ...set frame size and burst length = 8 words (?) */
value = (panel_info.vl_col * panel_info.vl_row *
NBITS(panel_info.vl_bpix)) / 32;
value = (timing->hactive.typ * timing->vactive.typ *
(1 << bpix)) / 32;
value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMAFRMCFG, value);
lcdc_writel(reg, ATMEL_LCDC_DMAFRMCFG, value);
/* Set pixel clock */
value = get_lcdc_clk_rate(0) / panel_info.vl_clk;
if (get_lcdc_clk_rate(0) % panel_info.vl_clk)
value = get_lcdc_clk_rate(0) / timing->pixelclock.typ;
if (get_lcdc_clk_rate(0) % timing->pixelclock.typ)
value++;
value = (value / 2) - 1;
if (!value) {
lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
lcdc_writel(reg, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
} else
lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON1,
lcdc_writel(reg, ATMEL_LCDC_LCDCON1,
value << ATMEL_LCDC_CLKVAL_OFFSET);
/* Initialize control register 2 */
@ -132,58 +155,160 @@ void lcd_ctrl_init(void *lcdbase)
#else
value = ATMEL_LCDC_MEMOR_LITTLE | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE;
#endif
if (panel_info.vl_tft)
if (tft)
value |= ATMEL_LCDC_DISTYPE_TFT;
value |= panel_info.vl_sync;
value |= (panel_info.vl_bpix << 5);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDCON2, value);
if (!(timing->flags & DISPLAY_FLAGS_HSYNC_HIGH))
value |= ATMEL_LCDC_INVLINE_INVERTED;
if (!(timing->flags & DISPLAY_FLAGS_VSYNC_HIGH))
value |= ATMEL_LCDC_INVFRAME_INVERTED;
value |= bpix << 5;
lcdc_writel(reg, ATMEL_LCDC_LCDCON2, value);
/* Vertical timing */
value = (panel_info.vl_vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
value |= panel_info.vl_upper_margin << ATMEL_LCDC_VBP_OFFSET;
value |= panel_info.vl_lower_margin;
lcdc_writel(panel_info.mmio, ATMEL_LCDC_TIM1, value);
value = (timing->vsync_len.typ - 1) << ATMEL_LCDC_VPW_OFFSET;
value |= timing->vback_porch.typ << ATMEL_LCDC_VBP_OFFSET;
value |= timing->vfront_porch.typ;
/* Magic! (Datasheet says "Bit 31 must be written to 1") */
value |= 1U << 31;
lcdc_writel(reg, ATMEL_LCDC_TIM1, value);
/* Horizontal timing */
value = (panel_info.vl_right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
value |= (panel_info.vl_hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
value |= (panel_info.vl_left_margin - 1);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_TIM2, value);
value = (timing->hfront_porch.typ - 1) << ATMEL_LCDC_HFP_OFFSET;
value |= (timing->hsync_len.typ - 1) << ATMEL_LCDC_HPW_OFFSET;
value |= (timing->hback_porch.typ - 1);
lcdc_writel(reg, ATMEL_LCDC_TIM2, value);
/* Display size */
value = (panel_info.vl_col - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
value |= panel_info.vl_row - 1;
lcdc_writel(panel_info.mmio, ATMEL_LCDC_LCDFRMCFG, value);
value = (timing->hactive.typ - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
value |= timing->vactive.typ - 1;
lcdc_writel(reg, ATMEL_LCDC_LCDFRMCFG, value);
/* FIFO Threshold: Use formula from data sheet */
value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_FIFO, value);
lcdc_writel(reg, ATMEL_LCDC_FIFO, value);
/* Toggle LCD_MODE every frame */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_MVAL, 0);
lcdc_writel(reg, ATMEL_LCDC_MVAL, 0);
/* Disable all interrupts */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_IDR, ~0UL);
lcdc_writel(reg, ATMEL_LCDC_IDR, ~0UL);
/* Set contrast */
value = ATMEL_LCDC_PS_DIV8 |
ATMEL_LCDC_ENA_PWMENABLE;
if (!panel_info.vl_cont_pol_low)
if (!cont_pol_low)
value |= ATMEL_LCDC_POL_POSITIVE;
lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_CTR, value);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
lcdc_writel(reg, ATMEL_LCDC_CONTRAST_CTR, value);
lcdc_writel(reg, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
/* Set framebuffer DMA base address and pixel offset */
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMABADDR1, (u_long)lcdbase);
lcdc_writel(reg, ATMEL_LCDC_DMABADDR1, lcdbase);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMAEN);
lcdc_writel(panel_info.mmio, ATMEL_LCDC_PWRCON,
lcdc_writel(reg, ATMEL_LCDC_DMACON, ATMEL_LCDC_DMAEN);
lcdc_writel(reg, ATMEL_LCDC_PWRCON,
(ATMEL_LCDC_GUARD_TIME << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
}
#ifndef CONFIG_DM_VIDEO
void lcd_ctrl_init(void *lcdbase)
{
struct display_timing timing;
timing.flags = 0;
if (!(panel_info.vl_sync & ATMEL_LCDC_INVLINE_INVERTED))
timing.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
if (!(panel_info.vl_sync & ATMEL_LCDC_INVFRAME_INVERTED))
timing.flags |= DISPLAY_FLAGS_VSYNC_LOW;
timing.pixelclock.typ = panel_info.vl_clk;
timing.hactive.typ = panel_info.vl_col;
timing.hfront_porch.typ = panel_info.vl_right_margin;
timing.hback_porch.typ = panel_info.vl_left_margin;
timing.hsync_len.typ = panel_info.vl_hsync_len;
timing.vactive.typ = panel_info.vl_row;
timing.vfront_porch.typ = panel_info.vl_clk;
timing.vback_porch.typ = panel_info.vl_clk;
timing.vsync_len.typ = panel_info.vl_clk;
atmel_fb_init(panel_info.mmio, &timing, panel_info.vl_bpix,
panel_info.vl_tft, panel_info.vl_cont_pol_low,
(ulong)lcdbase);
}
ulong calc_fbsize(void)
{
return ((panel_info.vl_col * panel_info.vl_row *
NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE;
}
#endif
#ifdef CONFIG_DM_VIDEO
static int atmel_fb_lcd_probe(struct udevice *dev)
{
struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
struct atmel_fb_priv *priv = dev_get_priv(dev);
struct display_timing *timing = &priv->timing;
/*
* For now some values are hard-coded. We could use the device tree
* bindings in simple-framebuffer.txt to specify the format/bpp and
* some Atmel-specific binding for tft and cont_pol_low.
*/
atmel_fb_init(ATMEL_BASE_LCDC, timing, VIDEO_BPP16, true, false,
uc_plat->base);
uc_priv->xsize = timing->hactive.typ;
uc_priv->ysize = timing->vactive.typ;
uc_priv->bpix = VIDEO_BPP16;
video_set_flush_dcache(dev, true);
debug("LCD frame buffer at %lx, size %x, %dx%d pixels\n", uc_plat->base,
uc_plat->size, uc_priv->xsize, uc_priv->ysize);
return 0;
}
static int atmel_fb_ofdata_to_platdata(struct udevice *dev)
{
struct atmel_lcd_platdata *plat = dev_get_platdata(dev);
struct atmel_fb_priv *priv = dev_get_priv(dev);
struct display_timing *timing = &priv->timing;
const void *blob = gd->fdt_blob;
if (fdtdec_decode_display_timing(blob, dev->of_offset,
plat->timing_index, timing)) {
debug("%s: Failed to decode display timing\n", __func__);
return -EINVAL;
}
return 0;
}
static int atmel_fb_lcd_bind(struct udevice *dev)
{
struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
(1 << VIDEO_BPP16) / 8;
debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
return 0;
}
static const struct udevice_id atmel_fb_lcd_ids[] = {
{ .compatible = "atmel,at91sam9g45-lcdc" },
{ }
};
U_BOOT_DRIVER(atmel_fb) = {
.name = "atmel_fb",
.id = UCLASS_VIDEO,
.of_match = atmel_fb_lcd_ids,
.bind = atmel_fb_lcd_bind,
.ofdata_to_platdata = atmel_fb_ofdata_to_platdata,
.probe = atmel_fb_lcd_probe,
.platdata_auto_alloc_size = sizeof(struct atmel_lcd_platdata),
.priv_auto_alloc_size = sizeof(struct atmel_fb_priv),
};
#endif

View File

@ -10,6 +10,15 @@
#ifndef _ATMEL_LCD_H_
#define _ATMEL_LCD_H_
/**
* struct atmel_lcd_platdata - platform data for Atmel LCDs with driver model
*
* @timing_index: Index of LCD timing to use in device tree node
*/
struct atmel_lcd_platdata {
int timing_index;
};
typedef struct vidinfo {
ushort vl_col; /* Number of columns (i.e. 640) */
ushort vl_row; /* Number of rows (i.e. 480) */

View File

@ -0,0 +1,155 @@
/*
* Bluewater Systems Snapper 9G45 module
*
* (C) Copyright 2011 Bluewater Systems
* Author: Andre Renaud <andre@bluewatersys.com>
* Author: Ryan Mallon <ryan@bluewatersys.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/* SoC type is defined in boards.cfg */
#include <asm/hardware.h>
#include <linux/sizes.h>
#define CONFIG_SYS_TEXT_BASE 0x73f00000
/* ARM asynchronous clock */
#define CONFIG_SYS_AT91_MAIN_CLOCK 12000000 /* from 12 MHz crystal */
#define CONFIG_SYS_AT91_SLOW_CLOCK 32768
/* CPU */
#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_INITRD_TAG
#define CONFIG_SKIP_LOWLEVEL_INIT_ONLY
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_BOARD_LATE_INIT
/* SDRAM */
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_SYS_SDRAM_BASE ATMEL_BASE_CS6
#define CONFIG_SYS_SDRAM_SIZE (128 * 1024 * 1024) /* 64MB */
#define CONFIG_SYS_INIT_SP_ADDR (ATMEL_BASE_SRAM + 0x1000 - \
GENERATED_GBL_DATA_SIZE)
/* Mem test settings */
#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + (1024 * 1024))
/* NAND Flash */
#define CONFIG_NAND_ATMEL
#define CONFIG_ATMEL_NAND_HWECC
#define CONFIG_SYS_NAND_ECC_BASE ATMEL_BASE_ECC
#define CONFIG_SYS_NO_FLASH
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE ATMEL_BASE_CS3
#define CONFIG_SYS_NAND_DBW_8
#define CONFIG_SYS_NAND_MASK_ALE (1 << 21) /* AD21 */
#define CONFIG_SYS_NAND_MASK_CLE (1 << 22) /* AD22 */
#define CONFIG_SYS_NAND_ENABLE_PIN AT91_PIN_PC14
#define CONFIG_SYS_NAND_READY_PIN AT91_PIN_PC8
/* Ethernet */
#define CONFIG_MACB
#define CONFIG_RMII
#define CONFIG_NET_RETRY_COUNT 20
#define CONFIG_RESET_PHY_R
#define CONFIG_AT91_WANTS_COMMON_PHY
#define CONFIG_TFTP_PORT
#define CONFIG_TFTP_TSIZE
/* USB */
#define CONFIG_USB_EHCI
#define CONFIG_USB_EHCI_ATMEL
#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 2
#define CONFIG_DOS_PARTITION
#define CONFIG_USB_STORAGE
#define CONFIG_PARTITION_UUIDS
/* MMC */
#define CONFIG_MMC
#define CONFIG_GENERIC_MMC
#define CONFIG_GENERIC_ATMEL_MCI
/* LCD */
#define CONFIG_ATMEL_LCD
#define CONFIG_CONSOLE_MUX
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
#define CONFIG_GURNARD_SPLASH
#define CONFIG_ATMEL_SPI
/* GPIOs and IO expander */
#define CONFIG_ATMEL_LEGACY
#define CONFIG_AT91_GPIO
#define CONFIG_AT91_GPIO_PULLUP 1
/* UARTs/Serial console */
#define CONFIG_ATMEL_USART
#define CONFIG_BAUDRATE 115200
/* Boot options */
#define CONFIG_SYS_LOAD_ADDR 0x23000000
#define CONFIG_ZERO_BOOTDELAY_CHECK
#define CONFIG_BOOTP_BOOTFILESIZE
#define CONFIG_BOOTP_BOOTPATH
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME
/* Environment settings */
#define CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET (512 << 10)
#define CONFIG_ENV_SIZE (256 << 10)
#define CONFIG_ENV_OVERWRITE
#define CONFIG_EXTRA_ENV_SETTINGS \
"ethaddr=00:00:00:00:00:00\0" \
"serial=0\0" \
"stdout=serial_atmel\0" \
"stderr=serial_atmel\0" \
"stdin=serial_atmel\0" \
"bootlimit=3\0" \
"loadaddr=0x71000000\0" \
"board_rev=2\0" \
"bootfile=/tftpboot/uImage\0" \
"bootargs_def=console=ttyS0,115200 panic=5 quiet lpj=997376\0" \
"nfsroot=/export/root\0" \
"boot_working=setenv bootargs $bootargs_def; nboot $loadaddr 0 0x20c0000 && bootm\0" \
"boot_safe=setenv bootargs $bootargs_def; nboot $loadaddr 0 0xc0000 && bootm\0" \
"boot_tftp=setenv bootargs $bootargs_def ip=any nfsroot=$nfsroot; setenv autoload y && bootp && bootm\0" \
"boot_usb=setenv bootargs $bootargs_def; usb start && usb storage && fatload usb 0:1 $loadaddr dds-xm200.bin && bootm\0" \
"boot_mmc=setenv bootargs $bootargs_def; mmc rescan && fatload mmc 0:1 $loadaddr dds-xm200.bin && bootm\0" \
"bootcmd=run boot_mmc ; run boot_usb ; run boot_working ; run boot_safe\0" \
"altbootcmd=run boot_mmc ; run boot_usb ; run boot_safe ; run boot_working\0"
/* Console settings */
#define CONFIG_SYS_CBSIZE 256
#define CONFIG_SYS_MAXARGS 16
#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \
sizeof(CONFIG_SYS_PROMPT) + 16)
#define CONFIG_SYS_LONGHELP
#define CONFIG_CMDLINE_EDITING
#define CONFIG_AUTO_COMPLETE
#define CONFIG_SYS_HUSH_PARSER
/* U-Boot memory settings */
#define CONFIG_SYS_MALLOC_LEN (1 << 20)
/* Command line configuration */
#define CONFIG_CMD_PING
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_FAT
#define CONFIG_CMD_USB
#define CONFIG_CMD_MII
#define CONFIG_CMD_MMC
#define CONFIG_CMD_NAND
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_PART
#endif /* __CONFIG_H */

View File

@ -0,0 +1,23 @@
/*
* This header provides constants for AT91 pmc status.
*
* The constants defined in this header are being used in dts.
*
* Licensed under GPLv2 or later.
*/
#ifndef _DT_BINDINGS_CLK_AT91_H
#define _DT_BINDINGS_CLK_AT91_H
#define AT91_PMC_MOSCS 0 /* MOSCS Flag */
#define AT91_PMC_LOCKA 1 /* PLLA Lock */
#define AT91_PMC_LOCKB 2 /* PLLB Lock */
#define AT91_PMC_MCKRDY 3 /* Master Clock */
#define AT91_PMC_LOCKU 6 /* UPLL Lock */
#define AT91_PMC_PCKRDY(id) (8 + (id)) /* Programmable Clock */
#define AT91_PMC_MOSCSELS 16 /* Main Oscillator Selection */
#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */
#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */
#define AT91_PMC_GCKRDY 24 /* Generated Clocks */
#endif

View File

@ -0,0 +1,52 @@
/*
* This header provides macros for at91 dma bindings.
*
* Copyright (C) 2013 Ludovic Desroches <ludovic.desroches@atmel.com>
*
* GPLv2 only
*/
#ifndef __DT_BINDINGS_AT91_DMA_H__
#define __DT_BINDINGS_AT91_DMA_H__
/* ---------- HDMAC ---------- */
/*
* Source and/or destination peripheral ID
*/
#define AT91_DMA_CFG_PER_ID_MASK (0xff)
#define AT91_DMA_CFG_PER_ID(id) (id & AT91_DMA_CFG_PER_ID_MASK)
/*
* FIFO configuration: it defines when a request is serviced.
*/
#define AT91_DMA_CFG_FIFOCFG_OFFSET (8)
#define AT91_DMA_CFG_FIFOCFG_MASK (0xf << AT91_DMA_CFG_FIFOCFG_OFFSET)
#define AT91_DMA_CFG_FIFOCFG_HALF (0x0 << AT91_DMA_CFG_FIFOCFG_OFFSET) /* half FIFO (default behavior) */
#define AT91_DMA_CFG_FIFOCFG_ALAP (0x1 << AT91_DMA_CFG_FIFOCFG_OFFSET) /* largest defined AHB burst */
#define AT91_DMA_CFG_FIFOCFG_ASAP (0x2 << AT91_DMA_CFG_FIFOCFG_OFFSET) /* single AHB access */
/* ---------- XDMAC ---------- */
#define AT91_XDMAC_DT_MEM_IF_MASK (0x1)
#define AT91_XDMAC_DT_MEM_IF_OFFSET (13)
#define AT91_XDMAC_DT_MEM_IF(mem_if) (((mem_if) & AT91_XDMAC_DT_MEM_IF_MASK) \
<< AT91_XDMAC_DT_MEM_IF_OFFSET)
#define AT91_XDMAC_DT_GET_MEM_IF(cfg) (((cfg) >> AT91_XDMAC_DT_MEM_IF_OFFSET) \
& AT91_XDMAC_DT_MEM_IF_MASK)
#define AT91_XDMAC_DT_PER_IF_MASK (0x1)
#define AT91_XDMAC_DT_PER_IF_OFFSET (14)
#define AT91_XDMAC_DT_PER_IF(per_if) (((per_if) & AT91_XDMAC_DT_PER_IF_MASK) \
<< AT91_XDMAC_DT_PER_IF_OFFSET)
#define AT91_XDMAC_DT_GET_PER_IF(cfg) (((cfg) >> AT91_XDMAC_DT_PER_IF_OFFSET) \
& AT91_XDMAC_DT_PER_IF_MASK)
#define AT91_XDMAC_DT_PERID_MASK (0x7f)
#define AT91_XDMAC_DT_PERID_OFFSET (24)
#define AT91_XDMAC_DT_PERID(perid) (((perid) & AT91_XDMAC_DT_PERID_MASK) \
<< AT91_XDMAC_DT_PERID_OFFSET)
#define AT91_XDMAC_DT_GET_PERID(cfg) (((cfg) >> AT91_XDMAC_DT_PERID_OFFSET) \
& AT91_XDMAC_DT_PERID_MASK)
#endif /* __DT_BINDINGS_AT91_DMA_H__ */

View File

@ -0,0 +1,40 @@
/*
* This header provides constants for most at91 pinctrl bindings.
*
* Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* GPLv2 only
*/
#ifndef __DT_BINDINGS_AT91_PINCTRL_H__
#define __DT_BINDINGS_AT91_PINCTRL_H__
#define AT91_PINCTRL_NONE (0 << 0)
#define AT91_PINCTRL_PULL_UP (1 << 0)
#define AT91_PINCTRL_MULTI_DRIVE (1 << 1)
#define AT91_PINCTRL_DEGLITCH (1 << 2)
#define AT91_PINCTRL_PULL_DOWN (1 << 3)
#define AT91_PINCTRL_DIS_SCHMIT (1 << 4)
#define AT91_PINCTRL_DEBOUNCE (1 << 16)
#define AT91_PINCTRL_DEBOUNCE_VAL(x) (x << 17)
#define AT91_PINCTRL_PULL_UP_DEGLITCH (AT91_PINCTRL_PULL_UP | AT91_PINCTRL_DEGLITCH)
#define AT91_PINCTRL_DRIVE_STRENGTH_DEFAULT (0x0 << 5)
#define AT91_PINCTRL_DRIVE_STRENGTH_LOW (0x1 << 5)
#define AT91_PINCTRL_DRIVE_STRENGTH_MED (0x2 << 5)
#define AT91_PINCTRL_DRIVE_STRENGTH_HI (0x3 << 5)
#define AT91_PIOA 0
#define AT91_PIOB 1
#define AT91_PIOC 2
#define AT91_PIOD 3
#define AT91_PIOE 4
#define AT91_PERIPH_GPIO 0
#define AT91_PERIPH_A 1
#define AT91_PERIPH_B 2
#define AT91_PERIPH_C 3
#define AT91_PERIPH_D 4
#endif /* __DT_BINDINGS_AT91_PINCTRL_H__ */

View File

@ -25,6 +25,8 @@ extern struct p_current *current;
printf(fmt, ##args)
#define dev_err(dev, fmt, args...) \
printf(fmt, ##args)
#define dev_warn(dev, fmt, args...) \
printf(fmt, ##args)
#define printk printf
#define printk_once printf

View File

@ -1170,7 +1170,7 @@ int fdtdec_decode_display_timing(const void *blob, int parent, int index,
if (fdtdec_get_bool(blob, node, "doubleclk"))
dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
return 0;
return ret;
}
int fdtdec_setup(void)

View File

@ -673,6 +673,15 @@ static int bootp_extended(u8 *e)
*e++ = 255; /* End of the list */
/*
* If nothing in list, remove it altogether. Some DHCP servers get
* upset by this minor faux pas and do not respond at all.
*/
if (e == start + 3) {
printf("*** Warning: no DHCP options requested\n");
e -= 3;
}
return e - start;
}
#endif