[U-Boot] [PATCH 0/6] ATSTK1000 LCD panel support

The following series adds support for the LCD panel on the ATSTK1000. To use this, you must first apply both of the following series:
http://lists.denx.de/pipermail/u-boot/2008-September/039826.html http://lists.denx.de/pipermail/u-boot/2008-September/039833.html
I'm a bit unsure what to do about this. While I certainly want LCD support out of the box on all boards that support it, this patchset brings the U-Boot image size dangerously close to 128k, which is the space we currently have available with the current MTD partitioning layout hardcoded into the kernel. With NAND flash support added on top of this, the ATSTK1006 image ends up at almost 150k, and there are still other features I'd like to support in the future, e.g. libfdt, Hush parser, USB, etc.
So this means I can either merge this as-is but disabled by default (which is bad from a testing perspective), disable some other features, or change the partitioning. Doing the latter will also make it possible to introduce redundant environment, but it means current kernels will break.
Since the ATSTK1000 doesn't actually ship with a filesystem in flash by default, the breakage will probably be limited to a handful of customized boards, but people who have done this kind of customization probably won't like that the flash layout changes behind their back.
What do everyone think about this? Is redundant environment and a boatload of features worth breaking compatibility with current kernels?
Haavard
Shortlog and diffstat for the whole series follows.
Haavard Skinnemoen (6): ATSTK1000: Make the MACBs individually selectable avr32: Add clk and portmux infrastructure for the LCDC avr32: Reserve memory for LCD framebuffer spi: Add spi_xfer_single() convenience wrapper ATSTK1000: Add driver for the onboard LCD panel ATSTK1000: LCD support
board/atmel/atstk1000/Makefile | 1 + board/atmel/atstk1000/atstk1000.c | 105 ++++++++++++++- board/atmel/atstk1000/ltv350qv.c | 157 +++++++++++++++++++++ board/atmel/atstk1000/ltv350qv.h | 95 +++++++++++++ cpu/at32ap/at32ap700x/portmux.c | 14 ++ include/asm-avr32/arch-at32ap700x/chip-features.h | 5 + include/asm-avr32/arch-at32ap700x/clk.h | 6 + include/asm-avr32/arch-at32ap700x/portmux.h | 3 + include/asm-avr32/global_data.h | 1 + include/configs/atstk1002.h | 25 ++++ include/configs/atstk1006.h | 26 ++++ include/spi.h | 15 ++- lib_avr32/board.c | 6 + 13 files changed, 457 insertions(+), 2 deletions(-) create mode 100644 board/atmel/atstk1000/ltv350qv.c create mode 100644 board/atmel/atstk1000/ltv350qv.h

Make it possible to enable just one of the two ethernet interfaces on the ATSTK1000. This is necessary for LCD support since MACB1 conflicts with the LCD controller.
Signed-off-by: Haavard Skinnemoen haavard.skinnemoen@atmel.com --- board/atmel/atstk1000/atstk1000.c | 8 +++++++- include/configs/atstk1002.h | 3 +++ include/configs/atstk1006.h | 3 +++ 3 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/board/atmel/atstk1000/atstk1000.c b/board/atmel/atstk1000/atstk1000.c index 7be3993..31174d3 100644 --- a/board/atmel/atstk1000/atstk1000.c +++ b/board/atmel/atstk1000/atstk1000.c @@ -79,8 +79,10 @@ int board_early_init_f(void)
portmux_enable_ebi(sdram_config.data_bits, 23, 0, PORTMUX_DRIVE_HIGH); portmux_enable_usart1(PORTMUX_DRIVE_MIN); -#if defined(CONFIG_MACB) +#if defined(CONFIG_ATSTK1000_MACB0) portmux_enable_macb0(PORTMUX_MACB_MII, PORTMUX_DRIVE_LOW); +#endif +#if defined(CONFIG_ATSTK1000_MACB1) portmux_enable_macb1(PORTMUX_MACB_MII, PORTMUX_DRIVE_LOW); #endif #if defined(CONFIG_MMC) @@ -122,8 +124,12 @@ extern int macb_eth_initialize(int id, void *regs, unsigned int phy_addr); #ifdef CONFIG_CMD_NET int board_eth_init(bd_t *bi) { +#ifdef CONFIG_ATSTK1000_MACB0 macb_eth_initialize(0, (void *)MACB0_BASE, bi->bi_phy_id[0]); +#endif +#ifdef CONFIG_ATSTK1000_MACB1 macb_eth_initialize(1, (void *)MACB1_BASE, bi->bi_phy_id[1]); +#endif return 0; } #endif diff --git a/include/configs/atstk1002.h b/include/configs/atstk1002.h index 85cedb2..4509416 100644 --- a/include/configs/atstk1002.h +++ b/include/configs/atstk1002.h @@ -149,6 +149,9 @@
#define CONFIG_ATMEL_USART 1 #define CONFIG_MACB 1 +/* Enable both MACs by default */ +#define CONFIG_ATSTK1000_MACB0 1 +#define CONFIG_ATSTK1000_MACB1 1 #define CONFIG_PORTMUX_PIO 1 #define CFG_NR_PIOS 5 #define CFG_HSDRAMC 1 diff --git a/include/configs/atstk1006.h b/include/configs/atstk1006.h index d4b2f12..8a6c044 100644 --- a/include/configs/atstk1006.h +++ b/include/configs/atstk1006.h @@ -149,6 +149,9 @@
#define CONFIG_ATMEL_USART 1 #define CONFIG_MACB 1 +/* Enable both MACs by default */ +#define CONFIG_ATSTK1000_MACB0 1 +#define CONFIG_ATSTK1000_MACB1 1 #define CONFIG_PORTMUX_PIO 1 #define CFG_NR_PIOS 5 #define CFG_HSDRAMC 1

