[U-Boot] [PATCH v2 8/8] lpc32xx: add support for board work_92105
Albert ARIBAUD (3ADEV)
albert.aribaud at 3adev.fr
Thu Feb 12 18:37:07 CET 2015
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
This board has SPL support, and uses the LPC32XX boot
image format.
Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud at 3adev.fr>
---
Changes in v2: None
arch/arm/Kconfig | 6 +
arch/arm/cpu/arm926ejs/lpc32xx/Makefile | 2 +
arch/arm/cpu/arm926ejs/lpc32xx/clk.c | 34 ++
arch/arm/cpu/arm926ejs/lpc32xx/cpu.c | 4 +
arch/arm/cpu/arm926ejs/lpc32xx/dram.c | 80 +++++
arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S | 45 +++
arch/arm/include/asm/arch-lpc32xx/clk.h | 5 +
arch/arm/include/asm/arch-lpc32xx/cpu.h | 1 +
arch/arm/include/asm/arch-lpc32xx/mux.h | 18 ++
arch/arm/include/asm/arch-lpc32xx/sys_proto.h | 4 +-
board/work-microwave/work_92105/Kconfig | 15 +
board/work-microwave/work_92105/MAINTAINERS | 6 +
board/work-microwave/work_92105/Makefile | 8 +
board/work-microwave/work_92105/README | 23 ++
board/work-microwave/work_92105/work_92105.c | 86 +++++
.../work-microwave/work_92105/work_92105_display.c | 349 +++++++++++++++++++++
.../work-microwave/work_92105/work_92105_display.h | 14 +
configs/work_92105_defconfig | 5 +
include/configs/work_92105.h | 259 +++++++++++++++
19 files changed, 963 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/cpu/arm926ejs/lpc32xx/dram.c
create mode 100644 arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
create mode 100644 arch/arm/include/asm/arch-lpc32xx/mux.h
create mode 100644 board/work-microwave/work_92105/Kconfig
create mode 100644 board/work-microwave/work_92105/MAINTAINERS
create mode 100644 board/work-microwave/work_92105/Makefile
create mode 100644 board/work-microwave/work_92105/README
create mode 100644 board/work-microwave/work_92105/work_92105.c
create mode 100644 board/work-microwave/work_92105/work_92105_display.c
create mode 100644 board/work-microwave/work_92105/work_92105_display.h
create mode 100644 configs/work_92105_defconfig
create mode 100644 include/configs/work_92105.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 47806f8..42983a3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -247,6 +247,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_JADECPU
bool "Support jadecpu"
select CPU_ARM926EJS
@@ -999,6 +1004,7 @@ source "board/udoo/Kconfig"
source "board/vpac270/Kconfig"
source "board/wandboard/Kconfig"
source "board/woodburn/Kconfig"
+source "board/work-microwave/work_92105/Kconfig"
source "board/xaeniax/Kconfig"
source "board/zipitz2/Kconfig"
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
index 314f004..4837377 100644
--- a/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/Makefile
@@ -6,3 +6,5 @@
#
obj-y = cpu.o clk.o devices.o timer.o
+
+obj-$(CONFIG_SPL_BUILD) += dram.o lowlevel_init.o
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
index b7a44d5..1ef8a36 100644
--- a/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/clk.c
@@ -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();
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
index eec4d9e..f4d7f02 100644
--- a/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/cpu.c
@@ -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;
@@ -33,6 +34,9 @@ void reset_cpu(ulong addr)
#if defined(CONFIG_ARCH_CPU_INIT)
int arch_cpu_init(void)
{
+#if defined(CONFIG_SPL_BUILD)
+ ddr_init();
+#endif
/*
* It might be necessary to flush data cache, if U-boot is loaded
* from kickstart bootloader, e.g. from S1L loader
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/dram.c b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
new file mode 100644
index 0000000..606f49d
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/dram.c
@@ -0,0 +1,80 @@
+/*
+ * LPC32xx dram init
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud at 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;
+
+#if defined(CONFIG_SPL_BUILD)
+
+void ddr_init(void)
+{
+ uint32_t ck;
+
+ /* Enable EMC interface and choose little endian mode */
+ emc->ctrl = 1;
+ emc->config = 0;
+ /* Select maximum EMC Dynamic Memory Refresh Time */
+ emc->refresh = 0x7FF;
+ /* Determine CLK */
+ ck = get_sdram_clk_rate();
+ /* Configure SDRAM */
+ clk->sdramclk_ctrl = (CONFIG_LPC32XX_SDRAM_COMMAND_DELAY << 14);
+ emc->config0 = CONFIG_LPC32XX_SDRAM_CONFIG0;
+ emc->rascas0 = CONFIG_LPC32XX_SDRAM_RASCAS0;
+ emc->read_config = CONFIG_LPC32XX_SDRAM_READ_CONFIG;
+ /* Set timings */
+ emc->t_rp = (ck / CONFIG_LPC32XX_SDRAM_T_RP) & 0x0000000F;
+ emc->t_ras = (ck / CONFIG_LPC32XX_SDRAM_T_RAS) & 0x0000000F;
+ emc->t_srex = (ck / CONFIG_LPC32XX_SDRAM_T_SREX) & 0x0000007F;
+ emc->t_wr = (ck / CONFIG_LPC32XX_SDRAM_T_WR) & 0x0000000F;
+ emc->t_rc = (ck / CONFIG_LPC32XX_SDRAM_T_RC) & 0x0000001F;
+ emc->t_rfc = (ck / CONFIG_LPC32XX_SDRAM_T_RFC) & 0x0000001F;
+ emc->t_xsr = (ck / CONFIG_LPC32XX_SDRAM_T_XSR) & 0x000000FF;
+ emc->t_rrd = CONFIG_LPC32XX_SDRAM_T_RRD;
+ emc->t_mrd = CONFIG_LPC32XX_SDRAM_T_MRD;
+ emc->t_cdlr = CONFIG_LPC32XX_SDRAM_T_CDLR;
+ /* Dynamic refresh */
+ emc->refresh = (((ck / CONFIG_LPC32XX_SDRAM_REFRESH) >> 4) & 0x7FF);
+ udelay(10);
+ /* Force all clocks, enable inverted ck, issue NOP command */
+ emc->control = 0x00000193;
+ udelay(100);
+ /* Keep all clocks enabled, issue a PRECHARGE ALL command */
+ emc->control = 0x00000113;
+ /* Fast dynamic refresh for at least a few SDRAM ck cycles */
+ emc->refresh = (((128) >> 4) & 0x7FF);
+ udelay(10);
+ /* set correct dynamic refresh timing */
+ emc->refresh = (((ck / CONFIG_LPC32XX_SDRAM_REFRESH) >> 4) & 0x7FF);
+ udelay(10);
+ /* set normal mode to CAS=3 */
+ emc->control = 0x00000093;
+ readl(EMC_DYCS0_BASE | CONFIG_LPC32XX_DRAM_MODE);
+ /* set extended mode to all zeroes */
+ emc->control = 0x00000093;
+ readl(EMC_DYCS0_BASE | CONFIG_LPC32XX_DRAM_EMODE);
+ /* stop forcing clocks, keep inverted clock, issue normal mode */
+ emc->control = 0x00000010;
+}
+#endif
diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
new file mode 100644
index 0000000..4b8053e
--- /dev/null
+++ b/arch/arm/cpu/arm926ejs/lpc32xx/lowlevel_init.S
@@ -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 at 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
diff --git a/arch/arm/include/asm/arch-lpc32xx/clk.h b/arch/arm/include/asm/arch-lpc32xx/clk.h
index 2cb5703..9449869 100644
--- a/arch/arm/include/asm/arch-lpc32xx/clk.h
+++ b/arch/arm/include/asm/arch-lpc32xx/clk.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-lpc32xx/cpu.h b/arch/arm/include/asm/arch-lpc32xx/cpu.h
index 1067107..0b5dca1 100644
--- a/arch/arm/include/asm/arch-lpc32xx/cpu.h
+++ b/arch/arm/include/asm/arch-lpc32xx/cpu.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 */
diff --git a/arch/arm/include/asm/arch-lpc32xx/mux.h b/arch/arm/include/asm/arch-lpc32xx/mux.h
new file mode 100644
index 0000000..dc1b5bc
--- /dev/null
+++ b/arch/arm/include/asm/arch-lpc32xx/mux.h
@@ -0,0 +1,18 @@
+/*
+ * LPC32xx MUX interface
+ *
+ * (C) Copyright 2015 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud at 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;
+};
diff --git a/arch/arm/include/asm/arch-lpc32xx/sys_proto.h b/arch/arm/include/asm/arch-lpc32xx/sys_proto.h
index 86d5ee9..edcc4bc 100644
--- a/arch/arm/include/asm/arch-lpc32xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-lpc32xx/sys_proto.h
@@ -12,5 +12,7 @@ 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(void);
+#endif
#endif /* _LPC32XX_SYS_PROTO_H */
diff --git a/board/work-microwave/work_92105/Kconfig b/board/work-microwave/work_92105/Kconfig
new file mode 100644
index 0000000..74f004f
--- /dev/null
+++ b/board/work-microwave/work_92105/Kconfig
@@ -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
diff --git a/board/work-microwave/work_92105/MAINTAINERS b/board/work-microwave/work_92105/MAINTAINERS
new file mode 100644
index 0000000..29a92c5
--- /dev/null
+++ b/board/work-microwave/work_92105/MAINTAINERS
@@ -0,0 +1,6 @@
+WORK_92105 BOARD
+M: Albert ARIBAUD <albert.aribaud at 3adev.fr>
+S: Maintained
+F: board/work-microwave/work_92105/
+F: include/configs/work_92105.h
+F: configs/work_92105_defconfig
diff --git a/board/work-microwave/work_92105/Makefile b/board/work-microwave/work_92105/Makefile
new file mode 100644
index 0000000..853dea9
--- /dev/null
+++ b/board/work-microwave/work_92105/Makefile
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2014 DENX Software Engineering GmbH
+# Written-by: Albert ARIBAUD <albert.aribaud at 3adev.fr>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := work_92105.o work_92105_display.o
diff --git a/board/work-microwave/work_92105/README b/board/work-microwave/work_92105/README
new file mode 100644
index 0000000..091d731
--- /dev/null
+++ b/board/work-microwave/work_92105/README
@@ -0,0 +1,23 @@
+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
+
+This board has SPL support, and uses the LPC32XX boot image format.
+Once the U-Boot target "work_92105" is built, the following two files
+can be flashed:
+
+ spl/lpc32xx-spl.bin at offset 0x0
+ u-boot.bin at offset 0x40000
diff --git a/board/work-microwave/work_92105/work_92105.c b/board/work-microwave/work_92105/work_92105.c
new file mode 100644
index 0000000..cad0d75
--- /dev/null
+++ b/board/work-microwave/work_92105/work_92105.c
@@ -0,0 +1,86 @@
+/*
+ * WORK Microwave work_92105 board support
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud at 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"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_SPL_BUILD)
+
+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();
+ lpc32xx_mlc_nand_init();
+}
+
+#else /* ! defined(CONFIG_SPL_BUILD) */
+
+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;
+}
+
+#endif /* CONFIG_SPL_BUILD */
+
+int board_init(void)
+{
+ /* 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;
+}
+
+#if defined(CONFIG_SPL_BUILD)
+u32 spl_boot_device(void)
+{
+ return BOOT_DEVICE_NAND;
+}
+#endif
diff --git a/board/work-microwave/work_92105/work_92105_display.c b/board/work-microwave/work_92105/work_92105_display.c
new file mode 100644
index 0000000..c8b1013
--- /dev/null
+++ b/board/work-microwave/work_92105/work_92105_display.c
@@ -0,0 +1,349 @@
+/*
+ * work_92105 display support
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud at 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 */
diff --git a/board/work-microwave/work_92105/work_92105_display.h b/board/work-microwave/work_92105/work_92105_display.h
new file mode 100644
index 0000000..dd6e768
--- /dev/null
+++ b/board/work-microwave/work_92105/work_92105_display.h
@@ -0,0 +1,14 @@
+/*
+ * work_92105 display support interface
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud at 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);
diff --git a/configs/work_92105_defconfig b/configs/work_92105_defconfig
new file mode 100644
index 0000000..9be52a8
--- /dev/null
+++ b/configs/work_92105_defconfig
@@ -0,0 +1,5 @@
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_SPL=y
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_WORK_92105=y
diff --git a/include/configs/work_92105.h b/include/configs/work_92105.h
new file mode 100644
index 0000000..fd242fb
--- /dev/null
+++ b/include/configs/work_92105.h
@@ -0,0 +1,259 @@
+/*
+ * WORK Microwave work_92105 board configuration file
+ *
+ * (C) Copyright 2014 DENX Software Engineering GmbH
+ * Written-by: Albert ARIBAUD <albert.aribaud at 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_64M
+#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
+
+#define CONFIG_CMD_DM
+
+/*
+ * 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_MAX_NAND_DEVICE 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 */
+#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
+
+/*
+ * DRAM timings for MT48H16M16LFBF-8 (x2 chips -> 64MB)
+ */
+
+/* delay commands by 7*0.25 = 1.75 ns */
+#define CONFIG_LPC32XX_SDRAM_COMMAND_DELAY 7
+/* 256Mb (16Mx16), 4banks, row len 13, column len 9, LP SDR */
+#define CONFIG_LPC32XX_SDRAM_CONFIG0 0x00005682
+/* CAS latency 6 * 0.5 = 3 clk, RAS latency = 2 clk */
+#define CONFIG_LPC32XX_SDRAM_RASCAS0 0x00000302
+/* capture on HCLK pos edge, apply command delay */
+#define CONFIG_LPC32XX_SDRAM_READ_CONFIG 0x00000011
+/* Timings */
+#define CONFIG_LPC32XX_SDRAM_T_RP 52631578 /* 19 ns */
+#define CONFIG_LPC32XX_SDRAM_T_RAS 20833333 /* 48 ns */
+#define CONFIG_LPC32XX_SDRAM_T_SREX 12500000 /* 80 ns */
+#define CONFIG_LPC32XX_SDRAM_T_WR 66666666 /* 15 ns */
+#define CONFIG_LPC32XX_SDRAM_T_RC 13888888 /* 72 ns */
+#define CONFIG_LPC32XX_SDRAM_T_RFC 10256410 /* 97.5 ns */
+#define CONFIG_LPC32XX_SDRAM_T_XSR 12500000 /* 80 ns */
+#define CONFIG_LPC32XX_SDRAM_T_RRD 1 /* 2 clocks */
+#define CONFIG_LPC32XX_SDRAM_T_MRD 1 /* 2 clocks */
+#define CONFIG_LPC32XX_SDRAM_T_CDLR 0 /* 1 clock */
+#define CONFIG_LPC32XX_SDRAM_REFRESH 128000
+#define CONFIG_LPC32XX_DRAM_MODE 0x00000030 /* CAS = 3 */
+#define CONFIG_LPC32XX_DRAM_EMODE 0x02000000 /* all zeroes */
+
+/*
+ * 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
+/* 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__*/
--
2.1.0
More information about the U-Boot
mailing list