lpc32xx: add support for board work_92105

Work_92105 from Work Microwave is an LPC3250-
based board with the following features:
- 64MB or 128MB SDR DRAM
- 1 GB SLC NAND, managed through MLC controller.
- Ethernet
- Ethernet + PHY SMSC8710
- I2C:
  - EEPROM (24M01-compatible)
  - RTC (DS1374-compatible)
  - Temperature sensor (DS620)
  - DACs (2 x MAX518)
- SPI (through SSP interface)
  - Port expander MAX6957
- LCD display (HD44780-compatible), controlled
  through the port expander and DACs

This board has SPL support, and uses the LPC32XX boot
image format.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
master
Albert ARIBAUD \(3ADEV\) 9 years ago committed by Albert ARIBAUD
parent 8c80eb3b53
commit 412ae53aad
  1. 20
      Makefile
  2. 6
      arch/arm/Kconfig
  3. 2
      arch/arm/cpu/arm926ejs/lpc32xx/Makefile
  4. 34
      arch/arm/cpu/arm926ejs/lpc32xx/clk.c
  5. 1
      arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
  6. 77
      arch/arm/cpu/arm926ejs/lpc32xx/dram.c
  7. 45
      arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
  8. 5
      arch/arm/include/asm/arch-lpc32xx/clk.h
  9. 1
      arch/arm/include/asm/arch-lpc32xx/cpu.h
  10. 21
      arch/arm/include/asm/arch-lpc32xx/emc.h
  11. 18
      arch/arm/include/asm/arch-lpc32xx/mux.h
  12. 6
      arch/arm/include/asm/arch-lpc32xx/sys_proto.h
  13. 15
      board/work-microwave/work_92105/Kconfig
  14. 6
      board/work-microwave/work_92105/MAINTAINERS
  15. 10
      board/work-microwave/work_92105/Makefile
  16. 91
      board/work-microwave/work_92105/README
  17. 77
      board/work-microwave/work_92105/work_92105.c
  18. 349
      board/work-microwave/work_92105/work_92105_display.c
  19. 14
      board/work-microwave/work_92105/work_92105_display.h
  20. 85
      board/work-microwave/work_92105/work_92105_spl.c
  21. 6
      configs/work_92105_defconfig
  22. 241
      include/configs/work_92105.h

@ -909,6 +909,26 @@ OBJCOPYFLAGS_u-boot-with-spl.bin = -I binary -O binary \
u-boot-with-spl.bin: spl/u-boot-spl.bin $(SPL_PAYLOAD) FORCE
$(call if_changed,pad_cat)
MKIMAGEFLAGS_lpc32xx-spl.img = -T lpc32xximage -a $(CONFIG_SPL_TEXT_BASE)
lpc32xx-spl.img: spl/u-boot-spl.bin FORCE
$(call if_changed,mkimage)
OBJCOPYFLAGS_lpc32xx-boot-0.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO)
lpc32xx-boot-0.bin: lpc32xx-spl.img
$(call if_changed,objcopy)
OBJCOPYFLAGS_lpc32xx-boot-1.bin = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO)
lpc32xx-boot-1.bin: lpc32xx-spl.img
$(call if_changed,objcopy)
lpc32xx-full.bin: lpc32xx-boot-0.bin lpc32xx-boot-1.bin u-boot.img
$(call if_changed,cat)
CLEAN_FILES += lpc32xx-*
OBJCOPYFLAGS_u-boot-with-tpl.bin = -I binary -O binary \
--pad-to=$(CONFIG_TPL_PAD_TO)
tpl/u-boot-with-tpl.bin: tpl/u-boot-tpl.bin u-boot.bin FORCE

@ -132,6 +132,11 @@ config TARGET_DEVKIT3250
bool "Support devkit3250"
select CPU_ARM926EJS
config TARGET_WORK_92105
bool "Support work_92105"
select CPU_ARM926EJS
select SUPPORT_SPL
config TARGET_MX25PDK
bool "Support mx25pdk"
select CPU_ARM926EJS
@ -872,6 +877,7 @@ source "board/vpac270/Kconfig"
source "board/wandboard/Kconfig"
source "board/warp/Kconfig"
source "board/woodburn/Kconfig"
source "board/work-microwave/work_92105/Kconfig"
source "board/xaeniax/Kconfig"
source "board/xilinx/zynqmp/Kconfig"
source "board/zipitz2/Kconfig"

@ -6,3 +6,5 @@
#
obj-y = cpu.o clk.o devices.o timer.o
obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o