Signed-off-by: Haavard Skinnemoen haavard.skinnemoen@atmel.com --- cpu/at32ap/at32ap700x/portmux.c | 14 ++++++++++++++ include/asm-avr32/arch-at32ap700x/chip-features.h | 5 +++++ include/asm-avr32/arch-at32ap700x/clk.h | 6 ++++++ include/asm-avr32/arch-at32ap700x/portmux.h | 3 +++ 4 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/cpu/at32ap/at32ap700x/portmux.c b/cpu/at32ap/at32ap700x/portmux.c index 2a3b004..da0c9c5 100644 --- a/cpu/at32ap/at32ap700x/portmux.c +++ b/cpu/at32ap/at32ap700x/portmux.c @@ -202,3 +202,17 @@ void portmux_enable_spi1(unsigned long cs_mask, unsigned long drive_strength) PORTMUX_DIR_OUTPUT | PORTMUX_INIT_HIGH); } #endif + +#ifdef AT32AP700x_CHIP_HAS_LCDC +void portmux_enable_lcdc(void) +{ + /* + * FIXME: We want to allow the board much more control over + * which pins to enable + */ + portmux_select_peripheral(PORTMUX_PORT_C, 0xfff80000, + PORTMUX_FUNC_A, 0); + portmux_select_peripheral(PORTMUX_PORT_D, 0x0003ffff, + PORTMUX_FUNC_A, 0); +} +#endif diff --git a/include/asm-avr32/arch-at32ap700x/chip-features.h b/include/asm-avr32/arch-at32ap700x/chip-features.h index c47107e..b6bd1cd 100644 --- a/include/asm-avr32/arch-at32ap700x/chip-features.h +++ b/include/asm-avr32/arch-at32ap700x/chip-features.h @@ -32,4 +32,9 @@ #define AT32AP700x_CHIP_HAS_MACB #endif
+/* AP7001 doesn't have a LCD controller */ +#if defined(CONFIG_AT32AP7000) || defined(CONFIG_AT32AP7002) +#define AT32AP700x_CHIP_HAS_LCDC +#endif + #endif /* __ASM_AVR32_ARCH_CHIP_FEATURES_H__ */ diff --git a/include/asm-avr32/arch-at32ap700x/clk.h b/include/asm-avr32/arch-at32ap700x/clk.h index 21545a3..83a76f2 100644 --- a/include/asm-avr32/arch-at32ap700x/clk.h +++ b/include/asm-avr32/arch-at32ap700x/clk.h @@ -82,6 +82,12 @@ static inline unsigned long get_spi_clk_rate(unsigned int dev_id) return get_pba_clk_rate(); } #endif +#ifdef AT32AP700x_CHIP_HAS_LCDC +static inline unsigned long get_lcdc_clk_rate(unsigned int dev_id) +{ + return CONFIG_LCDC_PIXCLK_RATE; +} +#endif
extern void clk_init(void);
diff --git a/include/asm-avr32/arch-at32ap700x/portmux.h b/include/asm-avr32/arch-at32ap700x/portmux.h index 96fe70d..491d588 100644 --- a/include/asm-avr32/arch-at32ap700x/portmux.h +++ b/include/asm-avr32/arch-at32ap700x/portmux.h @@ -85,5 +85,8 @@ void portmux_enable_mmci(unsigned int slot, unsigned long flags, void portmux_enable_spi0(unsigned long cs_mask, unsigned long drive_strength); void portmux_enable_spi1(unsigned long cs_mask, unsigned long drive_strength); #endif +#ifdef AT32AP700x_CHIP_HAS_LCDC +void portmux_enable_lcdc(void); +#endif
#endif /* __ASM_AVR32_ARCH_PORTMUX_H__ */

Use lcd_setmem() to reserve memory for the LCD framebuffer before relocation.
Signed-off-by: Haavard Skinnemoen haavard.skinnemoen@atmel.com --- include/asm-avr32/global_data.h | 1 + lib_avr32/board.c | 6 ++++++ 2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/include/asm-avr32/global_data.h b/include/asm-avr32/global_data.h index 007cfe4..7510401 100644 --- a/include/asm-avr32/global_data.h +++ b/include/asm-avr32/global_data.h @@ -41,6 +41,7 @@ typedef struct global_data { unsigned long reloc_off; /* Relocation Offset */ unsigned long env_addr; /* Address of env struct */ unsigned long env_valid; /* Checksum of env valid? */ + unsigned long fb_base; /* Base address of frame buffer */ unsigned long cpu_hz; /* cpu core clock frequency */ void **jt; /* jump table */ } gd_t; diff --git a/lib_avr32/board.c b/lib_avr32/board.c index 4ed6c96..9bc475c 100644 --- a/lib_avr32/board.c +++ b/lib_avr32/board.c @@ -238,6 +238,12 @@ void board_init_f(ulong board_type) addr -= CFG_DMA_ALLOC_LEN; #endif
+#ifdef CONFIG_LCD + /* Reserve memory for LCD display (always full pages) */ + addr = lcd_setmem(addr); + gd->fb_base = addr; +#endif + /* Allocate a Board Info struct on a word boundary */ addr -= sizeof(bd_t); addr &= ~3UL;

Quite often, you only want to do a single SPI transfer with chip select toggling before and after. Add a simple convenience wrapper for this purpose. For more "advanced" usage, the spi_xfer() function is still available.
Signed-off-by: Haavard Skinnemoen haavard.skinnemoen@atmel.com --- include/spi.h | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/include/spi.h b/include/spi.h index 320e50e..be87173 100644 --- a/include/spi.h +++ b/include/spi.h @@ -176,6 +176,19 @@ void spi_cs_activate(struct spi_slave *slave); void spi_cs_deactivate(struct spi_slave *slave);
/*----------------------------------------------------------------------- + * Single SPI Transfer + * + * Convenience wrapper for doing a single SPI transfer, i.e. asserting + * CS before, and deasserting it after the transfer. + */ +static inline int spi_xfer_single(struct spi_slave *slave, + unsigned int bitlen, const void *dout, void *din) +{ + return spi_xfer(slave, bitlen, dout, din, + SPI_XFER_BEGIN | SPI_XFER_END); +} + +/*----------------------------------------------------------------------- * Write 8 bits, then read 8 bits. * slave: The SPI slave we're communicating with * byte: Byte to be written @@ -193,7 +206,7 @@ static inline int spi_w8r8(struct spi_slave *slave, unsigned char byte) dout[0] = byte; dout[1] = 0;
- ret = spi_xfer(slave, 16, dout, din, SPI_XFER_BEGIN | SPI_XFER_END); + ret = spi_xfer_single(slave, 16, dout, din); return ret < 0 ? ret : din[1]; }

From: Haavard Skinnemoen hskinnemoen@atmel.com
This adds mode definitions and initialization code for the on-board Samsung LTV350QV panel.
Signed-off-by: Haavard Skinnemoen hskinnemoen@atmel.com --- board/atmel/atstk1000/Makefile | 1 + board/atmel/atstk1000/ltv350qv.c | 157 ++++++++++++++++++++++++++++++++++++++ board/atmel/atstk1000/ltv350qv.h | 95 +++++++++++++++++++++++ 3 files changed, 253 insertions(+), 0 deletions(-) create mode 100644 board/atmel/atstk1000/ltv350qv.c create mode 100644 board/atmel/atstk1000/ltv350qv.h
diff --git a/board/atmel/atstk1000/Makefile b/board/atmel/atstk1000/Makefile index f9b26e5..8d4f32c 100644 --- a/board/atmel/atstk1000/Makefile +++ b/board/atmel/atstk1000/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)lib$(BOARD).a
COBJS-y += $(BOARD).o COBJS-y += flash.o +COBJS-$(CONFIG_LCD) += ltv350qv.o
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) diff --git a/board/atmel/atstk1000/ltv350qv.c b/board/atmel/atstk1000/ltv350qv.c new file mode 100644 index 0000000..5ea6793 --- /dev/null +++ b/board/atmel/atstk1000/ltv350qv.c @@ -0,0 +1,157 @@ +/* + * Power control for Samsung LTV350QV Quarter VGA LCD Panel + * + * Copyright (C) 2006, 2007 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <common.h> +#include <lcd.h> +#include <spi.h> + +#include "ltv350qv.h" + +/* + * The power-on and power-off sequences are taken from the + * LTV350QV-F04 data sheet from Samsung. The register definitions are + * taken from the S6F2002 command list also from Samsung. Both + * documents are distributed with the AVR32 Linux BSP CD from Atmel. + * + * There's still some voodoo going on here, but it's a lot better than + * in the first incarnation of the driver where all we had was the raw + * numbers from the initialization sequence. + */ +static int ltv350qv_write_reg(struct spi_slave *spi, u8 reg, u16 val) +{ + int ret; + u8 buffer[3]; + + /* register index */ + buffer[0] = LTV_OPC_INDEX; + buffer[1] = 0x00; + buffer[2] = reg & 0x7f; + + ret = spi_xfer_single(spi, 8 * 3, buffer, NULL); + if (ret) + return ret; + + /* register value */ + buffer[0] = LTV_OPC_DATA; + buffer[1] = val >> 8; + buffer[2] = val; + + return spi_xfer_single(spi, 8 * 3, buffer, NULL); +} + +/* The comments are taken straight from the data sheet */ +static int ltv350qv_power_on(struct spi_slave *spi) +{ + int ret; + + spi_claim_bus(spi); + + /* Power On Reset Display off State */ + if (ltv350qv_write_reg(spi, LTV_PWRCTL1, 0x0000)) + goto err; + udelay(15000); + + /* Power Setting Function 1 */ + if (ltv350qv_write_reg(spi, LTV_PWRCTL1, LTV_VCOM_DISABLE)) + goto err; + if (ltv350qv_write_reg(spi, LTV_PWRCTL2, LTV_VCOML_ENABLE)) + goto err_power1; + + /* Power Setting Function 2 */ + if (ltv350qv_write_reg(spi, LTV_PWRCTL1, + LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) + | LTV_SUPPLY_CURRENT(5))) + goto err_power2; + + udelay(55000); + + /* Instruction Setting */ + ret = ltv350qv_write_reg(spi, LTV_IFCTL, + LTV_NMD | LTV_REV | LTV_NL(0x1d)); + ret |= ltv350qv_write_reg(spi, LTV_DATACTL, + LTV_DS_SAME | LTV_CHS_480 + | LTV_DF_RGB | LTV_RGB_BGR); + ret |= ltv350qv_write_reg(spi, LTV_ENTRY_MODE, + LTV_VSPL_ACTIVE_LOW + | LTV_HSPL_ACTIVE_LOW + | LTV_DPL_SAMPLE_RISING + | LTV_EPL_ACTIVE_LOW + | LTV_SS_RIGHT_TO_LEFT); + ret |= ltv350qv_write_reg(spi, LTV_GATECTL1, LTV_CLW(3)); + ret |= ltv350qv_write_reg(spi, LTV_GATECTL2, + LTV_NW_INV_1LINE | LTV_FWI(3)); + ret |= ltv350qv_write_reg(spi, LTV_VBP, 0x000a); + ret |= ltv350qv_write_reg(spi, LTV_HBP, 0x0021); + ret |= ltv350qv_write_reg(spi, LTV_SOTCTL, LTV_SDT(3) | LTV_EQ(0)); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(0), 0x0103); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(1), 0x0301); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(2), 0x1f0f); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(3), 0x1f0f); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(4), 0x0707); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(5), 0x0307); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(6), 0x0707); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(7), 0x0000); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(8), 0x0004); + ret |= ltv350qv_write_reg(spi, LTV_GAMMA(9), 0x0000); + if (ret) + goto err_settings; + + /* Wait more than 2 frames */ + udelay(20000); + + /* Display On Sequence */ + ret = ltv350qv_write_reg(spi, LTV_PWRCTL1, + LTV_VCOM_DISABLE | LTV_VCOMOUT_ENABLE + | LTV_POWER_ON | LTV_DRIVE_CURRENT(5) + | LTV_SUPPLY_CURRENT(5)); + ret |= ltv350qv_write_reg(spi, LTV_GATECTL2, + LTV_NW_INV_1LINE | LTV_DSC | LTV_FWI(3)); + if (ret) + goto err_disp_on; + + /* Display should now be ON. Phew. */ + spi_release_bus(spi); + return 0; + +err_disp_on: + /* + * Try to recover. Error handling probably isn't very useful + * at this point, just make a best effort to switch the panel + * off. + */ + ltv350qv_write_reg(spi, LTV_PWRCTL1, + LTV_VCOM_DISABLE | LTV_DRIVE_CURRENT(5) + | LTV_SUPPLY_CURRENT(5)); + ltv350qv_write_reg(spi, LTV_GATECTL2, + LTV_NW_INV_1LINE | LTV_FWI(3)); +err_settings: +err_power2: +err_power1: + ltv350qv_write_reg(spi, LTV_PWRCTL2, 0x0000); + udelay(1000); +err: + ltv350qv_write_reg(spi, LTV_PWRCTL1, LTV_VCOM_DISABLE); + spi_release_bus(spi); + return -1; +} + +void lcd_enable(void) +{ + struct spi_slave *spi; + int ret = -1; + + spi = spi_setup_slave(0, CFG_LCD_NPCS, 800000, SPI_MODE_3); + if (spi) { + ret = ltv350qv_power_on(spi); + spi_free_slave(spi); + } + + if (ret) + puts("ATSTK1000: Failed to power on LCD panel\n"); +} diff --git a/board/atmel/atstk1000/ltv350qv.h b/board/atmel/atstk1000/ltv350qv.h new file mode 100644 index 0000000..189112e --- /dev/null +++ b/board/atmel/atstk1000/ltv350qv.h @@ -0,0 +1,95 @@ +/* + * Register definitions for Samsung LTV350QV Quarter VGA LCD Panel + * + * Copyright (C) 2006, 2007 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __LTV350QV_H +#define __LTV350QV_H + +#define LTV_OPC_INDEX 0x74 +#define LTV_OPC_DATA 0x76 + +#define LTV_ID 0x00 /* ID Read */ +#define LTV_IFCTL 0x01 /* Display Interface Control */ +#define LTV_DATACTL 0x02 /* Display Data Control */ +#define LTV_ENTRY_MODE 0x03 /* Entry Mode */ +#define LTV_GATECTL1 0x04 /* Gate Control 1 */ +#define LTV_GATECTL2 0x05 /* Gate Control 2 */ +#define LTV_VBP 0x06 /* Vertical Back Porch */ +#define LTV_HBP 0x07 /* Horizontal Back Porch */ +#define LTV_SOTCTL 0x08 /* Source Output Timing Control */ +#define LTV_PWRCTL1 0x09 /* Power Control 1 */ +#define LTV_PWRCTL2 0x0a /* Power Control 2 */ +#define LTV_GAMMA(x) (0x10 + (x)) /* Gamma control */ + +/* Bit definitions for LTV_IFCTL */ +#define LTV_IM (1 << 15) +#define LTV_NMD (1 << 14) +#define LTV_SSMD (1 << 13) +#define LTV_REV (1 << 7) +#define LTV_NL(x) (((x) & 0x001f) << 0) + +/* Bit definitions for LTV_DATACTL */ +#define LTV_DS_SAME (0 << 12) +#define LTV_DS_D_TO_S (1 << 12) +#define LTV_DS_S_TO_D (2 << 12) +#define LTV_CHS_384 (0 << 9) +#define LTV_CHS_480 (1 << 9) +#define LTV_CHS_492 (2 << 9) +#define LTV_DF_RGB (0 << 6) +#define LTV_DF_RGBX (1 << 6) +#define LTV_DF_XRGB (2 << 6) +#define LTV_RGB_RGB (0 << 2) +#define LTV_RGB_BGR (1 << 2) +#define LTV_RGB_GRB (2 << 2) +#define LTV_RGB_RBG (3 << 2) + +/* Bit definitions for LTV_ENTRY_MODE */ +#define LTV_VSPL_ACTIVE_LOW (0 << 15) +#define LTV_VSPL_ACTIVE_HIGH (1 << 15) +#define LTV_HSPL_ACTIVE_LOW (0 << 14) +#define LTV_HSPL_ACTIVE_HIGH (1 << 14) +#define LTV_DPL_SAMPLE_RISING (0 << 13) +#define LTV_DPL_SAMPLE_FALLING (1 << 13) +#define LTV_EPL_ACTIVE_LOW (0 << 12) +#define LTV_EPL_ACTIVE_HIGH (1 << 12) +#define LTV_SS_LEFT_TO_RIGHT (0 << 8) +#define LTV_SS_RIGHT_TO_LEFT (1 << 8) +#define LTV_STB (1 << 1) + +/* Bit definitions for LTV_GATECTL1 */ +#define LTV_CLW(x) (((x) & 0x0007) << 12) +#define LTV_GAON (1 << 5) +#define LTV_SDR (1 << 3) + +/* Bit definitions for LTV_GATECTL2 */ +#define LTV_NW_INV_FRAME (0 << 14) +#define LTV_NW_INV_1LINE (1 << 14) +#define LTV_NW_INV_2LINE (2 << 14) +#define LTV_DSC (1 << 12) +#define LTV_GIF (1 << 8) +#define LTV_FHN (1 << 7) +#define LTV_FTI(x) (((x) & 0x0003) << 4) +#define LTV_FWI(x) (((x) & 0x0003) << 0) + +/* Bit definitions for LTV_SOTCTL */ +#define LTV_SDT(x) (((x) & 0x0007) << 10) +#define LTV_EQ(x) (((x) & 0x0007) << 2) + +/* Bit definitions for LTV_PWRCTL1 */ +#define LTV_VCOM_DISABLE (1 << 14) +#define LTV_VCOMOUT_ENABLE (1 << 11) +#define LTV_POWER_ON (1 << 9) +#define LTV_DRIVE_CURRENT(x) (((x) & 0x0007) << 4) /* 0=off, 5=max */ +#define LTV_SUPPLY_CURRENT(x) (((x) & 0x0007) << 0) /* 0=off, 5=max */ + +/* Bit definitions for LTV_PWRCTL2 */ +#define LTV_VCOML_ENABLE (1 << 13) +#define LTV_VCOML_VOLTAGE(x) (((x) & 0x001f) << 8) /* 0=1V, 31=-1V */ +#define LTV_VCOMH_VOLTAGE(x) (((x) & 0x001f) << 0) /* 0=3V, 31=4.5V */ + +#endif /* __LTV350QV_H */