@ -98,6 +98,40 @@ unsigned int get_periph_clk_rate(void)
return get_hclk_pll_rate() / get_periph_clk_div();
}
unsigned int get_sdram_clk_rate(void)
{
unsigned int src_clk;
if (!(readl(&clk->pwr_ctrl) & CLK_PWR_NORMAL_RUN))
return get_sys_clk_rate();
src_clk = get_hclk_pll_rate();
if (readl(&clk->sdramclk_ctrl) & CLK_SDRAM_DDR_SEL) {
/* using DDR */
switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_DDRAM_MASK) {
case CLK_HCLK_DDRAM_HALF:
return src_clk/2;
case CLK_HCLK_DDRAM_NOMINAL:
return src_clk;
default:
return 0;
}
} else {
/* using SDR */
switch (readl(&clk->hclkdiv_ctrl) & CLK_HCLK_ARM_PLL_DIV_MASK) {
case CLK_HCLK_ARM_PLL_DIV_4:
return src_clk/4;
case CLK_HCLK_ARM_PLL_DIV_2:
return src_clk/2;
case CLK_HCLK_ARM_PLL_DIV_1:
return src_clk;
default:
return 0;
}
}
}
int get_serial_clock(void)
{
return get_periph_clk_rate();

@ -9,6 +9,7 @@
#include <asm/arch/cpu.h>
#include <asm/arch/clk.h>
#include <asm/arch/wdt.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;

@ -0,0 +1,77 @@
/*
* LPC32xx dram init
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* This is called by SPL to gain access to the SDR DRAM.
*
* This code runs from SRAM.
*
* Actual CONFIG_LPC32XX_SDRAM_* parameters must be provided
* by the board configuration file.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <netdev.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clk.h>
#include <asm/arch/wdt.h>
#include <asm/arch/emc.h>
#include <asm/io.h>
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
static struct emc_regs *emc = (struct emc_regs *)EMC_BASE;
void ddr_init(struct emc_dram_settings *dram)
{
uint32_t ck;
/* Enable EMC interface and choose little endian mode */
writel(1, &emc->ctrl);
writel(0, &emc->config);
/* Select maximum EMC Dynamic Memory Refresh Time */
writel(0x7FF, &emc->refresh);
/* Determine CLK */
ck = get_sdram_clk_rate();
/* Configure SDRAM */
writel(dram->cmddelay, &clk->sdramclk_ctrl);
writel(dram->config0, &emc->config0);
writel(dram->rascas0, &emc->rascas0);
writel(dram->rdconfig, &emc->read_config);
/* Set timings */
writel((ck / dram->trp) & 0x0000000F, &emc->t_rp);
writel((ck / dram->tras) & 0x0000000F, &emc->t_ras);
writel((ck / dram->tsrex) & 0x0000007F, &emc->t_srex);
writel((ck / dram->twr) & 0x0000000F, &emc->t_wr);
writel((ck / dram->trc) & 0x0000001F, &emc->t_rc);
writel((ck / dram->trfc) & 0x0000001F, &emc->t_rfc);
writel((ck / dram->txsr) & 0x000000FF, &emc->t_xsr);
writel(dram->trrd, &emc->t_rrd);
writel(dram->tmrd, &emc->t_mrd);
writel(dram->tcdlr, &emc->t_cdlr);
/* Dynamic refresh */
writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh);
udelay(10);
/* Force all clocks, enable inverted ck, issue NOP command */
writel(0x00000193, &emc->control);
udelay(100);
/* Keep all clocks enabled, issue a PRECHARGE ALL command */
writel(0x00000113, &emc->control);
/* Fast dynamic refresh for at least a few SDRAM ck cycles */
writel((((128) >> 4) & 0x7FF), &emc->refresh);
udelay(10);
/* set correct dynamic refresh timing */
writel((((ck / dram->refresh) >> 4) & 0x7FF), &emc->refresh);
udelay(10);
/* set normal mode to CAS=3 */
writel(0x00000093, &emc->control);
readl(EMC_DYCS0_BASE | dram->mode);
/* set extended mode to all zeroes */
writel(0x00000093, &emc->control);
readl(EMC_DYCS0_BASE | dram->emode);
/* stop forcing clocks, keep inverted clock, issue normal mode */
writel(0x00000010, &emc->control);
}

@ -0,0 +1,45 @@
/*
* WORK Microwave work_92105 board low level init
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* Low level init is called from SPL to set up the clocks.
* On entry, the LPC3250 is in Direct Run mode with all clocks
* running at 13 MHz; on exit, ARM clock is 208 MHz, HCLK is
* 104 MHz and PCLK is 13 MHz.
*
* This code must run from SRAM so that the clock changes do
* not prevent it from executing.
*
* SPDX-License-Identifier: GPL-2.0+
*/
.globl lowlevel_init
lowlevel_init:
/* Set ARM, HCLK, PCLK dividers for normal mode */
ldr r0, =0x0000003D
ldr r1, =0x40004040
str r0, [r1]
/* Start HCLK PLL for 208 MHz */
ldr r0, =0x0001401E
ldr r1, =0x40004058
str r0, [r1]
/* wait for HCLK PLL to lock */
1:
ldr r0, [r1]
ands r0, r0, #1
beq 1b
/* switch to normal mode */
ldr r1, =0x40004044
ldr r0, [r1]
orr r0, #0x00000004
str r0, [r1]
/* Return to U-boot via saved link register */
mov pc, lr