Add the necessary glue and enable LCD support on ATSTK1002 and ATSTK1006.
Signed-off-by: Haavard Skinnemoen haavard.skinnemoen@atmel.com --- board/atmel/atstk1000/atstk1000.c | 97 +++++++++++++++++++++++++++++++++++++ include/configs/atstk1002.h | 22 ++++++++ include/configs/atstk1006.h | 23 +++++++++ 3 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/board/atmel/atstk1000/atstk1000.c b/board/atmel/atstk1000/atstk1000.c index 31174d3..d88db5d 100644 --- a/board/atmel/atstk1000/atstk1000.c +++ b/board/atmel/atstk1000/atstk1000.c @@ -24,6 +24,7 @@ #include <asm/io.h> #include <asm/sdram.h> #include <asm/arch/clk.h> +#include <asm/arch/gpio.h> #include <asm/arch/hmatrix.h> #include <asm/arch/portmux.h>
@@ -72,8 +73,59 @@ static const struct sdram_config sdram_config = { #endif };
+#ifdef CONFIG_LCD +#include <lcd.h> +#include <atmel_lcdc.h> + +vidinfo_t panel_info = { + .vl_col = 320, + .vl_row = 240, + .vl_clk = 6891000, + .vl_sync = ATMEL_LCDC_INVCLK_INVERTED + | ATMEL_LCDC_INVFRAME_INVERTED + | ATMEL_LCDC_INVLINE_INVERTED, + .vl_bpix = LCD_BPP, + .vl_tft = 1, + .vl_hsync_len = 16, + .vl_left_margin = 17, + .vl_right_margin = 33, + .vl_vsync_len = 1, + .vl_upper_margin = 10, + .vl_lower_margin = 10, + .mmio = LCDC_BASE, +}; + +#ifdef CONFIG_LCD_INFO +#include <version.h> + +void lcd_show_board_info(void) +{ + unsigned int i; + unsigned long dram_size = 0; + char mhz[32]; + + lcd_printf("%s\n", U_BOOT_VERSION); + lcd_printf("%s (C) 2008 Atmel Corporation\n", CFG_BOARD_NAME); + lcd_printf("%s CPU at %s MHz\n", CFG_CPU_NAME, strmhz(mhz, gd->cpu_hz)); + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) + dram_size += gd->bd->bi_dram[i].size; + lcd_printf(" %ld MiB SDRAM, %ld MiB Flash\n", + dram_size >> 20, gd->bd->bi_flashsize >> 20); +} +#endif + +int board_postclk_init(void) +{ + gclk_set_rate(GCLK_LCDC_PIXCLK, GCLK_PARENT_PLL0, + CONFIG_LCDC_PIXCLK_RATE); + return 0; +} +#endif + int board_early_init_f(void) { + unsigned int spi_cs_mask = 0; + /* Enable SDRAM in the EBI mux */ hmatrix_slave_write(EBI, SFR, HMATRIX_BIT(EBI_SDRAM_ENABLE));
@@ -88,6 +140,16 @@ int board_early_init_f(void) #if defined(CONFIG_MMC) portmux_enable_mmci(0, PORTMUX_MMCI_4BIT, PORTMUX_DRIVE_LOW); #endif +#if defined(CONFIG_ATMEL_SPI) +#if defined(CONFIG_LCD) + spi_cs_mask |= 1 << CFG_LCD_NPCS; +#endif +#endif + if (spi_cs_mask) + portmux_enable_spi0(spi_cs_mask, PORTMUX_DRIVE_LOW); +#if defined(CONFIG_LCD) + portmux_enable_lcdc(); +#endif
return 0; } @@ -133,3 +195,38 @@ int board_eth_init(bd_t *bi) return 0; } #endif + +#ifdef CONFIG_ATMEL_SPI +#include <spi.h> + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ +#if defined(CONFIG_LCD) + if (bus == 0 && cs == CFG_LCD_NPCS) + return 1; +#endif + return 0; +} + +void spi_cs_activate(struct spi_slave *slave) +{ + switch (slave->cs) { +#ifdef CONFIG_LCD + case CFG_LCD_NPCS: + gpio_set_value(CFG_LCD_NPCS_PIN, 0); + break; +#endif + } +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + switch (slave->cs) { +#ifdef CONFIG_LCD + case CFG_LCD_NPCS: + gpio_set_value(CFG_LCD_NPCS_PIN, 1); + break; +#endif + } +} +#endif /* CONFIG_ATMEL_SPI */ diff --git a/include/configs/atstk1002.h b/include/configs/atstk1002.h index 4509416..dc20620 100644 --- a/include/configs/atstk1002.h +++ b/include/configs/atstk1002.h @@ -32,6 +32,9 @@ #define CONFIG_ATSTK1002 1 #define CONFIG_ATSTK1000 1
+#define CFG_CPU_NAME "AT32AP7000" +#define CFG_BOARD_NAME "ATSTK1002" + #define CONFIG_ATSTK1000_EXT_FLASH 1
/* @@ -129,6 +132,8 @@ #define CONFIG_BOOTP_SUBNETMASK #define CONFIG_BOOTP_GATEWAY
+/* LCD support. This will affect a few other settings */ +#define CONFIG_LCD 1
/* * Command line configuration. @@ -158,6 +163,23 @@ #define CONFIG_MMC 1 #define CONFIG_ATMEL_MCI 1
+#ifdef CONFIG_LCD +/* Second MACB conflicts with LCD signals */ +#undef CONFIG_ATSTK1000_MACB1 +#define CONFIG_ATMEL_SPI 1 +#define CFG_LCD_NPCS 1 +#define CFG_LCD_NPCS_PIN GPIO_PIN_PA(4) +#define CONFIG_ATMEL_LCD 1 +#define CONFIG_LCDC_PIXCLK_RATE PLL0_RATE +#define CONFIG_ATMEL_LCD_BGR555 1 +#define LCD_BPP LCD_COLOR8 +#define CONFIG_LCD_LOGO 1 +#define CONFIG_LCD_INFO 1 +#define CONFIG_LCD_INFO_BELOW_LOGO 1 +#define CFG_WHITE_ON_BLACK 1 +#define CFG_CONSOLE_IS_IN_ENV 1 +#endif + #define CFG_DCACHE_LINESZ 32 #define CFG_ICACHE_LINESZ 32
diff --git a/include/configs/atstk1006.h b/include/configs/atstk1006.h index 8a6c044..b97032f 100644 --- a/include/configs/atstk1006.h +++ b/include/configs/atstk1006.h @@ -32,6 +32,9 @@ #define CONFIG_ATSTK1006 1 #define CONFIG_ATSTK1000 1
+#define CFG_CPU_NAME "AT32AP7000" +#define CFG_BOARD_NAME "ATSTK1006" + #define CONFIG_ATSTK1000_EXT_FLASH 1
/* @@ -130,6 +133,9 @@ #define CONFIG_BOOTP_GATEWAY
+/* LCD support. This will affect a few other settings */ +#define CONFIG_LCD 1 + /* * Command line configuration. */ @@ -158,6 +164,23 @@ #define CONFIG_MMC 1 #define CONFIG_ATMEL_MCI 1
+#ifdef CONFIG_LCD +/* Second MACB conflicts with LCD signals */ +#undef CONFIG_ATSTK1000_MACB1 +#define CONFIG_ATMEL_SPI 1 +#define CFG_LCD_NPCS 1 +#define CFG_LCD_NPCS_PIN GPIO_PIN_PA(4) +#define CONFIG_ATMEL_LCD 1 +#define CONFIG_LCDC_PIXCLK_RATE PLL0_RATE +#define CONFIG_ATMEL_LCD_BGR555 1 +#define LCD_BPP LCD_COLOR8 +#define CONFIG_LCD_LOGO 1 +#define CONFIG_LCD_INFO 1 +#define CONFIG_LCD_INFO_BELOW_LOGO 1 +#define CFG_WHITE_ON_BLACK 1 +#define CFG_CONSOLE_IS_IN_ENV 1 +#endif + #define CFG_DCACHE_LINESZ 32 #define CFG_ICACHE_LINESZ 32