@ -71,6 +71,7 @@ struct clk_pm_regs {
};
/* HCLK Divider Control Register bits */
#define CLK_HCLK_DDRAM_MASK (0x3 << 7)
#define CLK_HCLK_DDRAM_HALF (0x2 << 7)
#define CLK_HCLK_DDRAM_NOMINAL (0x1 << 7)
#define CLK_HCLK_DDRAM_STOPPED (0x0 << 7)
@ -158,11 +159,15 @@ struct clk_pm_regs {
/* SSP Clock Control Register bits */
#define CLK_SSP0_ENABLE_CLOCK (1 << 0)
/* SDRAMCLK register bits */
#define CLK_SDRAM_DDR_SEL (1 << 1)
unsigned int get_sys_clk_rate(void);
unsigned int get_hclk_pll_rate(void);
unsigned int get_hclk_clk_div(void);
unsigned int get_hclk_clk_rate(void);
unsigned int get_periph_clk_div(void);
unsigned int get_periph_clk_rate(void);
unsigned int get_sdram_clk_rate(void);
#endif /* _LPC32XX_CLK_H */

@ -27,6 +27,7 @@
#define HS_UART7_BASE 0x4001C000 /* High speed UART 7 registers base */
#define RTC_BASE 0x40024000 /* RTC registers base */
#define GPIO_BASE 0x40028000 /* GPIO registers base */
#define MUX_BASE 0x40028100 /* MUX registers base */
#define WDT_BASE 0x4003C000 /* Watchdog timer registers base */
#define TIMER0_BASE 0x40044000 /* Timer0 registers base */
#define TIMER1_BASE 0x4004C000 /* Timer1 registers base */

@ -76,4 +76,25 @@ struct emc_regs {
#define EMC_STAT_WAITWR(n) (((n) - 2) & 0x1F)
#define EMC_STAT_WAITTURN(n) (((n) - 1) & 0x0F)
/* EMC settings for DRAM */
struct emc_dram_settings {
u32 cmddelay;
u32 config0;
u32 rascas0;
u32 rdconfig;
u32 trp;
u32 tras;
u32 tsrex;
u32 twr;
u32 trc;
u32 trfc;
u32 txsr;
u32 trrd;
u32 tmrd;
u32 tcdlr;
u32 refresh;
u32 mode;
u32 emode;
};
#endif /* _LPC32XX_EMC_H */

@ -0,0 +1,18 @@
/*
* LPC32xx MUX interface
*
* (C) Copyright 2015 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* SPDX-License-Identifier: GPL-2.0+
*/
/**
* MUX register map for LPC32xx
*/
struct mux_regs {
u32 p_mux_set;
u32 p_mux_clr;
u32 p_mux_state;
};

@ -7,10 +7,14 @@
#ifndef _LPC32XX_SYS_PROTO_H
#define _LPC32XX_SYS_PROTO_H
#include <asm/arch/emc.h>
void lpc32xx_uart_init(unsigned int uart_id);
void lpc32xx_mac_init(void);
void lpc32xx_mlc_nand_init(void);
void lpc32xx_i2c_init(unsigned int devnum);
void lpc32xx_ssp_init(void);
#if defined(CONFIG_SPL_BUILD)
void ddr_init(const struct emc_dram_settings *dram);
#endif
#endif /* _LPC32XX_SYS_PROTO_H */

@ -0,0 +1,15 @@
if TARGET_WORK_92105
config SYS_BOARD
default "work_92105"
config SYS_VENDOR
default "work-microwave"
config SYS_SOC
default "lpc32xx"
config SYS_CONFIG_NAME
default "work_92105"
endif

@ -0,0 +1,6 @@
WORK_92105 BOARD
M: Albert ARIBAUD <albert.aribaud@3adev.fr>
S: Maintained
F: board/work-microwave/work_92105/
F: include/configs/work_92105.h
F: configs/work_92105_defconfig

@ -0,0 +1,10 @@
#
# (C) Copyright 2014 DENX Software Engineering GmbH
# Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y := work_92105.o work_92105_display.o
obj-$(CONFIG_SPL_BUILD) += work_92105_spl.o

@ -0,0 +1,91 @@
Work_92105 from Work Microwave is an LPC3250- based board with the
following features:
- 64MB SDR DRAM
- 1 GB SLC NAND, managed through MLC controller.
- Ethernet
- Ethernet + PHY SMSC8710
- I2C:
- EEPROM (24M01-compatible)
- RTC (DS1374-compatible)
- Temperature sensor (DS620)
- DACs (2 x MAX518)
- SPI (through SSP interface)
- Port expander MAX6957
- LCD display (HD44780-compatible), controlled
through the port expander and DACs
Standard SPL and U-Boot binaries
--------------------------------
The default 'make' (or the 'make all') command will produce the
following files:
1. spl/u-boot-spl.bin SPL, intended to run from SRAM at address 0.
This file can be loaded in SRAM through a JTAG
debugger or through the LPC32XX Service Boot
mechanism.
2. u-boot.bin The raw U-Boot image, which can be loaded in
DDR through a JTAG debugger (for instance by
breaking SPL after DDR init), or by a running
U-Boot through e.g. 'loady' or 'tftp' and then
executed with 'go'.
3. u-boot.img A U-Boot image with a mkimage header prepended.
SPL assumes (even when loaded through JTAG or
Service Boot) that such an image will be found
at offset 0x00040000 in NAND.
NAND cold-boot binaries
-----------------------
The board can boot entirely from power-on with only SPL and U-Boot in
NAND. The LPC32XX-specific 'make lpc32xx-full.bin' command will produce
(in addition to spl/u-boot-spl.bin and u-boot.img if they were not made
already) the following files:
4. lpc32xx-spl.img spl/u-boot-spl.bin, with a LPC32XX boot header
prepended. This header is required for the ROM
code to load SPL into SRAM and branch into it.
The content of this file is expected to reside
in NAND at addresses 0x00000000 and 0x00020000
(two copies).
5. lpc32xx-boot-0.bin lpc32xx-spl.img, padded with 0xFF bytes to a
size of 0x20000 bytes. This file covers exactly
the reserved area for the first bootloader copy
in NAND.
6. lpc32xx-boot-1.bin Same as lpc32xx-boot-0.bin. This is intended to
be used as the second bootloader copy.
7. lpc32xx-full.bin lpc32xx-boot-0.bin, lpc32xx-boot-1.bin and
u-boot.img concatenated. This file represents
the content of whole bootloader as present in
NAND at offset 00x00000000.
Flashing instructions
---------------------
The following assumes a working U-Boot on the target, with the ability
to load files into DDR.
To update the whole bootloader:
nand erase 0x00000000 0x80000
(load lpc32xx-full.bin at location $loadaddr)
nand write $loadaddr 0x00000000 $filesize
To update SPL only (note the double nand write) :
nand erase 0x00000000 0x40000
(load lpc32xx-spl.img or lpc32xx-boot-N.bin at location $loadaddr)
nand write $loadaddr 0x00000000 $filesize
nand write $loadaddr 0x00020000 $filesize
To update U-Boot only:
nand erase 0x00040000 0x40000
(load u-boot.img at location $loadaddr)
nand write $loadaddr 0x00040000 $filesize

@ -0,0 +1,77 @@
/*
* WORK Microwave work_92105 board support
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clk.h>
#include <asm/arch/emc.h>
#include <asm/arch/wdt.h>
#include <asm/gpio.h>
#include <spl.h>
#include "work_92105_display.h"
DECLARE_GLOBAL_DATA_PTR;
static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE;
static struct wdt_regs *wdt = (struct wdt_regs *)WDT_BASE;
void reset_periph(void)
{
setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG);
writel(WDTIM_MCTRL_RESFRC1, &wdt->mctrl);
udelay(150);
writel(0, &wdt->mctrl);
clrbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG);
}
int board_early_init_f(void)
{
/* initialize serial port for console */
lpc32xx_uart_init(CONFIG_SYS_LPC32XX_UART);
/* enable I2C, SSP, MAC, NAND */
lpc32xx_i2c_init(1); /* only I2C1 has devices, I2C2 has none */
lpc32xx_ssp_init();
lpc32xx_mac_init();
lpc32xx_mlc_nand_init();
/* Display must wait until after relocation and devices init */
return 0;
}
#define GPO_19 115
int board_early_init_r(void)
{
/* Set NAND !WP to 1 through GPO_19 */
gpio_request(GPO_19, "NAND_nWP");
gpio_direction_output(GPO_19, 1);
/* initialize display */
work_92105_display_init();
return 0;
}
int board_init(void)
{
reset_periph();
/* adress of boot parameters */
gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
return 0;
}
int dram_init(void)
{
gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
CONFIG_SYS_SDRAM_SIZE);
return 0;
}

@ -0,0 +1,349 @@
/*
* work_92105 display support
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* The work_92105 display is a HD44780-compatible module
* controlled through a MAX6957AAX SPI port expander, two
* MAX518 I2C DACs and native LPC32xx GPO 15.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/cpu.h>
#include <asm/arch/emc.h>
#include <asm/gpio.h>
#include <spi.h>
#include <i2c.h>
#include <version.h>
#include <vsprintf.h>
/*
* GPO 15 in port 3 is gpio 3*32+15 = 111
*/
#define GPO_15 111
/**
* MAX6957AAX registers that we will be using
*/
#define MAX6957_CONF 0x04
#define MAX6957_CONF_08_11 0x0A
#define MAX6957_CONF_12_15 0x0B
#define MAX6957_CONF_16_19 0x0C
/**
* Individual gpio ports (one per gpio) to HD44780
*/
#define MAX6957AAX_HD44780_RS 0x29
#define MAX6957AAX_HD44780_R_W 0x2A
#define MAX6957AAX_HD44780_EN 0x2B
#define MAX6957AAX_HD44780_DATA 0x4C
/**
* Display controller instructions
*/
/* Function set: eight bits, two lines, 8-dot font */
#define HD44780_FUNCTION_SET 0x38
/* Display ON / OFF: turn display on */
#define HD44780_DISPLAY_ON_OFF_CONTROL 0x0C
/* Entry mode: increment */
#define HD44780_ENTRY_MODE_SET 0x06
/* Clear */
#define HD44780_CLEAR_DISPLAY 0x01
/* Set DDRAM addr (to be ORed with exact address) */
#define HD44780_SET_DDRAM_ADDR 0x80
/* Set CGRAM addr (to be ORed with exact address) */
#define HD44780_SET_CGRAM_ADDR 0x40
/**
* Default value for contrats
*/
#define CONTRAST_DEFAULT 25
/**
* Define slave as a module-wide local to save passing it around,
* plus we will need it after init for the "hd44780" command.
*/
static struct spi_slave *slave;
/*
* Write a value into a MAX6957AAX register.
*/
static void max6957aax_write(uint8_t reg, uint8_t value)
{
uint8_t dout[2];
dout[0] = reg;
dout[1] = value;
gpio_set_value(GPO_15, 0);
/* do SPI read/write (passing din==dout is OK) */
spi_xfer(slave, 16, dout, dout, SPI_XFER_BEGIN | SPI_XFER_END);
gpio_set_value(GPO_15, 1);
}
/*
* Read a value from a MAX6957AAX register.
*
* According to the MAX6957AAX datasheet, we should release the chip
* select halfway through the read sequence, when the actual register
* value is read; but the WORK_92105 hardware prevents the MAX6957AAX
* SPI OUT from reaching the LPC32XX SIP MISO if chip is not selected.
* so let's release the CS an hold it again while reading the result.
*/
static uint8_t max6957aax_read(uint8_t reg)
{
uint8_t dout[2], din[2];
/* send read command */
dout[0] = reg | 0x80; /* set bit 7 to indicate read */
dout[1] = 0;
gpio_set_value(GPO_15, 0);
/* do SPI read/write (passing din==dout is OK) */
spi_xfer(slave, 16, dout, dout, SPI_XFER_BEGIN | SPI_XFER_END);
/* latch read command */
gpio_set_value(GPO_15, 1);
/* read register -- din = noop on xmit, din[1] = reg on recv */
din[0] = 0;
din[1] = 0;
gpio_set_value(GPO_15, 0);
/* do SPI read/write (passing din==dout is OK) */
spi_xfer(slave, 16, din, din, SPI_XFER_BEGIN | SPI_XFER_END);
/* end of read. */
gpio_set_value(GPO_15, 1);
return din[1];
}
static void hd44780_instruction(unsigned long instruction)
{
max6957aax_write(MAX6957AAX_HD44780_RS, 0);
max6957aax_write(MAX6957AAX_HD44780_R_W, 0);
max6957aax_write(MAX6957AAX_HD44780_EN, 1);
max6957aax_write(MAX6957AAX_HD44780_DATA, instruction);
max6957aax_write(MAX6957AAX_HD44780_EN, 0);
/* HD44780 takes 37 us for most instructions, 1520 for clear */
if (instruction == HD44780_CLEAR_DISPLAY)
udelay(2000);
else
udelay(100);
}
static void hd44780_write_char(char c)
{
max6957aax_write(MAX6957AAX_HD44780_RS, 1);
max6957aax_write(MAX6957AAX_HD44780_R_W, 0);
max6957aax_write(MAX6957AAX_HD44780_EN, 1);
max6957aax_write(MAX6957AAX_HD44780_DATA, c);
max6957aax_write(MAX6957AAX_HD44780_EN, 0);
/* HD44780 takes 37 us to write to DDRAM or CGRAM */
udelay(100);
}
static void hd44780_write_str(char *s)
{
max6957aax_write(MAX6957AAX_HD44780_RS, 1);
max6957aax_write(MAX6957AAX_HD44780_R_W, 0);
while (*s) {
max6957aax_write(MAX6957AAX_HD44780_EN, 1);
max6957aax_write(MAX6957AAX_HD44780_DATA, *s);
max6957aax_write(MAX6957AAX_HD44780_EN, 0);
s++;
/* HD44780 takes 37 us to write to DDRAM or CGRAM */
udelay(100);
}
}
/*
* Existing user code might expect these custom characters to be
* recognized and displayed on the LCD
*/
static u8 char_gen_chars[] = {
/* #8, empty rectangle */
0x1F, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1F,
/* #9, filled right arrow */
0x10, 0x18, 0x1C, 0x1E, 0x1C, 0x18, 0x10, 0x00,
/* #10, filled left arrow */
0x01, 0x03, 0x07, 0x0F, 0x07, 0x03, 0x01, 0x00,
/* #11, up and down arrow */
0x04, 0x0E, 0x1F, 0x00, 0x00, 0x1F, 0x0E, 0x04,
/* #12, plus/minus */
0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x1F, 0x00,
/* #13, fat exclamation mark */
0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00,
/* #14, empty square */
0x00, 0x1F, 0x11, 0x11, 0x11, 0x1F, 0x00, 0x00,
/* #15, struck out square */
0x00, 0x1F, 0x19, 0x15, 0x13, 0x1F, 0x00, 0x00,
};
static void hd44780_init_char_gen(void)
{
int i;
hd44780_instruction(HD44780_SET_CGRAM_ADDR);
for (i = 0; i < sizeof(char_gen_chars); i++)
hd44780_write_char(char_gen_chars[i]);
hd44780_instruction(HD44780_SET_DDRAM_ADDR);
}
void work_92105_display_init(void)
{
int claim_err;
char *display_contrast_str;
uint8_t display_contrast = CONTRAST_DEFAULT;
uint8_t enable_backlight = 0x96;
slave = spi_setup_slave(0, 0, 500000, 0);
if (!slave) {
printf("Failed to set up SPI slave\n");
return;
}
claim_err = spi_claim_bus(slave);
if (claim_err)
debug("Failed to claim SPI bus: %d\n", claim_err);
/* enable backlight */
i2c_write(0x2c, 0x01, 1, &enable_backlight, 1);
/* set display contrast */
display_contrast_str = getenv("fwopt_dispcontrast");
if (display_contrast_str)
display_contrast = simple_strtoul(display_contrast_str,
NULL, 10);
i2c_write(0x2c, 0x00, 1, &display_contrast, 1);
/* request GPO_15 as an output initially set to 1 */
gpio_request(GPO_15, "MAX6957_nCS");
gpio_direction_output(GPO_15, 1);
/* enable MAX6957 portexpander */
max6957aax_write(MAX6957_CONF, 0x01);
/* configure pin 8 as input, pins 9..19 as outputs */
max6957aax_write(MAX6957_CONF_08_11, 0x56);
max6957aax_write(MAX6957_CONF_12_15, 0x55);
max6957aax_write(MAX6957_CONF_16_19, 0x55);
/* initialize HD44780 */
max6957aax_write(MAX6957AAX_HD44780_EN, 0);
hd44780_instruction(HD44780_FUNCTION_SET);
hd44780_instruction(HD44780_DISPLAY_ON_OFF_CONTROL);
hd44780_instruction(HD44780_ENTRY_MODE_SET);
/* write custom character glyphs */
hd44780_init_char_gen();
/* Show U-Boot version, date and time as a sign-of-life */
hd44780_instruction(HD44780_CLEAR_DISPLAY);
hd44780_instruction(HD44780_SET_DDRAM_ADDR | 0);
hd44780_write_str(U_BOOT_VERSION);
hd44780_instruction(HD44780_SET_DDRAM_ADDR | 64);
hd44780_write_str(U_BOOT_DATE);
hd44780_instruction(HD44780_SET_DDRAM_ADDR | 64 | 20);
hd44780_write_str(U_BOOT_TIME);
}
#ifdef CONFIG_CMD_MAX6957
static int do_max6957aax(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
int reg, val;
if (argc != 3)
return CMD_RET_USAGE;
switch (argv[1][0]) {
case 'r':
case 'R':
reg = simple_strtoul(argv[2], NULL, 0);
val = max6957aax_read(reg);
printf("MAX6957 reg 0x%02x read 0x%02x\n", reg, val);
return 0;
default:
reg = simple_strtoul(argv[1], NULL, 0);
val = simple_strtoul(argv[2], NULL, 0);
max6957aax_write(reg, val);
printf("MAX6957 reg 0x%02x wrote 0x%02x\n", reg, val);
return 0;
}
return 1;
}
#ifdef CONFIG_SYS_LONGHELP
static char max6957aax_help_text[] =
"max6957aax - write or read display register:\n"
"\tmax6957aax R|r reg - read display register;\n"
"\tmax6957aax reg val - write display register.";
#endif
U_BOOT_CMD(
max6957aax, 6, 1, do_max6957aax,
"SPI MAX6957 display write/read",
max6957aax_help_text
);
#endif /* CONFIG_CMD_MAX6957 */
#ifdef CONFIG_CMD_HD44760
/*
* We need the HUSH parser because we need string arguments, and
* only HUSH can understand them.
*/
#if !defined(CONFIG_SYS_HUSH_PARSER)
#error CONFIG_CMD_HD44760 requires CONFIG_SYS_HUSH_PARSER
#endif
static int do_hd44780(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
char *cmd;
if (argc != 3)
return CMD_RET_USAGE;
cmd = argv[1];
if (strcasecmp(cmd, "cmd") == 0)
hd44780_instruction(simple_strtol(argv[2], NULL, 0));
else if (strcasecmp(cmd, "data") == 0)
hd44780_write_char(simple_strtol(argv[2], NULL, 0));
else if (strcasecmp(cmd, "str") == 0)
hd44780_write_str(argv[2]);
return 0;
}
#ifdef CONFIG_SYS_LONGHELP
static char hd44780_help_text[] =
"hd44780 - control LCD driver:\n"
"\thd44780 cmd <val> - send command <val> to driver;\n"
"\thd44780 data <val> - send data <val> to driver;\n"
"\thd44780 str \"<text>\" - send \"<text>\" to driver.";
#endif
U_BOOT_CMD(
hd44780, 6, 1, do_hd44780,
"HD44780 LCD driver control",
hd44780_help_text
);
#endif /* CONFIG_CMD_HD44780 */