The following series adds support for the LCD panel on the ATSTK1000. To use this, you must first apply both of the following series:
http://lists.denx.de/pipermail/u-boot/2008-September/039826.html http://lists.denx.de/pipermail/u-boot/2008-September/039833.html
I'm a bit unsure what to do about this. While I certainly want LCD support out of the box on all boards that support it, this patchset brings the U-Boot image size dangerously close to 128k, which is the space we currently have available with the current MTD partitioning layout hardcoded into the kernel. With NAND flash support added on top of this, the ATSTK1006 image ends up at almost 150k, and there are still other features I'd like to support in the future, e.g. libfdt, Hush parser, USB, etc.
So this means I can either merge this as-is but disabled by default (which is bad from a testing perspective), disable some other features, or change the partitioning. Doing the latter will also make it possible to introduce redundant environment, but it means current kernels will break.
Since the ATSTK1000 doesn't actually ship with a filesystem in flash by default, the breakage will probably be limited to a handful of customized boards, but people who have done this kind of customization probably won't like that the flash layout changes behind their back.
What do everyone think about this? Is redundant environment and a boatload of features worth breaking compatibility with current kernels?
Haavard
I would prefer more testing over user/developer compability.
But if you resize the partition for u-boot be sure to resize to 256k and not 192k, since this would cause a lot more problems than needed for us using flash chips with 128k block size. Not a big problem but an issue.
I would love to see USB support implemented.
Regards Eirik Aanonsen