@ -0,0 +1,14 @@
/*
* work_92105 display support interface
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* The work_92105 display is a HD44780-compatible module
* controlled through a MAX6957AAX SPI port expander, two
* MAX518 I2C DACs and native LPC32xx GPO 15.
*
* SPDX-License-Identifier: GPL-2.0+
*/
void work_92105_display_init(void);

@ -0,0 +1,85 @@
/*
* WORK Microwave work_92105 board support
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/cpu.h>
#include <asm/arch/emc.h>
#include <asm/gpio.h>
#include <spl.h>
#include "work_92105_display.h"
struct emc_dram_settings dram_64mb = {
.cmddelay = 0x0001C000,
.config0 = 0x00005682,
.rascas0 = 0x00000302,
.rdconfig = 0x00000011,
.trp = 52631578,
.tras = 20833333,
.tsrex = 12500000,
.twr = 66666666,
.trc = 13888888,
.trfc = 10256410,
.txsr = 12500000,
.trrd = 1,
.tmrd = 1,
.tcdlr = 0,
.refresh = 128000,
.mode = 0x00018000,
.emode = 0x02000000
};
const struct emc_dram_settings dram_128mb = {
.cmddelay = 0x0001C000,
.config0 = 0x00005882,
.rascas0 = 0x00000302,
.rdconfig = 0x00000011,
.trp = 52631578,
.tras = 22222222,
.tsrex = 8333333,
.twr = 66666666,
.trc = 14814814,
.trfc = 10256410,
.txsr = 8333333,
.trrd = 1,
.tmrd = 1,
.tcdlr = 0,
.refresh = 128000,
.mode = 0x00030000,
.emode = 0x02000000
};
void spl_board_init(void)
{
/* initialize serial port for console */
lpc32xx_uart_init(CONFIG_SYS_LPC32XX_UART);
/* initialize console */
preloader_console_init();
/* init DDR and NAND to chainload U-Boot */
ddr_init(&dram_128mb);
/*
* If this is actually a 64MB module, then the highest column
* bit in any address will be ignored, and thus address 0x80000000
* should be mirrored at address 0x80000800. Test this.
*/
writel(0x31415926, 0x80000000); /* write Pi at 0x80000000 */
writel(0x16180339, 0x80000800); /* write Phi at 0x80000800 */
if (readl(0x80000000) == 0x16180339) /* check 0x80000000 */ {
/* actually 64MB mirrored: reconfigure controller */
ddr_init(&dram_64mb);
}
/* initialize NAND controller to load U-Boot from NAND */
lpc32xx_mlc_nand_init();
}
u32 spl_boot_device(void)
{
return BOOT_DEVICE_NAND;
}

@ -0,0 +1,6 @@
CONFIG_ARM=y
CONFIG_TARGET_WORK_92105=y
CONFIG_DM=y
CONFIG_DM_GPIO=y
CONFIG_SPL=y
CONFIG_SYS_EXTRA_OPTIONS=""

@ -0,0 +1,241 @@
/*
* WORK Microwave work_92105 board configuration file
*
* (C) Copyright 2014 DENX Software Engineering GmbH
* Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_WORK_92105_H__
#define __CONFIG_WORK_92105_H__
/* SoC and board defines */
#include <linux/sizes.h>
#include <asm/arch/cpu.h>
/*
* Define work_92105 machine type by hand -- done only for compatibility
* with original board code
*/
#define MACH_TYPE_WORK_92105 736
#define CONFIG_MACH_TYPE MACH_TYPE_WORK_92105
#define CONFIG_SYS_ICACHE_OFF
#define CONFIG_SYS_DCACHE_OFF
#if !defined(CONFIG_SPL_BUILD)
#define CONFIG_SKIP_LOWLEVEL_INIT
#endif
#define CONFIG_BOARD_EARLY_INIT_F
#define CONFIG_BOARD_EARLY_INIT_R
/* generate LPC32XX-specific SPL image */
#define CONFIG_LPC32XX_SPL
/*
* Memory configurations
*/
#define CONFIG_NR_DRAM_BANKS 1
#define CONFIG_SYS_MALLOC_LEN SZ_1M
#define CONFIG_SYS_SDRAM_BASE EMC_DYCS0_BASE
#define CONFIG_SYS_SDRAM_SIZE SZ_128M
#define CONFIG_SYS_TEXT_BASE 0x80100000
#define CONFIG_SYS_MEMTEST_START (CONFIG_SYS_SDRAM_BASE + SZ_32K)
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_TEXT_BASE - SZ_1M)
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_32K)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_512K \
- GENERATED_GBL_DATA_SIZE)
/*
* Serial Driver
*/
#define CONFIG_SYS_LPC32XX_UART 5 /* UART5 - NS16550 */
#define CONFIG_BAUDRATE 115200
/*
* Ethernet Driver
*/
#define CONFIG_PHY_SMSC
#define CONFIG_LPC32XX_ETH
#define CONFIG_PHYLIB
#define CONFIG_PHY_ADDR 0
#define CONFIG_SYS_FAULT_ECHO_LINK_DOWN
#define CONFIG_CMD_MII
#define CONFIG_CMD_PING
#define CONFIG_CMD_DHCP
/* FIXME: remove "Waiting for PHY auto negotiation to complete..." message */
/*
* I2C driver
*/
#define CONFIG_SYS_I2C_LPC32XX
#define CONFIG_SYS_I2C
#define CONFIG_CMD_I2C
#define CONFIG_SYS_I2C_SPEED 350000
/*
* I2C EEPROM
*/
#define CONFIG_CMD_EEPROM
#define CONFIG_SYS_I2C_EEPROM_ADDR 0x56
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
/*
* I2C RTC
*/
#define CONFIG_CMD_DATE
#define CONFIG_RTC_DS1374
/*
* I2C Temperature Sensor (DTT)
*/
#define CONFIG_CMD_DTT
#define CONFIG_DTT_SENSORS { 0, 1 }
#define CONFIG_DTT_DS620
/*
* U-Boot General Configurations
*/
#define CONFIG_SYS_GENERIC_BOARD
#define CONFIG_SYS_LONGHELP
#define CONFIG_SYS_CBSIZE 1024
#define CONFIG_SYS_PBSIZE \
(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
#define CONFIG_SYS_MAXARGS 16
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
#define CONFIG_SYS_HUSH_PARSER
#define CONFIG_AUTO_COMPLETE
#define CONFIG_CMDLINE_EDITING
#define CONFIG_VERSION_VARIABLE
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_DOS_PARTITION
/*
* No NOR
*/
#define CONFIG_SYS_NO_FLASH
/*
* NAND chip timings for FIXME: which one?
*/
#define CONFIG_LPC32XX_NAND_MLC_TCEA_DELAY 333333333
#define CONFIG_LPC32XX_NAND_MLC_BUSY_DELAY 10000000
#define CONFIG_LPC32XX_NAND_MLC_NAND_TA 18181818
#define CONFIG_LPC32XX_NAND_MLC_RD_HIGH 31250000
#define CONFIG_LPC32XX_NAND_MLC_RD_LOW 45454545
#define CONFIG_LPC32XX_NAND_MLC_WR_HIGH 40000000
#define CONFIG_LPC32XX_NAND_MLC_WR_LOW 83333333
/*
* NAND
*/
/* driver configuration */
#define CONFIG_SYS_NAND_SELF_INIT
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_MAX_NAND_CHIPS 1
#define CONFIG_SYS_NAND_BASE MLC_NAND_BASE
#define CONFIG_NAND_LPC32XX_MLC
#define CONFIG_CMD_NAND
/*
* GPIO
*/
#define CONFIG_CMD_GPIO
#define CONFIG_LPC32XX_GPIO
/*
* SSP/SPI/DISPLAY
*/
#define CONFIG_CMD_SPI
#define CONFIG_LPC32XX_SSP
#define CONFIG_LPC32XX_SSP_TIMEOUT 100000
#define CONFIG_CMD_MAX6957
#define CONFIG_CMD_HD44760
/*
* Environment
*/
#define CONFIG_ENV_IS_IN_NAND 1
#define CONFIG_ENV_SIZE 0x00020000
#define CONFIG_ENV_OFFSET 0x00100000
#define CONFIG_ENV_OFFSET_REDUND 0x00120000
#define CONFIG_ENV_ADDR 0x80000100
/*
* Provide default ethernet address
*
* THIS IS NORMALLY NOT DONE. HERE WE KEEP WHAT WAS IN THE PORTED
* BOARD CONFIG IN CASE SOME PROVISIONING PROCESS OUT THERE EXPECTS
* THIS MAC ADDRESS WHEN THE DEVICE HAS STILL ITS DEFAULT CONFIG.
*/
#define CONFIG_ETHADDR 00:12:B4:00:AF:FE
#define CONFIG_OVERWRITE_ETHADDR_ONCE
/*
* U-Boot Commands
*/
#include <config_cmd_default.h>
/*
* Boot Linux
*/
#define CONFIG_CMDLINE_TAG
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_INITRD_TAG
#define CONFIG_ZERO_BOOTDELAY_CHECK
#define CONFIG_BOOTDELAY 3
#define CONFIG_BOOTFILE "uImage"
#define CONFIG_BOOTARGS "console=ttyS2,115200n8"
#define CONFIG_LOADADDR 0x80008000
/*
* SPL
*/
/* SPL will be executed at offset 0 */
#define CONFIG_SPL_TEXT_BASE 0x00000000
/* SPL will use SRAM as stack */
#define CONFIG_SPL_STACK 0x0000FFF8
#define CONFIG_SPL_BOARD_INIT
/* Use the framework and generic lib */
#define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_LIBGENERIC_SUPPORT
#define CONFIG_SPL_LIBCOMMON_SUPPORT
/* SPL will use serial */
#define CONFIG_SPL_SERIAL_SUPPORT
/* SPL will load U-Boot from NAND offset 0x40000 */
#define CONFIG_SPL_NAND_SUPPORT
#define CONFIG_SPL_NAND_DRIVERS
#define CONFIG_SPL_NAND_BASE
#define CONFIG_SPL_NAND_BOOT
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x00040000
#define CONFIG_SPL_PAD_TO 0x20000
/* U-Boot will be 0x40000 bytes, loaded and run at CONFIG_SYS_TEXT_BASE */
#define CONFIG_SYS_MONITOR_LEN 0x40000 /* actually, MAX size */
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE
#define CONFIG_SYS_NAND_U_BOOT_DST CONFIG_SYS_TEXT_BASE
/*
* Include SoC specific configuration
*/
#include <asm/arch/config.h>
#endif /* __CONFIG_WORK_92105_H__*/
Loading…
Cancel
Save