"Eirik Aanonsen" eaa@wprmedical.com wrote:
I would prefer more testing over user/developer compability.
Yes. I don't feel good about merging something which no boards use by default.
But if you resize the partition for u-boot be sure to resize to 256k and not 192k, since this would cause a lot more problems than needed for us using flash chips with 128k block size. Not a big problem but an issue.
I'm talking about changing the partitioning specifically on ATSTK1000. Other boards can do whatever they want. But it may be a good idea to reserve 256k anyway since it becomes less likely that we'll have to do the same thing all over again in the future.
Also note that we're not talking about increasing the size of the boot loader in general -- if you have a custom board and don't want to spend 256k of flash on the boot loader, you'll just have to not enable these space-consuming features.
I have to say I was a bit surprised by the size of the NAND code though. The LCD code is sort of excused since it sucks in a big uncompressed logo...
I would love to see USB support implemented.
Yeah...maybe I shouldn't have said that ;-) It would be cool to be able to run console over USB, but I don't know if U-Boot has any USB gadget support...so it might take a while to implement.
Haavard

I would prefer more testing over user/developer compability.
Yes. I don't feel good about merging something which no boards use by default.
But if you resize the partition for u-boot be sure to resize to 256k
and
not 192k, since this would cause a lot more problems than needed for
us
using flash chips with 128k block size. Not a big problem but an
issue.
I'm talking about changing the partitioning specifically on ATSTK1000. Other boards can do whatever they want. But it may be a good idea to reserve 256k anyway since it becomes less likely that we'll have to do the same thing all over again in the future.
But making it more likely to have equal partitions makes it easier to test kernels on different boards for debugging. I use my kernel on both the stk1000 and my own custom board. Then again no big deal but makes compliance/testing easier.
...
I have to say I was a bit surprised by the size of the NAND code though. The LCD code is sort of excused since it sucks in a big uncompressed logo...
Is there any plans for supporting the UBI/UBIFS, or is it planned? ( prob. not but yes it is large, but too large? )
I would love to see USB support implemented.
Yeah...maybe I shouldn't have said that ;-) It would be cool to be able to run console over USB, but I don't know if U-Boot has any USB gadget support...so it might take a while to implement.
I think besides a usb core there is not much useful released relating to gadget drivers at least. No, pressure :)
Haavard
Eirik Aa

"Eirik Aanonsen" eaa@wprmedical.com wrote:
I'm talking about changing the partitioning specifically on ATSTK1000. Other boards can do whatever they want. But it may be a good idea to reserve 256k anyway since it becomes less likely that we'll have to do the same thing all over again in the future.
But making it more likely to have equal partitions makes it easier to test kernels on different boards for debugging. I use my kernel on both the stk1000 and my own custom board. Then again no big deal but makes compliance/testing easier.
Right. I was thinking maybe we could extend the boot protocol to pass partitioning information from u-boot to the kernel -- that should make it possible to run the same kernel on boards with different flash layout as long as the in-flash u-boot is consistent with the flash layout.
One problem this doesn't solve is that if you load an older kernel which doesn't understand the extended boot protocol, it will keep using the old flash layout.
I have to say I was a bit surprised by the size of the NAND code though. The LCD code is sort of excused since it sucks in a big uncompressed logo...
Is there any plans for supporting the UBI/UBIFS, or is it planned? ( prob. not but yes it is large, but too large? )
I've seen some discussions with patches on the upstream u-boot list. Would be very nice to have.
I suspect some of the problem with the NAND code is all the default ops which aren't used by anything but can't be garbage collected by the linker because they are referenced by nand_set_defaults().
Haavard

On Tue, 2008-09-02 at 14:09 +0200, Haavard Skinnemoen wrote:
Right. I was thinking maybe we could extend the boot protocol to pass partitioning information from u-boot to the kernel -- that should make it possible to run the same kernel on boards with different flash layout as long as the in-flash u-boot is consistent with the flash layout.
If we do end up with libfdt on avr32 then we solve our problems here too, we can encapsulate this partitioning in the fdt image. But, as I understand it, that involves not only the actual libfdt support but making all avr32 driver nice and OF compatible. At least, if we want the fdt support to be _useful_ then that needs to happen (CMIIW).
One problem this doesn't solve is that if you load an older kernel which doesn't understand the extended boot protocol, it will keep using the old flash layout.
Doesn't the MTD system have facility to override partitioning information from the boot arguments? If so then any big u-boots can just ship with such a clause in their default bootargs, job done. Have to look in to that...
--Ben.

Ben Nizette bn@niasdigital.com wrote:
On Tue, 2008-09-02 at 14:09 +0200, Haavard Skinnemoen wrote:
Right. I was thinking maybe we could extend the boot protocol to pass partitioning information from u-boot to the kernel -- that should make it possible to run the same kernel on boards with different flash layout as long as the in-flash u-boot is consistent with the flash layout.
If we do end up with libfdt on avr32 then we solve our problems here too, we can encapsulate this partitioning in the fdt image.
Yes, we can probably do that. I guess it all depends on what we want to do first.
But, as I understand it, that involves not only the actual libfdt support but making all avr32 driver nice and OF compatible. At least, if we want the fdt support to be _useful_ then that needs to happen (CMIIW).
Or we could just add a glue layer which creates platform_devices based on the fdt information. Perhaps pass along a pointer to the device tree node for drivers that want to peek at it. PowerPC has a of_node in struct dev_archdata for this purpose I believe.
One problem this doesn't solve is that if you load an older kernel which doesn't understand the extended boot protocol, it will keep using the old flash layout.
Doesn't the MTD system have facility to override partitioning information from the boot arguments? If so then any big u-boots can just ship with such a clause in their default bootargs, job done. Have to look in to that...
Yes. But it won't fix boards which already have a valid environment and just want to upgrade u-boot. We could perhaps fix up the bootargs and add partitioning information when preparing to boot the kernel...
Haavard

On Wed, 2008-09-03 at 11:03 +0200, Haavard Skinnemoen wrote:
Ben Nizette bn@niasdigital.com wrote:
Doesn't the MTD system have facility to override partitioning information from the boot arguments? If so then any big u-boots can just ship with such a clause in their default bootargs, job done. Have to look in to that...
Yes. But it won't fix boards which already have a valid environment and just want to upgrade u-boot. We could perhaps fix up the bootargs and add partitioning information when preparing to boot the kernel...
Hmm, I don't think anything we do will fix the case of people just trying to upgrade u-boot but keeping an old environment. Fixing the partitioning information as the kernel sees it won't alter the actual partition layout in flash, we're going to need the user's help there, and if they're repartitioning their flash there's a good chance they just nuked their old environment anyway.
Right, I give in, prolly best to just keep the LCD support disabled by default, stick a page on the 'freaks wiki explaining all the steps to turn it on and try and point as many people towards that as possible.
--Ben.
participants (3)
-
Ben Nizette
-
Eirik Aanonsen
-
Haavard Skinnemoen