int arch_cpu_init(void)
{
s5p_set_cpu_id();
-#ifndef CONFIG_RECOVERY_BLOCK
+
s5p_clock_init();
-#endif
+
return 0;
}
#endif
#ifdef CONFIG_DISPLAY_CPUINFO
int print_cpuinfo(void)
{
-#ifndef CONFIG_RECOVERY_BLOCK
char buf[32];
printf("CPU:\tS5P%X@%sMHz\n",
s5p_cpu_id, strmhz(buf, get_arm_clk()));
-#endif
+
return 0;
}
#endif
.globl _start
_start: b reset
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
*
*************************************************************************/
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
.globl _TEXT_BASE
#endif
_TEXT_BASE:
.word TEXT_BASE
-#if defined(CONFIG_PRELOADER) || defined(CONFIG_RECOVERY_BLOCK)
+#if defined(CONFIG_PRELOADER)
.globl _armboot_start
_armboot_start:
.word _start
#endif
#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
/* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
orr r0, r0, #0xd3
msr cpsr,r0
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
#if (CONFIG_OMAP34XX)
/* Copy vectors to mask ROM indirect addr */
adr r0, _start @ r0 <- current position of code
bl cpy_clk_code @ put dpll adjust code behind vectors
#endif /* NAND Boot */
#endif
-#endif /* CONFIG_PRELOADER || CONFIG_RECOVERY_BLOCK */
+#endif /* CONFIG_PRELOADER */
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
-#if !defined(CONFIG_RECOVERY_BLOCK)
bl cpu_init_crit
#endif
-#endif
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
* after relocating the monitor code.
*
*/
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
_start_armboot: .word start_oneboot
#elif defined(CONFIG_MMC_IPL)
_start_armboot: .word start_mmcboot
-#elif defined(CONFIG_RECOVERY_BLOCK)
-_start_armboot: .word start_recovery_boot
#endif
#endif
#if !defined(CONFIG_SKIP_RELOCATE_UBOOT)
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
adr r0, _start
ldr r2, _TEXT_BASE
ldr r3, _bss_start
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
jump_2_ram:
ldr r0, _TEXT_BASE
ldr r2, _board_init_r
*
*************************************************************************/
cpu_init_crit:
-#if !defined(CONFIG_RECOVERY_BLOCK)
/*
* Invalidate L1 I/D
*/
bl lowlevel_init @ go setup pll,mux,memory
mov lr, ip @ restore link
mov pc, lr @ back to my caller
-#endif
-#if !defined(CONFIG_PRELOADER) && !defined(CONFIG_RECOVERY_BLOCK)
+#if !defined(CONFIG_PRELOADER)
/*
*************************************************************************
*
bl do_fiq
#endif
-#endif /* CONFIG_PRELOADER || CONFIG_RECOVERY_BLOCK */
+#endif /* CONFIG_PRELOADER */
fi
}
-make_recovery_image()
-{
- if [ "$IPL" != "mmc" ]; then
- cat recovery/recovery-evt0.bin u-boot.bin > u-boot-recovery-evt0.bin
- cat recovery/recovery-fused.bin u-boot.bin > u-boot-recovery-evt1-fused.bin
- cp u-boot-recovery.bin u-boot-recovery-evt1.bin
- fi
-}
-
check_ccache
check_users
check_ipl $1
build_uboot $*
make_evt_image
-#make_recovery_image
if [ "$IPL" != "mmc" ]; then
size=`ls -al u-boot-onenand.bin | awk -F' ' '{printf $5}'`
switch (img_type) {
case IMG_BOOT:
ofs = parts[part_id]->offset;
-#ifdef CONFIG_RECOVERY
- {
- /* block is fixed:
- 1m = ipl(16k)+recovery(240k)+bootloader(768k)*/
- long *buf = (long *)down_ram_addr;
- u32 ofst;
- u32 bootloader_edge = parts[part_id]->size;
- u32 bootloader_addr = bootloader_edge >> 2;
- u32 recovery_edge = bootloader_addr;
- u32 recovery_addr = recovery_edge >> 4;
- u32 ipl_addr = 0;
-
- if (len > bootloader_addr) {
- ofst = bootloader_addr / sizeof(buf);
- if (*(buf + ofst) == 0xea000012) {
- /* case: ipl + recovery + bootloader */
- printf("target: ipl + recovery + loader\n");
- ofs = ipl_addr;
- } else {
- /* case: unknown format */
- printf("target: unknown\n");
- *((ulong *) usbd->tx_data) = STATUS_ERROR;
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- return 0;
- }
- } else {
- ofst = recovery_addr/sizeof(buf);
- if (*(buf + ofst) == 0xea000012 &&
- *(buf + ofst - 1) == 0x00000000) {
- /* case: ipl + bootloader (old type) */
- printf("target: ipl + bootloader\n");
- ofs = ipl_addr;
- } else {
- /* case: bootloader only */
- printf("target: bootloader\n");
- ofs = bootloader_addr;
-
- /* skip revision check */
- down_mode = MODE_FORCE;
- }
- }
-
- sprintf(offset, "%x", (uint)ofs);
- sprintf(length, "%x", parts[part_id]->size);
-
- /* check block is locked/locked-tight */
- ret = nand_cmd(3, offset, length, NULL);
- if (ret) {
- printf("target is locked%s\n",
- (ret == 1) ? "-tight" : "");
- printf("-> try at recovery mode "
- "to update 'system'.\n");
- printf(" how-to: reset "
- "while pressing volume up and down.\n");
- *((ulong *) usbd->tx_data) = STATUS_ERROR;
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- return 0;
- }
- }
-#endif
#ifdef CONFIG_S5PC1XX
/* Workaround: for prevent revision mismatch */
if (cpu_is_s5pc110() && (down_mode != MODE_FORCE)) {
/* OneNAND IPL uses 8KiB */
#define CONFIG_ONENAND_START_PAGE 4
-/* IPL + RECOVERY + U-BOOT */
-#define CONFIG_RECOVERY_UBOOT_BLOCK 1
-#define CONFIG_RECOVERY_BOOT_BLOCKS 4
-
#define CONFIG_ENV_IS_IN_ONENAND 1
#define CONFIG_ENV_SIZE 4096
#define CONFIG_ENV_ADDR (1 << 20) /* 1 MB, 0x100000 */
-#define CONFIG_RECOVERY_SIZE (768 << 10) /* 768 KiB, 0xC0000 */
-#define CONFIG_RECOVERY_ADDR (256 << 10) /* 256 KiB, 0x40000 */
-
#define CONFIG_USE_ONENAND_BOARD_INIT
#define CONFIG_SAMSUNG_ONENAND 1
#define CONFIG_SYS_ONENAND_BASE 0xB0000000
/* OneNAND IPL uses 32KiB = 2KiB * 16 */
#define CONFIG_ONENAND_START_PAGE 16
-/* IPL + RECOVERY + U-BOOT */
-#define CONFIG_RECOVERY_UBOOT_BLOCK 1
-#define CONFIG_RECOVERY_BOOT_BLOCKS 4
-
#define CONFIG_ENV_IS_IN_ONENAND 1
#define CONFIG_ENV_SIZE 4096
#define CONFIG_ENV_ADDR (1 << 20) /* 1 MB, 0x100000 */
-#define CONFIG_RECOVERY_SIZE (768 << 10) /* 768 KiB, 0xC0000 */
-#define CONFIG_RECOVERY_ADDR (256 << 10) /* 256 KiB, 0x40000 */
-
#define CONFIG_USE_ONENAND_BOARD_INIT
#define CONFIG_SYS_ONENAND_BASE 0x0C000000
+++ /dev/null
-#
-# Samsung Universal(S5PC110) board Recovery block
-#
-# Copyright (C) 2010 Samsung Electronics
-# Minkyu Kang <mk7.kang@samsung.com>
-# Kyungmin Park <kyungmin.park@samsung.com>
-#
-
-include $(TOPDIR)/$(RECOVERY_BLOCK)/config.mk
-
-recoveryobj := $(SRCTREE)/$(RECOVERY_BLOCK)/
-
-# Recovery block' size should be 1 block (256K)
-# Recovery block includes the onenand_ipl(16K), so actual size is 240K
-# 256K - 16K(IPL Size)
-TEXT_BASE_256K = 0x3403C000
-
-OBJS = recovery.o
-OBJS += onenand.o
-OBJS += usbd.o
-OBJS += serial.o
-
-SRCS := $(OBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(OBJS))
-
-LIBS = drivers/onenand/libonenand.a
-LIBS += drivers/usb/libusb.a
-LIBS += drivers/serial/libserial.a
-LIBS := $(addprefix $(recoveryobj),$(LIBS))
-.PHONY : $(LIBS) $(TIMESTAMP_FILE) $(VERSION_FILE)
-
-LIBBOARD = board/$(BOARDDIR)/lib$(BOARD).a
-LIBBOARD := $(addprefix $(recoveryobj),$(LIBBOARD))
-
-# Add GCC lib
-PLATFORM_LIBGCC = -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
-
-__OBJS := $(subst $(obj),,$(OBJS))
-__LIBS := $(subst $(obj),,$(LIBS)) $(subst $(obj),,$(LIBBOARD))
-
-#########################################################################
-#########################################################################
-
-ALL = $(recoveryobj)recovery-256k.bin
-
-all: $(obj).depend $(ALL)
-
-$(recoveryobj)recovery-256k.bin: $(recoveryobj)recovery
- $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(TEXT_BASE_256K) -O binary $< $@
- cat $(OBJTREE)/onenand_ipl/onenand-ipl-16k-evt0.bin $@ > $(recoveryobj)recovery-evt0.bin
- cat $(OBJTREE)/onenand_ipl/onenand-ipl-16k-fused.bin $@ > $(recoveryobj)recovery-fused.bin
- cat $(OBJTREE)/onenand_ipl/onenand-ipl-16k.bin $@ > $(recoveryobj)recovery.bin
-
-$(recoveryobj)recovery: $(obj).depend $(OBJS) $(LIBS) $(LIBBOARD)
- $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
- --start-group $(__LIBS) --end-group $(PLATFORM_LIBGCC) \
- -Map $@.map -o $@
-
-$(LIBS):
- $(MAKE) -C $(dir $(subst $(obj),,$@))
-
-$(LIBBOARD): $(LIBS)
- $(MAKE) -C $(dir $(subst $(obj),,$@))
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+++ /dev/null
-#
-# Samsung Universal(S5PC110) board Recovery block
-#
-# Copyright (C) 2010 Samsung Electronics
-# Minkyu Kang <mk7.kang@samsung.com>
-# Kyungmin Park <kyungmin.park@samsung.com>
-#
-
-include $(TOPDIR)/$(RECOVERY_BLOCK)/config.mk
-
-LIB := $(obj)lib$(BOARD).a
-
-SOBJS = start.o reset.o _memcpy32.o
-COBJS = string.o dlmalloc.o cpu_info.o
-COBJS += gpio.o
-COBJS += universal.o
-
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(SOBJS) $(OBJS)
- $(AR) $(ARFLAGS) $@ $(SOBJS) $(OBJS)
-
-# create symbolic links from common files
-
-$(obj)start.S:
- @rm -f $@
- ln -s $(SRCTREE)/$(CPUDIR)/$@ $@
-
-$(obj)reset.S:
- @rm -f $@
- ln -s $(SRCTREE)/$(CPUDIR)/$(SOC)/$@ $@
-
-$(obj)cpu_info.c:
- @rm -f $@
- ln -s $(SRCTREE)/$(CPUDIR)/s5p-common/$@ $@
-
-$(obj)_memcpy32.S:
- ln -sf $(SRCTREE)/arch/$(ARCH)/lib/$@ $@
-
-$(obj)string.c:
- @rm -f $@
- ln -s $(SRCTREE)/lib/$@ $@
-
-$(obj)dlmalloc.c:
- @rm -f $@
- ln -s $(SRCTREE)/common/$@ $@
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+++ /dev/null
-#
-# Copyright (C) 2010 Samsung Electronics
-# Minkyu Kang <mk7.kang@samsung.com>
-# Kyungmin Park <kyungmin.park@samsung.com>
-#
-
-# On S5PC110 we use the 336 MiB OneDRAM bank at
-#
-# 0x30000000 to 0x35000000 (80MiB)
-# 0x40000000 to 0x50000000 (256MiB)
-#
-TEXT_BASE = 0x34000000
+++ /dev/null
-/*
- * Copyright (C) 2009-2010 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/gpio.h>
-
-#define CON_MASK(x) (0xf << ((x) << 2))
-#define CON_SFR(x, v) ((v) << ((x) << 2))
-
-#define DAT_MASK(x) (0x1 << (x))
-#define DAT_SET(x) (0x1 << (x))
-
-#define PULL_MASK(x) (0x3 << ((x) << 1))
-#define PULL_MODE(x, v) ((v) << ((x) << 1))
-
-#define DRV_MASK(x) (0x3 << ((x) << 1))
-#define DRV_SET(x, m) ((m) << ((x) << 1))
-#define RATE_MASK(x) (0x1 << (x + 16))
-#define RATE_SET(x) (0x1 << (x + 16))
-
-void gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
-{
- unsigned int value;
-
- value = readl(&bank->con);
- value &= ~CON_MASK(gpio);
- value |= CON_SFR(gpio, cfg);
- writel(value, &bank->con);
- value = readl(&bank->con);
-}
-
-void gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en)
-{
- unsigned int value;
-
- gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
-
- value = readl(&bank->dat);
- value &= ~DAT_MASK(gpio);
- if (en)
- value |= DAT_SET(gpio);
- writel(value, &bank->dat);
- value = readl(&bank->dat);
-}
-
-void gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
-{
- gpio_cfg_pin(bank, gpio, GPIO_INPUT);
-}
-
-void gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
-{
- unsigned int value;
-
- value = readl(&bank->dat);
- value &= ~DAT_MASK(gpio);
- if (en)
- value |= DAT_SET(gpio);
- writel(value, &bank->dat);
- value = readl(&bank->dat);
-}
-
-unsigned int gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
-{
- unsigned int value;
-
- value = readl(&bank->dat);
- return !!(value & DAT_MASK(gpio));
-}
-
-void gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
-{
- unsigned int value;
-
- value = readl(&bank->pull);
- value &= ~PULL_MASK(gpio);
-
- switch (mode) {
- case GPIO_PULL_DOWN:
- case GPIO_PULL_UP:
- value |= PULL_MODE(gpio, mode);
- break;
- default:
- break;
- }
-
- writel(value, &bank->pull);
- value = readl(&bank->pull);
-}
-
-void gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
-{
- unsigned int value;
-
- value = readl(&bank->drv);
- value &= ~DRV_MASK(gpio);
-
- switch (mode) {
- case GPIO_DRV_1X:
- case GPIO_DRV_2X:
- case GPIO_DRV_3X:
- case GPIO_DRV_4X:
- value |= DRV_SET(gpio, mode);
- break;
- default:
- return;
- }
-
- writel(value, &bank->drv);
- value = readl(&bank->drv);
-}
-
-void gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
-{
- unsigned int value;
-
- value = readl(&bank->drv);
- value &= ~RATE_MASK(gpio);
-
- switch (mode) {
- case GPIO_DRV_FAST:
- case GPIO_DRV_SLOW:
- value |= RATE_SET(gpio);
- break;
- default:
- return;
- }
-
- writel(value, &bank->drv);
- value = readl(&bank->drv);
-}
+++ /dev/null
-/*
- * Copyright (C) 2005-2010 Samsung Electronics
- * Kyungmin Park <kyungmin.park@samsung.com>
- */
-
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
- . = 0x00000000;
-
- . = ALIGN(4);
- .text :
- {
- board/samsung/universal_c100/start.o (.text)
- *(.text)
- }
-
- . = ALIGN(4);
- .rodata : { *(.rodata) }
-
- . = ALIGN(4);
- .data : { *(.data) }
-
- . = ALIGN(4);
- .got : { *(.got) }
-
- . = ALIGN(4);
- __bss_start = .;
- .bss : { *(.bss) }
- _end = .;
-}
+++ /dev/null
-/*
- * Copyright (C) 2009-2010 Samsung Electronics
- */
-
-#include <common.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/keypad.h>
-#include <asm/arch/power.h>
-#include "recovery.h"
-#include "onenand.h"
-
-#ifdef RECOVERY_DEBUG
-#define PUTS(s) serial_puts(DEBUG_MARK""s)
-#else
-#define PUTS(s)
-#endif
-
-#define C110_MACH_START 3100
-#define C100_MACH_START 3000
-
-/* board is MACH_AQUILA and board is like below. */
-#define J1_B2_BOARD 0x0200
-#define LIMO_UNIVERSAL_BOARD 0x0400
-#define LIMO_REAL_BOARD 0x0800
-#define MEDIA_BOARD 0x1000
-#define BAMBOO_BOARD 0x2000
-
-/* board is MACH_GONI and board is like below */
-#define S1_BOARD 0x1000
-#define KESSLER_BOARD 0x4000
-#define SDK_BOARD 0x8000
-
-#define BOARD_MASK 0xFF00
-
-enum {
- MACH_UNIVERSAL,
- MACH_TICKERTAPE,
- MACH_CHANGED,
- MACH_P1P2, /* Don't remove it */
- MACH_GEMINUS,
- MACH_CYPRESS,
-
- MACH_WMG160 = 160,
-
- MACH_PSEUDO_END,
-};
-
-typedef int (init_fnc_t) (void);
-
-static bd_t bd;
-
-static unsigned int board_rev;
-
-static void sdelay(unsigned long usec)
-{
- ulong kv;
-
- do {
- kv = 0x100000;
- while (kv)
- kv--;
- usec--;
- } while (usec);
-}
-
-static int hwrevision(int rev)
-{
- return (board_rev & 0xf) == rev;
-}
-
-static int c110_machine_id(void)
-{
- return bd.bi_arch_number - C110_MACH_START;
-}
-
-static int mach_is_aquila(void)
-{
- return bd.bi_arch_number == MACH_TYPE_AQUILA;
-}
-
-static int mach_is_geminus(void)
-{
- return c110_machine_id() == MACH_GEMINUS;
-}
-
-static int board_is_limo_universal(void)
-{
- return mach_is_aquila() && (board_rev & LIMO_UNIVERSAL_BOARD);
-}
-
-static int board_is_limo_real(void)
-{
- return mach_is_aquila() && (board_rev & LIMO_REAL_BOARD);
-}
-
-/* Kessler */
-static int mach_is_goni(void)
-{
- return bd.bi_arch_number == MACH_TYPE_GONI;
-}
-
-static int board_is_sdk(void)
-{
- return mach_is_goni() && (board_rev & SDK_BOARD);
-}
-
-/* DLNA Dongle */
-static int mach_is_wmg160(void)
-{
- return c110_machine_id() == MACH_WMG160;
-}
-
-static void check_board_revision(int board, int rev)
-{
- if (board == MACH_TYPE_AQUILA) {
- /* Limo Real or Universal */
- if (rev & LIMO_UNIVERSAL_BOARD)
- board_rev &= ~J1_B2_BOARD;
- if (rev & LIMO_REAL_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & MEDIA_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & BAMBOO_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD |
- LIMO_REAL_BOARD |
- MEDIA_BOARD);
- } else if (board == MACH_TYPE_GONI) {
- if (rev & KESSLER_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & SDK_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & S1_BOARD)
- board_rev &= ~(J1_B2_BOARD | LIMO_UNIVERSAL_BOARD |
- LIMO_REAL_BOARD);
- } else {
- board_rev &= ~BOARD_MASK;
- }
-}
-
-static unsigned int get_hw_revision(struct s5p_gpio_bank *bank, int hwrev3)
-{
- unsigned int rev;
-
- gpio_direction_input(bank, 2);
- gpio_direction_input(bank, 3);
- gpio_direction_input(bank, 4);
- gpio_direction_input(bank, hwrev3);
-
- gpio_set_pull(bank, 2, GPIO_PULL_NONE); /* HWREV_MODE0 */
- gpio_set_pull(bank, 3, GPIO_PULL_NONE); /* HWREV_MODE1 */
- gpio_set_pull(bank, 4, GPIO_PULL_NONE); /* HWREV_MODE2 */
- gpio_set_pull(bank, hwrev3, GPIO_PULL_NONE); /* HWREV_MODE3 */
-
- rev = gpio_get_value(bank, 2);
- rev |= (gpio_get_value(bank, 3) << 1);
- rev |= (gpio_get_value(bank, 4) << 2);
- rev |= (gpio_get_value(bank, hwrev3) << 3);
-
- return rev;
-}
-
-static void check_hw_revision(void)
-{
- unsigned int board = MACH_UNIVERSAL; /* Default is Universal */
-
- if (cpu_is_s5pc100()) {
- struct s5pc100_gpio *gpio =
- (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
-
- board_rev = get_hw_revision(&gpio->j0, 0);
-
- /* C100 TickerTape */
- if (board_rev == 3)
- board = MACH_TICKERTAPE;
- } else {
- struct s5pc110_gpio *gpio =
- (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
- int hwrev3 = 1;
-
- board_rev = 0;
-
- /*
- * Note Check 'Aquila' board first
- *
- * TT: TickerTape
- * SS: SplitScreen
- * LRA: Limo Real Aquila
- * LUA: Limo Universal Aquila
- * OA: Old Aquila
- * CYP: Cypress
- * BB: Bamboo
- *
- * ADDR = 0xE0200000 + OFF
- *
- * OFF Universal BB LRA LUA OA TT SS CYP
- * J1: 0x0264 0x10 0x10 0x00 0x00 0x00 0x00 0x00
- * J2: 0x0284 0x01 0x10 0x00
- * H1: 0x0C24 W 0x28 0xA8 0x1C 0x0F
- * H3: 0x0C64 0x03 0x07 0x0F
- * D1: 0x00C4 0x0F 0x3F 0x3F 0x0F 0xXC 0x3F
- * I: 0x0224 0x02 0x00 0x08
- * MP03: 0x0324 0x9x 0xbx 0x9x
- * MP05: 0x0364 0x80 0x88
- */
-
- /* C110 Aquila */
- if (gpio_get_value(&gpio->j1, 4) == 0) {
- board = MACH_TYPE_AQUILA;
- board_rev |= J1_B2_BOARD;
-
- gpio_set_pull(&gpio->j2, 6, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j2, 6);
-
- /* Check board */
- if (gpio_get_value(&gpio->h1, 2) == 0)
- board_rev |= LIMO_UNIVERSAL_BOARD;
-
- if (gpio_get_value(&gpio->h3, 2) == 0)
- board_rev |= LIMO_REAL_BOARD;
-
- if (gpio_get_value(&gpio->j2, 6) == 1)
- board_rev |= MEDIA_BOARD;
-
- /* set gpio to default value. */
- gpio_set_pull(&gpio->j2, 6, GPIO_PULL_DOWN);
- gpio_direction_output(&gpio->j2, 6, 0);
- }
-
- /* Workaround: C110 Aquila Rev0.6 */
- if (board_rev == 6) {
- board = MACH_TYPE_AQUILA;
- board_rev |= LIMO_REAL_BOARD;
- }
-
- /* C110 Aquila Bamboo */
- if (gpio_get_value(&gpio->j2, 0) == 1) {
- board = MACH_TYPE_AQUILA;
- board_rev |= BAMBOO_BOARD;
- }
-
- /* C110 TickerTape */
- if (gpio_get_value(&gpio->d1, 0) == 0 &&
- gpio_get_value(&gpio->d1, 1) == 0)
- board = MACH_TICKERTAPE;
-
- /* WMG160 - GPH3[0:4] = 0x00 */
- if (board == MACH_TICKERTAPE) {
- int i, wmg160 = 1;
-
- for (i = 0; i < 4; i++) {
- if (gpio_get_value(&gpio->h3, i) != 0) {
- wmg160 = 0;
- break;
- }
- }
- if (wmg160) {
- board = MACH_WMG160;
- hwrev3 = 7;
- }
- }
-
- /* C110 Geminus for rev0.0 */
- gpio_set_pull(&gpio->j1, 2, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j1, 2);
- if (gpio_get_value(&gpio->j1, 2) == 1) {
- board = MACH_GEMINUS;
- if ((board_rev & ~BOARD_MASK) == 3)
- board_rev &= ~0xff;
- }
- gpio_set_pull(&gpio->j1, 2, GPIO_PULL_DOWN);
- gpio_direction_output(&gpio->j1, 2, 0);
-
- /* C110 Geminus for rev0.1 ~ */
- gpio_set_pull(&gpio->j0, 6, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j0, 6);
- if (gpio_get_value(&gpio->j0, 6) == 1) {
- board = MACH_GEMINUS;
- hwrev3 = 7;
- }
- gpio_set_pull(&gpio->j0, 6, GPIO_PULL_DOWN);
-
- /* Kessler MP0_5[6] == 1 */
- gpio_direction_input(&gpio->mp0_5, 6);
- if (gpio_get_value(&gpio->mp0_5, 6) == 1) {
- /* Cypress: Do this for cypress */
- gpio_set_pull(&gpio->j2, 2, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j2, 2);
- if (gpio_get_value(&gpio->j2, 2) == 1) {
- board = MACH_CYPRESS;
- gpio_direction_output(&gpio->mp0_5, 6, 0);
- } else {
- board = MACH_TYPE_GONI;
- board_rev |= KESSLER_BOARD;
-
- /* Limo SDK MP0_5[4] == 1 */
- gpio_direction_input(&gpio->mp0_5, 4);
- if (gpio_get_value(&gpio->mp0_5, 4) == 1) {
- board_rev &= ~KESSLER_BOARD;
- board_rev |= SDK_BOARD;
- }
- }
- gpio_set_pull(&gpio->j2, 2, GPIO_PULL_DOWN);
- hwrev3 = 7;
- } else {
- gpio_direction_output(&gpio->mp0_5, 6, 0);
- /* Goni S1 board detection */
- if (board == MACH_TICKERTAPE) {
- board = MACH_TYPE_GONI;
- board_rev |= S1_BOARD;
- hwrev3 = 7;
- }
- }
-
- board_rev |= get_hw_revision(&gpio->j0, hwrev3);
- }
-
- /* Set machine id */
- if (board < MACH_PSEUDO_END) {
- if (cpu_is_s5pc110())
- bd.bi_arch_number = C110_MACH_START + board;
- else
- bd.bi_arch_number = C100_MACH_START + board;
- } else {
- bd.bi_arch_number = board;
- }
-}
-
-static void show_hw_revision(void)
-{
- int board;
-
- /*
- * Workaround for Rev 0.3 + CP Ver ES 3.1
- * it's Rev 0.4
- */
- if (board_is_limo_real()) {
- if (hwrevision(0)) {
- /* default is Rev 0.4 */
- board_rev &= ~0xf;
- board_rev |= 0x4;
- }
- }
-
- if (mach_is_goni() || mach_is_aquila())
- board = bd.bi_arch_number;
- else if (cpu_is_s5pc110())
- board = bd.bi_arch_number - C110_MACH_START;
- else
- board = bd.bi_arch_number - C100_MACH_START;
-
- check_board_revision(board, board_rev);
-
- /* Set CPU Revision */
- if (mach_is_aquila()) {
- if (board_is_limo_real()) {
- if ((board_rev & 0xf) < 8)
- s5p_set_cpu_rev(0);
- }
- } else if (mach_is_goni()) {
- if (board_is_sdk() &&
- (hwrevision(2) || hwrevision(4) || hwrevision(5)))
- s5p_set_cpu_rev(2); /* EVT1-Fused */
- else
- s5p_set_cpu_rev(1);
- } else if (mach_is_geminus()) {
- if ((board_rev & 0xf) < 1)
- s5p_set_cpu_rev(0);
- } else if (mach_is_wmg160()) {
- if (hwrevision(5))
- s5p_set_cpu_rev(0);
- else
- s5p_set_cpu_rev(2);
- } else {
- s5p_set_cpu_rev(0);
- }
-
- if (cpu_is_s5pc110())
- writel(0xc1100000 | (0xffff & (s5p_get_cpu_rev() ? 1 : 0)),
- S5PC110_INFORM3);
-}
-
-static int check_keypad(void)
-{
- uint condition = 0;
- uint reg, value;
- uint col_num, row_num;
- uint col_mask;
- uint col_mask_shift;
- uint row_state[4] = {0, 0, 0, 0};
- uint i;
- int cpu_rev;
-
- if (cpu_is_s5pc100()) {
- struct s5pc100_gpio *gpio =
- (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
-
- row_num = 3;
- col_num = 3;
-
- /* Set GPH2[2:0] to KP_COL[2:0] */
- gpio_cfg_pin(&gpio->h2, 0, 0x3);
- gpio_cfg_pin(&gpio->h2, 1, 0x3);
- gpio_cfg_pin(&gpio->h2, 2, 0x3);
-
- /* Set GPH3[2:0] to KP_ROW[2:0] */
- gpio_cfg_pin(&gpio->h3, 0, 0x3);
- gpio_cfg_pin(&gpio->h3, 1, 0x3);
- gpio_cfg_pin(&gpio->h3, 2, 0x3);
-
- reg = S5PC100_KEYPAD_BASE;
- col_mask = S5PC1XX_KEYIFCOL_MASK;
- col_mask_shift = 0;
- } else {
- struct s5pc110_gpio *gpio =
- (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
-
- if (mach_is_wmg160())
- return 0;
-
- if (board_is_limo_real() || board_is_limo_universal()) {
- row_num = 2;
- col_num = 3;
- } else {
- row_num = 4;
- col_num = 4;
- }
-
- for (i = 0; i < row_num; i++) {
- /* Set GPH3[3:0] to KP_ROW[3:0] */
- gpio_cfg_pin(&gpio->h3, i, 0x3);
- gpio_set_pull(&gpio->h3, i, GPIO_PULL_UP);
- }
-
- for (i = 0; i < col_num; i++)
- /* Set GPH2[3:0] to KP_COL[3:0] */
- gpio_cfg_pin(&gpio->h2, i, 0x3);
-
- reg = S5PC110_KEYPAD_BASE;
- col_mask = S5PC110_KEYIFCOLEN_MASK;
- col_mask_shift = 8;
- }
-
- /* KEYIFCOL reg clear */
- writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
-
- /* key_scan */
- for (i = 0; i < col_num; i++) {
- value = col_mask;
- value &= ~(1 << i) << col_mask_shift;
-
- writel(value, reg + S5PC1XX_KEYIFCOL_OFFSET);
- sdelay(1000);
-
- value = readl(reg + S5PC1XX_KEYIFROW_OFFSET);
- row_state[i] = ~value & ((1 << row_num) - 1);
- }
-
- /* KEYIFCOL reg clear */
- writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
-
- cpu_rev = s5p_get_cpu_rev();
- if (cpu_rev == 1) {
- if ((row_state[1] & 0x6) == 0x6)
- condition = 1;
- } else if (cpu_rev == 2) {
- if ((row_state[2] & 0x6) == 0x6)
- condition = 1;
- } else {
- if ((row_state[1] & 0x3) == 0x3)
- condition = 1;
- }
-
- return condition;
-}
-
-static int check_block(void)
-{
- struct onenand_op *onenand_ops = onenand_get_interface();
- struct mtd_info *mtd = onenand_ops->mtd;
- struct onenand_chip *this = mtd->priv;
- int i;
- int retlen = 0;
- u32 from = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- u32 len = 1 << this->erase_shift;
- u32 *buf = (u32 *)CONFIG_SYS_DOWN_ADDR;
-
- /* check first page of bootloader*/
- onenand_ops->read(from, len, (ssize_t *)&retlen, (u_char *)buf, 0);
- if (retlen != len)
- return 1;
-
- for (i = 0; i < (this->writesize / sizeof(this->writesize)); i++)
- if (*(buf + i) != 0xffffffff)
- return 0;
-
- return 1;
-}
-
-int board_check_condition(void)
-{
- if (check_keypad()) {
- PUTS("check: manual\n");
- return 1;
- }
-
- if (check_block()) {
- PUTS("check: bootloader broken\n");
- return 2;
- }
-
- return 0;
-}
-
-int board_load_bootloader(unsigned char *buf)
-{
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
- u32 ofs, len, retlen;
-
- ofs = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- len = CONFIG_SYS_MONITOR_LEN;
-
- mtd->read(mtd, ofs, len, &retlen, buf);
-
- if (len != retlen)
- return -1;
-
- return 0;
-}
-
-int board_lock_recoveryblock(void)
-{
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
- u32 ofs = 0;
- u32 len = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- int ret = 0;
-
- /* lock-tight the recovery block */
- if (this->lock_tight != NULL)
- ret = this->lock_tight(mtd, ofs, len);
-
- return ret;
-}
-
-void board_update_init(void)
-{
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
-
- /* Unlock whole block */
- this->unlock_all(mtd);
-}
-
-int board_update_image(u32 *buf, u32 len)
-{
- struct onenand_op *onenand_ops = onenand_get_interface();
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
- u32 ofs;
- u32 ipl_addr = 0;
- u32 ipl_edge = CONFIG_ONENAND_START_PAGE << this->page_shift;
- u32 recovery_addr = ipl_edge;
- u32 recovery_edge = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- u32 bootloader_addr = recovery_edge;
- int ret, retlen;
-
- if (len > bootloader_addr) {
- if (*(buf + bootloader_addr/sizeof(buf)) == 0xea000012) {
- /* case: IPL + Recovery + bootloader */
- PUTS("target: ipl + recovery + bootloader\n");
- ofs = ipl_addr;
- /* len = bootloader_edge; */
- } else {
- /* case: unknown format */
- PUTS("target: unknown\n");
- return 1;
- }
- } else {
- if (*(buf + recovery_addr/sizeof(buf)) == 0xea000012 &&
- *(buf + recovery_addr/sizeof(buf) - 1) == 0x00000000) {
- /* case: old image (IPL + bootloader) */
- PUTS("target: ipl + bootloader (old type)\n");
- ofs = ipl_addr;
- /* len = recovery_edge; */
- } else {
- /* case: bootloader only */
- PUTS("target: bootloader\n");
- ofs = bootloader_addr;
- /* len = bootloader_edge - recovery_edge; */
- }
- }
-
-#ifdef CONFIG_S5P
- /* Workaround: for prevent revision mismatch */
- if (cpu_is_s5pc110() && (ofs == 0)) {
- int img_rev;
-
- if (*buf == 0xea000012)
- img_rev = 0;
- else if (*(buf + 0x400) == 0xea000012)
- img_rev = 2;
- else
- img_rev = 1;
-
- if (img_rev != s5p_get_cpu_rev()) {
- PUTS("target check: CPU revision mismatch!\n");
- PUTS("target check: system is ");
- if (s5p_get_cpu_rev() == 1)
- serial_puts("EVT1\n");
- else if (s5p_get_cpu_rev() == 2)
- serial_puts("EVT1-Fused\n");
- else
- serial_puts("EVT0\n");
- PUTS("target check: download image is ");
- if (img_rev == 1)
- serial_puts("EVT1\n");
- else if (img_rev == 2)
- serial_puts("EVT1-Fused\n");
- else
- serial_puts("EVT0\n");
- PUTS("try again.");
- return 1;
- }
- }
-#endif
-
- /* Erase */
- ret = onenand_ops->erase(ofs, len, 0);
- if (ret)
- return ret;
-
- /* Write */
- onenand_ops->write(ofs, len, (ssize_t *)&retlen, (u_char *)buf);
- if (ret)
- return ret;
-
- return 0;
-}
-
-void board_recovery_init(void)
-{
- struct s5pc110_gpio *gpio =
- (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
-
- /* basic arch cpu dependent setup */
- arch_cpu_init();
-
- /* Check H/W Revision */
- check_hw_revision();
-
- show_hw_revision();
-
- /* set GPIO to enable UART2 */
- gpio_cfg_pin(&gpio->a1, 0, 0x2);
- gpio_cfg_pin(&gpio->a1, 1, 0x2);
-
- /* UART_SEL MP0_5[7] at S5PC110 */
- gpio_direction_output(&gpio->mp0_5, 7, 0x1);
- gpio_set_pull(&gpio->mp0_5, 7, GPIO_PULL_DOWN);
-}
+++ /dev/null
-#
-# Samsung Universal(S5PC110) board Recovery block
-#
-# Copyright (C) 2010 Samsung Electronics
-# Minkyu Kang <mk7.kang@samsung.com>
-# Kyungmin Park <kyungmin.park@samsung.com>
-#
-
-include $(TOPDIR)/$(RECOVERY_BLOCK)/config.mk
-
-LIB := $(obj)lib$(BOARD).a
-
-SOBJS = start.o reset.o _memcpy32.o
-COBJS = string.o dlmalloc.o cpu_info.o
-COBJS += gpio.o
-COBJS += universal.o
-
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(SOBJS) $(OBJS)
- $(AR) $(ARFLAGS) $@ $(SOBJS) $(OBJS)
-
-# create symbolic links from common files
-
-$(obj)start.S:
- @rm -f $@
- ln -s $(SRCTREE)/$(CPUDIR)/$@ $@
-
-$(obj)reset.S:
- @rm -f $@
- ln -s $(SRCTREE)/$(CPUDIR)/$(SOC)/$@ $@
-
-$(obj)cpu_info.c:
- @rm -f $@
- ln -s $(SRCTREE)/$(CPUDIR)/s5p-common/$@ $@
-
-$(obj)_memcpy32.S:
- ln -sf $(SRCTREE)/arch/$(ARCH)/lib/$@ $@
-
-$(obj)string.c:
- @rm -f $@
- ln -s $(SRCTREE)/lib/$@ $@
-
-$(obj)dlmalloc.c:
- @rm -f $@
- ln -s $(SRCTREE)/common/$@ $@
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+++ /dev/null
-#
-# Copyright (C) 2010 Samsung Electronics
-# Minkyu Kang <mk7.kang@samsung.com>
-# Kyungmin Park <kyungmin.park@samsung.com>
-#
-
-# On S5PC110 we use the 336 MiB OneDRAM bank at
-#
-# 0x30000000 to 0x35000000 (80MiB)
-# 0x40000000 to 0x50000000 (256MiB)
-#
-TEXT_BASE = 0x34000000
+++ /dev/null
-/*
- * Copyright (C) 2009-2010 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/gpio.h>
-
-#define CON_MASK(x) (0xf << ((x) << 2))
-#define CON_SFR(x, v) ((v) << ((x) << 2))
-
-#define DAT_MASK(x) (0x1 << (x))
-#define DAT_SET(x) (0x1 << (x))
-
-#define PULL_MASK(x) (0x3 << ((x) << 1))
-#define PULL_MODE(x, v) ((v) << ((x) << 1))
-
-#define DRV_MASK(x) (0x3 << ((x) << 1))
-#define DRV_SET(x, m) ((m) << ((x) << 1))
-#define RATE_MASK(x) (0x1 << (x + 16))
-#define RATE_SET(x) (0x1 << (x + 16))
-
-void gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg)
-{
- unsigned int value;
-
- value = readl(&bank->con);
- value &= ~CON_MASK(gpio);
- value |= CON_SFR(gpio, cfg);
- writel(value, &bank->con);
- value = readl(&bank->con);
-}
-
-void gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int en)
-{
- unsigned int value;
-
- gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
-
- value = readl(&bank->dat);
- value &= ~DAT_MASK(gpio);
- if (en)
- value |= DAT_SET(gpio);
- writel(value, &bank->dat);
- value = readl(&bank->dat);
-}
-
-void gpio_direction_input(struct s5p_gpio_bank *bank, int gpio)
-{
- gpio_cfg_pin(bank, gpio, GPIO_INPUT);
-}
-
-void gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int en)
-{
- unsigned int value;
-
- value = readl(&bank->dat);
- value &= ~DAT_MASK(gpio);
- if (en)
- value |= DAT_SET(gpio);
- writel(value, &bank->dat);
- value = readl(&bank->dat);
-}
-
-unsigned int gpio_get_value(struct s5p_gpio_bank *bank, int gpio)
-{
- unsigned int value;
-
- value = readl(&bank->dat);
- return !!(value & DAT_MASK(gpio));
-}
-
-void gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode)
-{
- unsigned int value;
-
- value = readl(&bank->pull);
- value &= ~PULL_MASK(gpio);
-
- switch (mode) {
- case GPIO_PULL_DOWN:
- case GPIO_PULL_UP:
- value |= PULL_MODE(gpio, mode);
- break;
- default:
- break;
- }
-
- writel(value, &bank->pull);
- value = readl(&bank->pull);
-}
-
-void gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode)
-{
- unsigned int value;
-
- value = readl(&bank->drv);
- value &= ~DRV_MASK(gpio);
-
- switch (mode) {
- case GPIO_DRV_1X:
- case GPIO_DRV_2X:
- case GPIO_DRV_3X:
- case GPIO_DRV_4X:
- value |= DRV_SET(gpio, mode);
- break;
- default:
- return;
- }
-
- writel(value, &bank->drv);
- value = readl(&bank->drv);
-}
-
-void gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode)
-{
- unsigned int value;
-
- value = readl(&bank->drv);
- value &= ~RATE_MASK(gpio);
-
- switch (mode) {
- case GPIO_DRV_FAST:
- case GPIO_DRV_SLOW:
- value |= RATE_SET(gpio);
- break;
- default:
- return;
- }
-
- writel(value, &bank->drv);
- value = readl(&bank->drv);
-}
+++ /dev/null
-/*
- * Copyright (C) 2005-2010 Samsung Electronics
- * Kyungmin Park <kyungmin.park@samsung.com>
- */
-
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
- . = 0x00000000;
-
- . = ALIGN(4);
- .text :
- {
- board/samsung/universal_c110/start.o (.text)
- *(.text)
- }
-
- . = ALIGN(4);
- .rodata : { *(.rodata) }
-
- . = ALIGN(4);
- .data : { *(.data) }
-
- . = ALIGN(4);
- .got : { *(.got) }
-
- . = ALIGN(4);
- __bss_start = .;
- .bss : { *(.bss) }
- _end = .;
-}
+++ /dev/null
-/*
- * Copyright (C) 2009-2010 Samsung Electronics
- */
-
-#include <common.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-#include <asm/io.h>
-#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
-#include <asm/arch/keypad.h>
-#include <asm/arch/power.h>
-#include "recovery.h"
-#include "onenand.h"
-
-#ifdef RECOVERY_DEBUG
-#define PUTS(s) serial_puts(DEBUG_MARK""s)
-#else
-#define PUTS(s)
-#endif
-
-#define C110_MACH_START 3100
-#define C100_MACH_START 3000
-
-/* board is MACH_AQUILA and board is like below. */
-#define J1_B2_BOARD 0x0200
-#define LIMO_UNIVERSAL_BOARD 0x0400
-#define LIMO_REAL_BOARD 0x0800
-#define MEDIA_BOARD 0x1000
-#define BAMBOO_BOARD 0x2000
-
-/* board is MACH_GONI and board is like below */
-#define S1_BOARD 0x1000
-#define KESSLER_BOARD 0x4000
-#define SDK_BOARD 0x8000
-
-#define BOARD_MASK 0xFF00
-
-enum {
- MACH_UNIVERSAL,
- MACH_TICKERTAPE,
- MACH_CHANGED,
- MACH_P1P2, /* Don't remove it */
- MACH_GEMINUS,
- MACH_CYPRESS,
-
- MACH_WMG160 = 160,
-
- MACH_PSEUDO_END,
-};
-
-typedef int (init_fnc_t) (void);
-
-static bd_t bd;
-
-static unsigned int board_rev;
-
-static void sdelay(unsigned long usec)
-{
- ulong kv;
-
- do {
- kv = 0x100000;
- while (kv)
- kv--;
- usec--;
- } while (usec);
-}
-
-static int hwrevision(int rev)
-{
- return (board_rev & 0xf) == rev;
-}
-
-static int c110_machine_id(void)
-{
- return bd.bi_arch_number - C110_MACH_START;
-}
-
-static int mach_is_aquila(void)
-{
- return bd.bi_arch_number == MACH_TYPE_AQUILA;
-}
-
-static int mach_is_geminus(void)
-{
- return c110_machine_id() == MACH_GEMINUS;
-}
-
-static int board_is_limo_universal(void)
-{
- return mach_is_aquila() && (board_rev & LIMO_UNIVERSAL_BOARD);
-}
-
-static int board_is_limo_real(void)
-{
- return mach_is_aquila() && (board_rev & LIMO_REAL_BOARD);
-}
-
-/* Kessler */
-static int mach_is_goni(void)
-{
- return bd.bi_arch_number == MACH_TYPE_GONI;
-}
-
-static int board_is_sdk(void)
-{
- return mach_is_goni() && (board_rev & SDK_BOARD);
-}
-
-/* DLNA Dongle */
-static int mach_is_wmg160(void)
-{
- return c110_machine_id() == MACH_WMG160;
-}
-
-static void check_board_revision(int board, int rev)
-{
- if (board == MACH_TYPE_AQUILA) {
- /* Limo Real or Universal */
- if (rev & LIMO_UNIVERSAL_BOARD)
- board_rev &= ~J1_B2_BOARD;
- if (rev & LIMO_REAL_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & MEDIA_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & BAMBOO_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD |
- LIMO_REAL_BOARD |
- MEDIA_BOARD);
- } else if (board == MACH_TYPE_GONI) {
- if (rev & KESSLER_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & SDK_BOARD)
- board_rev &= ~(J1_B2_BOARD |
- LIMO_UNIVERSAL_BOARD);
- if (rev & S1_BOARD)
- board_rev &= ~(J1_B2_BOARD | LIMO_UNIVERSAL_BOARD |
- LIMO_REAL_BOARD);
- } else {
- board_rev &= ~BOARD_MASK;
- }
-}
-
-static unsigned int get_hw_revision(struct s5p_gpio_bank *bank, int hwrev3)
-{
- unsigned int rev;
-
- gpio_direction_input(bank, 2);
- gpio_direction_input(bank, 3);
- gpio_direction_input(bank, 4);
- gpio_direction_input(bank, hwrev3);
-
- gpio_set_pull(bank, 2, GPIO_PULL_NONE); /* HWREV_MODE0 */
- gpio_set_pull(bank, 3, GPIO_PULL_NONE); /* HWREV_MODE1 */
- gpio_set_pull(bank, 4, GPIO_PULL_NONE); /* HWREV_MODE2 */
- gpio_set_pull(bank, hwrev3, GPIO_PULL_NONE); /* HWREV_MODE3 */
-
- rev = gpio_get_value(bank, 2);
- rev |= (gpio_get_value(bank, 3) << 1);
- rev |= (gpio_get_value(bank, 4) << 2);
- rev |= (gpio_get_value(bank, hwrev3) << 3);
-
- return rev;
-}
-
-static void check_hw_revision(void)
-{
- unsigned int board = MACH_UNIVERSAL; /* Default is Universal */
-
- if (cpu_is_s5pc100()) {
- struct s5pc100_gpio *gpio =
- (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
-
- board_rev = get_hw_revision(&gpio->j0, 0);
-
- /* C100 TickerTape */
- if (board_rev == 3)
- board = MACH_TICKERTAPE;
- } else {
- struct s5pc110_gpio *gpio =
- (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
- int hwrev3 = 1;
-
- board_rev = 0;
-
- /*
- * Note Check 'Aquila' board first
- *
- * TT: TickerTape
- * SS: SplitScreen
- * LRA: Limo Real Aquila
- * LUA: Limo Universal Aquila
- * OA: Old Aquila
- * CYP: Cypress
- * BB: Bamboo
- *
- * ADDR = 0xE0200000 + OFF
- *
- * OFF Universal BB LRA LUA OA TT SS CYP
- * J1: 0x0264 0x10 0x10 0x00 0x00 0x00 0x00 0x00
- * J2: 0x0284 0x01 0x10 0x00
- * H1: 0x0C24 W 0x28 0xA8 0x1C 0x0F
- * H3: 0x0C64 0x03 0x07 0x0F
- * D1: 0x00C4 0x0F 0x3F 0x3F 0x0F 0xXC 0x3F
- * I: 0x0224 0x02 0x00 0x08
- * MP03: 0x0324 0x9x 0xbx 0x9x
- * MP05: 0x0364 0x80 0x88
- */
-
- /* C110 Aquila */
- if (gpio_get_value(&gpio->j1, 4) == 0) {
- board = MACH_TYPE_AQUILA;
- board_rev |= J1_B2_BOARD;
-
- gpio_set_pull(&gpio->j2, 6, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j2, 6);
-
- /* Check board */
- if (gpio_get_value(&gpio->h1, 2) == 0)
- board_rev |= LIMO_UNIVERSAL_BOARD;
-
- if (gpio_get_value(&gpio->h3, 2) == 0)
- board_rev |= LIMO_REAL_BOARD;
-
- if (gpio_get_value(&gpio->j2, 6) == 1)
- board_rev |= MEDIA_BOARD;
-
- /* set gpio to default value. */
- gpio_set_pull(&gpio->j2, 6, GPIO_PULL_DOWN);
- gpio_direction_output(&gpio->j2, 6, 0);
- }
-
- /* Workaround: C110 Aquila Rev0.6 */
- if (board_rev == 6) {
- board = MACH_TYPE_AQUILA;
- board_rev |= LIMO_REAL_BOARD;
- }
-
- /* C110 Aquila Bamboo */
- if (gpio_get_value(&gpio->j2, 0) == 1) {
- board = MACH_TYPE_AQUILA;
- board_rev |= BAMBOO_BOARD;
- }
-
- /* C110 TickerTape */
- if (gpio_get_value(&gpio->d1, 0) == 0 &&
- gpio_get_value(&gpio->d1, 1) == 0)
- board = MACH_TICKERTAPE;
-
- /* WMG160 - GPH3[0:4] = 0x00 */
- if (board == MACH_TICKERTAPE) {
- int i, wmg160 = 1;
-
- for (i = 0; i < 4; i++) {
- if (gpio_get_value(&gpio->h3, i) != 0) {
- wmg160 = 0;
- break;
- }
- }
- if (wmg160) {
- board = MACH_WMG160;
- hwrev3 = 7;
- }
- }
-
- /* C110 Geminus for rev0.0 */
- gpio_set_pull(&gpio->j1, 2, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j1, 2);
- if (gpio_get_value(&gpio->j1, 2) == 1) {
- board = MACH_GEMINUS;
- if ((board_rev & ~BOARD_MASK) == 3)
- board_rev &= ~0xff;
- }
- gpio_set_pull(&gpio->j1, 2, GPIO_PULL_DOWN);
- gpio_direction_output(&gpio->j1, 2, 0);
-
- /* C110 Geminus for rev0.1 ~ */
- gpio_set_pull(&gpio->j0, 6, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j0, 6);
- if (gpio_get_value(&gpio->j0, 6) == 1) {
- board = MACH_GEMINUS;
- hwrev3 = 7;
- }
- gpio_set_pull(&gpio->j0, 6, GPIO_PULL_DOWN);
-
- /* Kessler MP0_5[6] == 1 */
- gpio_direction_input(&gpio->mp0_5, 6);
- if (gpio_get_value(&gpio->mp0_5, 6) == 1) {
- /* Cypress: Do this for cypress */
- gpio_set_pull(&gpio->j2, 2, GPIO_PULL_NONE);
- gpio_direction_input(&gpio->j2, 2);
- if (gpio_get_value(&gpio->j2, 2) == 1) {
- board = MACH_CYPRESS;
- gpio_direction_output(&gpio->mp0_5, 6, 0);
- } else {
- board = MACH_TYPE_GONI;
- board_rev |= KESSLER_BOARD;
-
- /* Limo SDK MP0_5[4] == 1 */
- gpio_direction_input(&gpio->mp0_5, 4);
- if (gpio_get_value(&gpio->mp0_5, 4) == 1) {
- board_rev &= ~KESSLER_BOARD;
- board_rev |= SDK_BOARD;
- }
- }
- gpio_set_pull(&gpio->j2, 2, GPIO_PULL_DOWN);
- hwrev3 = 7;
- } else {
- gpio_direction_output(&gpio->mp0_5, 6, 0);
- /* Goni S1 board detection */
- if (board == MACH_TICKERTAPE) {
- board = MACH_TYPE_GONI;
- board_rev |= S1_BOARD;
- hwrev3 = 7;
- }
- }
-
- board_rev |= get_hw_revision(&gpio->j0, hwrev3);
- }
-
- /* Set machine id */
- if (board < MACH_PSEUDO_END) {
- if (cpu_is_s5pc110())
- bd.bi_arch_number = C110_MACH_START + board;
- else
- bd.bi_arch_number = C100_MACH_START + board;
- } else {
- bd.bi_arch_number = board;
- }
-}
-
-static void show_hw_revision(void)
-{
- int board;
-
- /*
- * Workaround for Rev 0.3 + CP Ver ES 3.1
- * it's Rev 0.4
- */
- if (board_is_limo_real()) {
- if (hwrevision(0)) {
- /* default is Rev 0.4 */
- board_rev &= ~0xf;
- board_rev |= 0x4;
- }
- }
-
- if (mach_is_goni() || mach_is_aquila())
- board = bd.bi_arch_number;
- else if (cpu_is_s5pc110())
- board = bd.bi_arch_number - C110_MACH_START;
- else
- board = bd.bi_arch_number - C100_MACH_START;
-
- check_board_revision(board, board_rev);
-
- /* Set CPU Revision */
- if (mach_is_aquila()) {
- if (board_is_limo_real()) {
- if ((board_rev & 0xf) < 8)
- s5p_set_cpu_rev(0);
- }
- } else if (mach_is_goni()) {
- if (board_is_sdk() &&
- (hwrevision(2) || hwrevision(4) || hwrevision(5)))
- s5p_set_cpu_rev(2); /* EVT1-Fused */
- else
- s5p_set_cpu_rev(1);
- } else if (mach_is_geminus()) {
- if ((board_rev & 0xf) < 1)
- s5p_set_cpu_rev(0);
- } else if (mach_is_wmg160()) {
- if (hwrevision(5))
- s5p_set_cpu_rev(0);
- else
- s5p_set_cpu_rev(2);
- } else {
- s5p_set_cpu_rev(0);
- }
-
- if (cpu_is_s5pc110())
- writel(0xc1100000 | (0xffff & (s5p_get_cpu_rev() ? 1 : 0)),
- S5PC110_INFORM3);
-}
-
-static int check_keypad(void)
-{
- uint condition = 0;
- uint reg, value;
- uint col_num, row_num;
- uint col_mask;
- uint col_mask_shift;
- uint row_state[4] = {0, 0, 0, 0};
- uint i;
- int cpu_rev;
-
- if (cpu_is_s5pc100()) {
- struct s5pc100_gpio *gpio =
- (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
-
- row_num = 3;
- col_num = 3;
-
- /* Set GPH2[2:0] to KP_COL[2:0] */
- gpio_cfg_pin(&gpio->h2, 0, 0x3);
- gpio_cfg_pin(&gpio->h2, 1, 0x3);
- gpio_cfg_pin(&gpio->h2, 2, 0x3);
-
- /* Set GPH3[2:0] to KP_ROW[2:0] */
- gpio_cfg_pin(&gpio->h3, 0, 0x3);
- gpio_cfg_pin(&gpio->h3, 1, 0x3);
- gpio_cfg_pin(&gpio->h3, 2, 0x3);
-
- reg = S5PC100_KEYPAD_BASE;
- col_mask = S5PC1XX_KEYIFCOL_MASK;
- col_mask_shift = 0;
- } else {
- struct s5pc110_gpio *gpio =
- (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
-
- if (mach_is_wmg160())
- return 0;
-
- if (board_is_limo_real() || board_is_limo_universal()) {
- row_num = 2;
- col_num = 3;
- } else {
- row_num = 4;
- col_num = 4;
- }
-
- for (i = 0; i < row_num; i++) {
- /* Set GPH3[3:0] to KP_ROW[3:0] */
- gpio_cfg_pin(&gpio->h3, i, 0x3);
- gpio_set_pull(&gpio->h3, i, GPIO_PULL_UP);
- }
-
- for (i = 0; i < col_num; i++)
- /* Set GPH2[3:0] to KP_COL[3:0] */
- gpio_cfg_pin(&gpio->h2, i, 0x3);
-
- reg = S5PC110_KEYPAD_BASE;
- col_mask = S5PC110_KEYIFCOLEN_MASK;
- col_mask_shift = 8;
- }
-
- /* KEYIFCOL reg clear */
- writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
-
- /* key_scan */
- for (i = 0; i < col_num; i++) {
- value = col_mask;
- value &= ~(1 << i) << col_mask_shift;
-
- writel(value, reg + S5PC1XX_KEYIFCOL_OFFSET);
- sdelay(1000);
-
- value = readl(reg + S5PC1XX_KEYIFROW_OFFSET);
- row_state[i] = ~value & ((1 << row_num) - 1);
- }
-
- /* KEYIFCOL reg clear */
- writel(0, reg + S5PC1XX_KEYIFCOL_OFFSET);
-
- cpu_rev = s5p_get_cpu_rev();
- if (cpu_rev == 1) {
- if ((row_state[1] & 0x6) == 0x6)
- condition = 1;
- } else if (cpu_rev == 2) {
- if ((row_state[2] & 0x6) == 0x6)
- condition = 1;
- } else {
- if ((row_state[1] & 0x3) == 0x3)
- condition = 1;
- }
-
- return condition;
-}
-
-static int check_block(void)
-{
- struct onenand_op *onenand_ops = onenand_get_interface();
- struct mtd_info *mtd = onenand_ops->mtd;
- struct onenand_chip *this = mtd->priv;
- int i;
- int retlen = 0;
- u32 from = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- u32 len = 1 << this->erase_shift;
- u32 *buf = (u32 *)CONFIG_SYS_DOWN_ADDR;
-
- /* check first page of bootloader*/
- onenand_ops->read(from, len, (ssize_t *)&retlen, (u_char *)buf, 0);
- if (retlen != len)
- return 1;
-
- for (i = 0; i < (this->writesize / sizeof(this->writesize)); i++)
- if (*(buf + i) != 0xffffffff)
- return 0;
-
- return 1;
-}
-
-int board_check_condition(void)
-{
- if (check_keypad()) {
- PUTS("check: manual\n");
- return 1;
- }
-
- if (check_block()) {
- PUTS("check: bootloader broken\n");
- return 2;
- }
-
- return 0;
-}
-
-int board_load_bootloader(unsigned char *buf)
-{
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
- u32 ofs, len, retlen;
-
- ofs = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- len = CONFIG_SYS_MONITOR_LEN;
-
- mtd->read(mtd, ofs, len, &retlen, buf);
-
- if (len != retlen)
- return -1;
-
- return 0;
-}
-
-int board_lock_recoveryblock(void)
-{
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
- u32 ofs = 0;
- u32 len = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- int ret = 0;
-
- /* lock-tight the recovery block */
- if (this->lock_tight != NULL)
- ret = this->lock_tight(mtd, ofs, len);
-
- return ret;
-}
-
-void board_update_init(void)
-{
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
-
- /* Unlock whole block */
- this->unlock_all(mtd);
-}
-
-int board_update_image(u32 *buf, u32 len)
-{
- struct onenand_op *onenand_ops = onenand_get_interface();
- struct mtd_info *mtd = &onenand_mtd;
- struct onenand_chip *this = mtd->priv;
- u32 ofs;
- u32 ipl_addr = 0;
- u32 ipl_edge = CONFIG_ONENAND_START_PAGE << this->page_shift;
- u32 recovery_addr = ipl_edge;
- u32 recovery_edge = CONFIG_RECOVERY_UBOOT_BLOCK << this->erase_shift;
- u32 bootloader_addr = recovery_edge;
- int ret, retlen;
-
- if (len > bootloader_addr) {
- if (*(buf + bootloader_addr/sizeof(buf)) == 0xea000012) {
- /* case: IPL + Recovery + bootloader */
- PUTS("target: ipl + recovery + bootloader\n");
- ofs = ipl_addr;
- /* len = bootloader_edge; */
- } else {
- /* case: unknown format */
- PUTS("target: unknown\n");
- return 1;
- }
- } else {
- if (*(buf + recovery_addr/sizeof(buf)) == 0xea000012 &&
- *(buf + recovery_addr/sizeof(buf) - 1) == 0x00000000) {
- /* case: old image (IPL + bootloader) */
- PUTS("target: ipl + bootloader (old type)\n");
- ofs = ipl_addr;
- /* len = recovery_edge; */
- } else {
- /* case: bootloader only */
- PUTS("target: bootloader\n");
- ofs = bootloader_addr;
- /* len = bootloader_edge - recovery_edge; */
- }
- }
-
-#ifdef CONFIG_S5P
- /* Workaround: for prevent revision mismatch */
- if (cpu_is_s5pc110() && (ofs == 0)) {
- int img_rev;
-
- if (*buf == 0xea000012)
- img_rev = 0;
- else if (*(buf + 0x400) == 0xea000012)
- img_rev = 2;
- else
- img_rev = 1;
-
- if (img_rev != s5p_get_cpu_rev()) {
- PUTS("target check: CPU revision mismatch!\n");
- PUTS("target check: system is ");
- if (s5p_get_cpu_rev() == 1)
- serial_puts("EVT1\n");
- else if (s5p_get_cpu_rev() == 2)
- serial_puts("EVT1-Fused\n");
- else
- serial_puts("EVT0\n");
- PUTS("target check: download image is ");
- if (img_rev == 1)
- serial_puts("EVT1\n");
- else if (img_rev == 2)
- serial_puts("EVT1-Fused\n");
- else
- serial_puts("EVT0\n");
- PUTS("try again.");
- return 1;
- }
- }
-#endif
-
- /* Erase */
- ret = onenand_ops->erase(ofs, len, 0);
- if (ret)
- return ret;
-
- /* Write */
- onenand_ops->write(ofs, len, (ssize_t *)&retlen, (u_char *)buf);
- if (ret)
- return ret;
-
- return 0;
-}
-
-void board_recovery_init(void)
-{
- struct s5pc110_gpio *gpio =
- (struct s5pc110_gpio *) S5PC110_GPIO_BASE;
-
- /* basic arch cpu dependent setup */
- arch_cpu_init();
-
- /* Check H/W Revision */
- check_hw_revision();
-
- show_hw_revision();
-
- /* set GPIO to enable UART2 */
- gpio_cfg_pin(&gpio->a1, 0, 0x2);
- gpio_cfg_pin(&gpio->a1, 1, 0x2);
-
- /* UART_SEL MP0_5[7] at S5PC110 */
- gpio_direction_output(&gpio->mp0_5, 7, 0x1);
- gpio_set_pull(&gpio->mp0_5, 7, GPIO_PULL_DOWN);
-}
+++ /dev/null
-#
-# Copyright (C) 2010 Samsung Electronics
-#
-
-#########################################################################
-
-ifneq ($(OBJTREE),$(SRCTREE))
-ifeq ($(CURDIR),$(SRCTREE))
-dir :=
-else
-dir := $(subst $(SRCTREE)/,,$(CURDIR))
-endif
-
-obj := $(if $(dir),$(OBJTREE)/$(dir)/,$(OBJTREE)/)
-src := $(if $(dir),$(SRCTREE)/$(dir)/,$(SRCTREE)/)
-
-$(shell mkdir -p $(obj))
-else
-obj :=
-src :=
-endif
-
-# clean the slate ...
-PLATFORM_RELFLAGS =
-PLATFORM_CPPFLAGS =
-PLATFORM_LDFLAGS =
-
-#########################################################################
-
-HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
- $(HOSTCPPFLAGS)
-HOSTSTRIP = strip
-
-#
-# Mac OS X / Darwin's C preprocessor is Apple specific. It
-# generates numerous errors and warnings. We want to bypass it
-# and use GNU C's cpp. To do this we pass the -traditional-cpp
-# option to the compiler. Note that the -traditional-cpp flag
-# DOES NOT have the same semantics as GNU C's flag, all it does
-# is invoke the GNU preprocessor in stock ANSI/ISO C fashion.
-#
-# Apple's linker is similar, thanks to the new 2 stage linking
-# multiple symbol definitions are treated as errors, hence the
-# -multiply_defined suppress option to turn off this error.
-#
-
-ifeq ($(HOSTOS),darwin)
-HOSTCC = cc
-HOSTCFLAGS += -traditional-cpp
-HOSTLDFLAGS += -multiply_defined suppress
-else
-HOSTCC = gcc
-endif
-
-ifeq ($(HOSTOS),cygwin)
-HOSTCFLAGS += -ansi
-endif
-
-# We build some files with extra pedantic flags to try to minimize things
-# that won't build on some weird host compiler -- though there are lots of
-# exceptions for files that aren't complaint.
-
-HOSTCFLAGS_NOPED = $(filter-out -pedantic,$(HOSTCFLAGS))
-HOSTCFLAGS += -pedantic
-
-#########################################################################
-#
-# Option checker (courtesy linux kernel) to ensure
-# only supported compiler options are used
-#
-cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
- > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
-
-#
-# Include the make variables (CC, etc...)
-#
-AS = $(CROSS_COMPILE)as
-LD = $(CROSS_COMPILE)ld
-CC = $(CROSS_COMPILE)gcc
-CPP = $(CC) -E
-AR = $(CROSS_COMPILE)ar
-NM = $(CROSS_COMPILE)nm
-LDR = $(CROSS_COMPILE)ldr
-STRIP = $(CROSS_COMPILE)strip
-OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJDUMP = $(CROSS_COMPILE)objdump
-RANLIB = $(CROSS_COMPILE)RANLIB
-
-#########################################################################
-
-# Load generated board configuration
-sinclude $(OBJTREE)/include/autoconf.mk
-
-# Some architecture config.mk files need to know what CPUDIR is set to,
-# so calculate CPUDIR before including ARCH/SOC/CPU config.mk files.
-# Check if arch/$ARCH/cpu/$CPU exists, otherwise assume arch/$ARCH/cpu contains
-# CPU-specific code.
-CPUDIR=arch/$(ARCH)/cpu/$(CPU)
-ifneq ($(SRCTREE)/$(CPUDIR),$(wildcard $(SRCTREE)/$(CPUDIR)))
-CPUDIR=arch/$(ARCH)/cpu
-endif
-
-sinclude $(TOPDIR)/arch/$(ARCH)/config.mk # include architecture dependend rules
-sinclude $(TOPDIR)/$(CPUDIR)/config.mk # include CPU specific rules
-
-ifdef SOC
-sinclude $(TOPDIR)/$(CPUDIR)/$(SOC)/config.mk # include SoC specific rules
-endif
-ifdef VENDOR
-BOARDDIR = $(VENDOR)/$(BOARD)
-else
-BOARDDIR = $(BOARD)
-endif
-ifdef BOARD
-sinclude $(TOPDIR)/$(RECOVERY_BLOCK)/board/$(BOARDDIR)/config.mk
-endif
-
-#########################################################################
-
-# sinclude $(TOPDIR)/lib_$(ARCH)/config.mk
-
-CROSS_COMPILE ?= arm-linux-
-
-PLATFORM_CPPFLAGS += -DCONFIG_ARM -D__ARM__
-
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-PLATFORM_CPPFLAGS += $(call cc-option,-marm,)
-
-# Try if EABI is supported, else fall back to old API,
-# i. e. for example:
-# - with ELDK 4.2 (EABI supported), use:
-# -mabi=aapcs-linux -mno-thumb-interwork
-# - with ELDK 4.1 (gcc 4.x, no EABI), use:
-# -mabi=apcs-gnu -mno-thumb-interwork
-# - with ELDK 3.1 (gcc 3.x), use:
-# -mapcs-32 -mno-thumb-interwork
-PLATFORM_CPPFLAGS += $(call cc-option,\
- -mabi=aapcs-linux -mno-thumb-interwork,\
- $(call cc-option,\
- -mapcs-32,\
- $(call cc-option,\
- -mabi=apcs-gnu,\
- )\
- ) $(call cc-option,-mno-thumb-interwork,)\
- )
-
-# For EABI, make sure to provide raise()
-ifneq (,$(findstring -mabi=aapcs-linux,$(PLATFORM_CPPFLAGS)))
-# This file is parsed several times; make sure to add only once.
-ifeq (,$(findstring lib_arm/eabi_compat.o,$(PLATFORM_LIBS)))
-PLATFORM_LIBS += $(OBJTREE)/lib_arm/eabi_compat.o
-endif
-endif
-LDSCRIPT := $(SRCTREE)/$(RECOVERY_BLOCK)/board/$(BOARDDIR)/recovery.lds
-
-#########################################################################
-
-# sinclude $(TOPDIR)/cpu/$(CPU)/config.mk
-PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \
- -msoft-float
-
-# Make ARMv5 to allow more compilers to work, even though its v7a.
-PLATFORM_CPPFLAGS += -march=armv5
-# =========================================================================
-#
-# Supply options according to compiler version
-#
-# =========================================================================
-PLATFORM_RELFLAGS +=$(call cc-option,-mshort-load-bytes,\
- $(call cc-option,-malignment-traps,))
-
-#########################################################################
-
-ifneq (,$(findstring s,$(MAKEFLAGS)))
-ARFLAGS = cr
-else
-ARFLAGS = crv
-endif
-RELFLAGS= $(PLATFORM_RELFLAGS)
-DBGFLAGS= -g # -DDEBUG
-OPTFLAGS= -Os #-fomit-frame-pointer
-OBJCFLAGS += --gap-fill=0x00
-
-gccincdir := $(shell $(CC) -print-file-name=include)
-
-CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \
- -D__KERNEL__
-ifneq ($(TEXT_BASE),)
-CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
-endif
-
-ifneq ($(RESET_VECTOR_ADDRESS),)
-CPPFLAGS += -DRESET_VECTOR_ADDRESS=$(RESET_VECTOR_ADDRESS)
-endif
-
-ifneq ($(OBJTREE),$(SRCTREE))
-CPPFLAGS += -I$(OBJTREE)/include2 -I$(OBJTREE)/include
-endif
-
-CPPFLAGS += -I$(TOPDIR)/include
-CPPFLAGS += -fno-builtin -ffreestanding -nostdinc \
- -isystem $(gccincdir) -pipe $(PLATFORM_CPPFLAGS)
-
-CPPFLAGS += -I$(TOPDIR)/$(RECOVERY_BLOCK)
-CPPFLAGS += -DCONFIG_RECOVERY_BLOCK -D__HAVE_ARCH_MEMCPY32
-CPPFLAGS += -DRECOVERY_DEBUG
-
-ifdef BUILD_TAG
-CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes \
- -DBUILD_TAG='"$(BUILD_TAG)"'
-else
-CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes
-endif
-
-CFLAGS += $(call cc-option,-fno-stack-protector)
-
-# avoid trigraph warnings while parsing pci.h (produced by NIOS gcc-2.9)
-# this option have to be placed behind -Wall -- that's why it is here
-ifeq ($(ARCH),nios)
-ifeq ($(findstring 2.9,$(shell $(CC) --version)),2.9)
-CFLAGS := $(CPPFLAGS) -Wall -Wno-trigraphs
-endif
-endif
-
-# $(CPPFLAGS) sets -g, which causes gcc to pass a suitable -g<format>
-# option to the assembler.
-AFLAGS_DEBUG :=
-
-# turn jbsr into jsr for m68k
-ifeq ($(ARCH),m68k)
-ifeq ($(findstring 3.4,$(shell $(CC) --version)),3.4)
-AFLAGS_DEBUG := -Wa,-gstabs,-S
-endif
-endif
-
-AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS)
-
-LDFLAGS += -Bstatic -T $(LDSCRIPT) $(PLATFORM_LDFLAGS)
-ifneq ($(TEXT_BASE),)
-LDFLAGS += -Ttext $(TEXT_BASE)
-endif
-
-#########################################################################
-
-export HOSTCC HOSTCFLAGS HOSTLDFLAGS PEDCFLAGS HOSTSTRIP CROSS_COMPILE \
- AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP MAKE
-export TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS
-
-#########################################################################
-
-# Allow boards to use custom optimize flags on a per dir/file basis
-BCURDIR := $(notdir $(CURDIR))
-$(obj)%.s: %.S
- $(CPP) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $<
-$(obj)%.o: %.S
- $(CC) $(AFLAGS) $(AFLAGS_$(@F)) $(AFLAGS_$(BCURDIR)) -o $@ $< -c
-$(obj)%.o: %.c
- $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
-$(obj)%.i: %.c
- $(CPP) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c
-$(obj)%.s: %.c
- $(CC) $(CFLAGS) $(CFLAGS_$(@F)) $(CFLAGS_$(BCURDIR)) -o $@ $< -c -S
-
-#########################################################################
+++ /dev/null
-#
-# Copyright (C) 2005-2007 Samsung Electronics.
-# Kyungmin Park <kyungmin.park@samsung.com>
-#
-
-include $(TOPDIR)/$(RECOVERY_BLOCK)/config.mk
-
-LIB := $(obj)libonenand.a
-
-COBJS := onenand_base.o onenand_bbt.o
-
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+++ /dev/null
-/*
- * linux/drivers/mtd/onenand/onenand_base.c
- *
- * Copyright (C) 2005-2007 Samsung Electronics
- * Kyungmin Park <kyungmin.park@samsung.com>
- */
-
-#include <common.h>
-#include <linux/mtd/compat.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-
-#include <asm/io.h>
-#include <asm/errno.h>
-#include <malloc.h>
-
-#ifdef printk
-#undef printk
-#endif
-#define printk(...) do {} while (0)
-#define puts(...) do {} while (0)
-
-extern void *memcpy32(void *dst, const void *src, int len);
-
-/* It should access 16-bit instead of 8-bit */
-static void *memcpy_16(void *dst, const void *src, unsigned int len)
-{
- void *ret = dst;
- short *d = dst;
- const short *s = src;
-
- if (len >= 32 && (len & (32 - 1)) == 0)
- return memcpy32(dst, src, len);
-
- len >>= 1;
- while (len-- > 0)
- *d++ = *s++;
- return ret;
-}
-
-/**
- * onenand_oob_128 - oob info for Flex-Onenand with 4KB page
- * For now, we expose only 64 out of 80 ecc bytes
- */
-static struct nand_ecclayout onenand_oob_128 = {
- .eccbytes = 64,
- .eccpos = {
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
- 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
- 102, 103, 104, 105
- },
- .oobfree = {
- {2, 4}, {18, 4}, {34, 4}, {50, 4},
- {66, 4}, {82, 4}, {98, 4}, {114, 4}
- }
-};
-
-/**
- * onenand_oob_64 - oob info for large (2KB) page
- */
-static struct nand_ecclayout onenand_oob_64 = {
- .eccbytes = 20,
- .eccpos = {
- 8, 9, 10, 11, 12,
- 24, 25, 26, 27, 28,
- 40, 41, 42, 43, 44,
- 56, 57, 58, 59, 60,
- },
- .oobfree = {
- {2, 3}, {14, 2}, {18, 3}, {30, 2},
- {34, 3}, {46, 2}, {50, 3}, {62, 2}
- }
-};
-
-/**
- * onenand_oob_32 - oob info for middle (1KB) page
- */
-static struct nand_ecclayout onenand_oob_32 = {
- .eccbytes = 10,
- .eccpos = {
- 8, 9, 10, 11, 12,
- 24, 25, 26, 27, 28,
- },
- .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} }
-};
-
-static const unsigned char ffchars[] __attribute__((aligned(4))) = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 80 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 96 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 112 */
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 128 */
-};
-
-/**
- * from ../mtdpart.c to support callback
- */
-void mtd_erase_callback(struct erase_info *instr)
-{
- /* do noting */
-}
-
-/**
- * onenand_readw - [OneNAND Interface] Read OneNAND register
- * @param addr address to read
- *
- * Read OneNAND register
- */
-static unsigned short onenand_readw(void __iomem * addr)
-{
- return readw(addr);
-}
-
-/**
- * onenand_writew - [OneNAND Interface] Write OneNAND register with value
- * @param value value to write
- * @param addr address to write
- *
- * Write OneNAND register with value
- */
-static void onenand_writew(unsigned short value, void __iomem * addr)
-{
- writew(value, addr);
-}
-
-/**
- * onenand_block_address - [DEFAULT] Get block address
- * @param device the device id
- * @param block the block
- * @return translated block address if DDP, otherwise same
- *
- * Setup Start Address 1 Register (F100h)
- */
-static int onenand_block_address(struct onenand_chip *this, int block)
-{
- /* Device Flash Core select, NAND Flash Block Address */
- if (block & this->density_mask)
- return ONENAND_DDP_CHIP1 | (block ^ this->density_mask);
-
- return block;
-}
-
-/**
- * onenand_bufferram_address - [DEFAULT] Get bufferram address
- * @param device the device id
- * @param block the block
- * @return set DBS value if DDP, otherwise 0
- *
- * Setup Start Address 2 Register (F101h) for DDP
- */
-static int onenand_bufferram_address(struct onenand_chip *this, int block)
-{
- /* Device BufferRAM Select */
- if (block & this->density_mask)
- return ONENAND_DDP_CHIP1;
-
- return ONENAND_DDP_CHIP0;
-}
-
-/**
- * onenand_page_address - [DEFAULT] Get page address
- * @param page the page address
- * @param sector the sector address
- * @return combined page and sector address
- *
- * Setup Start Address 8 Register (F107h)
- */
-static int onenand_page_address(int page, int sector)
-{
- /* Flash Page Address, Flash Sector Address */
- int fpa, fsa;
-
- fpa = page & ONENAND_FPA_MASK;
- fsa = sector & ONENAND_FSA_MASK;
-
- return ((fpa << ONENAND_FPA_SHIFT) | fsa);
-}
-
-/**
- * onenand_buffer_address - [DEFAULT] Get buffer address
- * @param dataram1 DataRAM index
- * @param sectors the sector address
- * @param count the number of sectors
- * @return the start buffer value
- *
- * Setup Start Buffer Register (F200h)
- */
-static int onenand_buffer_address(int dataram1, int sectors, int count)
-{
- int bsa, bsc;
-
- /* BufferRAM Sector Address */
- bsa = sectors & ONENAND_BSA_MASK;
-
- if (dataram1)
- bsa |= ONENAND_BSA_DATARAM1; /* DataRAM1 */
- else
- bsa |= ONENAND_BSA_DATARAM0; /* DataRAM0 */
-
- /* BufferRAM Sector Count */
- bsc = count & ONENAND_BSC_MASK;
-
- return ((bsa << ONENAND_BSA_SHIFT) | bsc);
-}
-
-/**
- * flexonenand_block - Return block number for flash address
- * @param this - OneNAND device structure
- * @param addr - Address for which block number is needed
- */
-static unsigned int flexonenand_block(struct onenand_chip *this, loff_t addr)
-{
- unsigned int boundary, blk, die = 0;
-
- if (ONENAND_IS_DDP(this) && addr >= this->diesize[0]) {
- die = 1;
- addr -= this->diesize[0];
- }
-
- boundary = this->boundary[die];
-
- blk = addr >> (this->erase_shift - 1);
- if (blk > boundary)
- blk = (blk + boundary + 1) >> 1;
-
- blk += die ? this->density_mask : 0;
- return blk;
-}
-
-unsigned int onenand_block(struct onenand_chip *this, loff_t addr)
-{
- if (!FLEXONENAND(this))
- return addr >> this->erase_shift;
- return flexonenand_block(this, addr);
-}
-
-/**
- * flexonenand_addr - Return address of the block
- * @this: OneNAND device structure
- * @block: Block number on Flex-OneNAND
- *
- * Return address of the block
- */
-static loff_t flexonenand_addr(struct onenand_chip *this, int block)
-{
- loff_t ofs = 0;
- int die = 0, boundary;
-
- if (ONENAND_IS_DDP(this) && block >= this->density_mask) {
- block -= this->density_mask;
- die = 1;
- ofs = this->diesize[0];
- }
-
- boundary = this->boundary[die];
- ofs += (loff_t) block << (this->erase_shift - 1);
- if (block > (boundary + 1))
- ofs += (loff_t) (block - boundary - 1)
- << (this->erase_shift - 1);
- return ofs;
-}
-
-loff_t onenand_addr(struct onenand_chip *this, int block)
-{
- if (!FLEXONENAND(this))
- return (loff_t) block << this->erase_shift;
- return flexonenand_addr(this, block);
-}
-
-/**
- * flexonenand_region - [Flex-OneNAND] Return erase region of addr
- * @param mtd MTD device structure
- * @param addr address whose erase region needs to be identified
- */
-int flexonenand_region(struct mtd_info *mtd, loff_t addr)
-{
- int i;
-
- for (i = 0; i < mtd->numeraseregions; i++)
- if (addr < mtd->eraseregions[i].offset)
- break;
- return i - 1;
-}
-
-/**
- * onenand_get_density - [DEFAULT] Get OneNAND density
- * @param dev_id OneNAND device ID
- *
- * Get OneNAND density from device ID
- */
-static inline int onenand_get_density(int dev_id)
-{
- int density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT;
- return (density & ONENAND_DEVICE_DENSITY_MASK);
-}
-
-/**
- * onenand_command - [DEFAULT] Send command to OneNAND device
- * @param mtd MTD device structure
- * @param cmd the command to be sent
- * @param addr offset to read from or write to
- * @param len number of bytes to read or write
- *
- * Send command to OneNAND device. This function is used for middle/large page
- * devices (1KB/2KB Bytes per page)
- */
-static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr,
- size_t len)
-{
- struct onenand_chip *this = mtd->priv;
- int value, block, page;
-
- /* Address translation */
- switch (cmd) {
- case ONENAND_CMD_UNLOCK:
- case ONENAND_CMD_LOCK:
- case ONENAND_CMD_LOCK_TIGHT:
- case ONENAND_CMD_UNLOCK_ALL:
- block = -1;
- page = -1;
- break;
-
- case FLEXONENAND_CMD_PI_ACCESS:
- /* addr contains die index */
- block = addr * this->density_mask;
- page = -1;
- break;
-
- case ONENAND_CMD_ERASE:
- case ONENAND_CMD_BUFFERRAM:
- block = onenand_block(this, addr);
- page = -1;
- break;
-
- case FLEXONENAND_CMD_READ_PI:
- cmd = ONENAND_CMD_READ;
- block = addr * this->density_mask;
- page = 0;
- break;
-
- default:
- block = onenand_block(this, addr);
- page = (int) (addr
- - onenand_addr(this, block)) >> this->page_shift;
- page &= this->page_mask;
- break;
- }
-
- /* NOTE: The setting order of the registers is very important! */
- if (cmd == ONENAND_CMD_BUFFERRAM) {
- /* Select DataRAM for DDP */
- value = onenand_bufferram_address(this, block);
- this->write_word(value,
- this->base + ONENAND_REG_START_ADDRESS2);
-
- if (ONENAND_IS_4KB_PAGE(this))
- /* It is always BufferRAM0 */
- ONENAND_SET_BUFFERRAM0(this);
- else
- /* Switch to the next data buffer */
- ONENAND_SET_NEXT_BUFFERRAM(this);
-
- return 0;
- }
-
- if (block != -1) {
- /* Write 'DFS, FBA' of Flash */
- value = onenand_block_address(this, block);
- this->write_word(value,
- this->base + ONENAND_REG_START_ADDRESS1);
-
- /* Select DataRAM for DDP */
- value = onenand_bufferram_address(this, block);
- this->write_word(value,
- this->base + ONENAND_REG_START_ADDRESS2);
- }
-
- if (page != -1) {
- /* Now we use page size operation */
- int sectors = 0, count = 0;
- int dataram;
-
- switch (cmd) {
- case FLEXONENAND_CMD_RECOVER_LSB:
- case ONENAND_CMD_READ:
- case ONENAND_CMD_READOOB:
- case ONENAND_CMD_SUPERLOAD:
- if (ONENAND_IS_4KB_PAGE(this))
- /* It is always BufferRAM0 */
- dataram = ONENAND_SET_BUFFERRAM0(this);
- else
- dataram = ONENAND_SET_NEXT_BUFFERRAM(this);
- break;
-
- default:
- dataram = ONENAND_CURRENT_BUFFERRAM(this);
- break;
- }
-
- /* Write 'FPA, FSA' of Flash */
- value = onenand_page_address(page, sectors);
- this->write_word(value,
- this->base + ONENAND_REG_START_ADDRESS8);
-
- /* Write 'BSA, BSC' of DataRAM */
- value = onenand_buffer_address(dataram, sectors, count);
- this->write_word(value, this->base + ONENAND_REG_START_BUFFER);
- }
-
- /* Interrupt clear */
- this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT);
- /* Write command */
- this->write_word(cmd, this->base + ONENAND_REG_COMMAND);
-
- return 0;
-}
-
-/**
- * onenand_read_ecc - return ecc status
- * @param this onenand chip structure
- */
-static int onenand_read_ecc(struct onenand_chip *this)
-{
- int ecc, i;
-
- if (!ONENAND_IS_4KB_PAGE(this))
- return this->read_word(this->base + ONENAND_REG_ECC_STATUS);
-
- for (i = 0; i < 4; i++) {
- ecc = this->read_word(this->base
- + ((ONENAND_REG_ECC_STATUS + i) << 1));
- if (likely(!ecc))
- continue;
- if (ecc & FLEXONENAND_UNCORRECTABLE_ERROR)
- return ONENAND_ECC_2BIT_ALL;
- }
-
- return 0;
-}
-
-/**
- * onenand_wait - [DEFAULT] wait until the command is done
- * @param mtd MTD device structure
- * @param state state to select the max. timeout value
- *
- * Wait for command done. This applies to all OneNAND command
- * Read can take up to 30us, erase up to 2ms and program up to 350us
- * according to general OneNAND specs
- */
-static int onenand_wait(struct mtd_info *mtd, int state)
-{
- struct onenand_chip *this = mtd->priv;
- unsigned int flags = ONENAND_INT_MASTER;
- unsigned int interrupt = 0;
- unsigned int ctrl;
-
- while (1) {
- interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
- if (interrupt & flags)
- break;
- }
-
- ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
-
- if (interrupt & ONENAND_INT_READ) {
- int ecc = onenand_read_ecc(this);
- if (ecc & ONENAND_ECC_2BIT_ALL) {
- printk("onenand_wait: ECC error = 0x%04x\n", ecc);
- return -EBADMSG;
- }
- }
-
- if (ctrl & ONENAND_CTRL_ERROR) {
- printk("onenand_wait: controller error = 0x%04x\n", ctrl);
- if (ctrl & ONENAND_CTRL_LOCK)
- printk("onenand_wait: it's locked error = 0x%04x\n",
- ctrl);
-
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * onenand_bufferram_offset - [DEFAULT] BufferRAM offset
- * @param mtd MTD data structure
- * @param area BufferRAM area
- * @return offset given area
- *
- * Return BufferRAM offset given area
- */
-static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
-{
- struct onenand_chip *this = mtd->priv;
-
- if (ONENAND_CURRENT_BUFFERRAM(this)) {
- if (area == ONENAND_DATARAM)
- return mtd->writesize;
- if (area == ONENAND_SPARERAM)
- return mtd->oobsize;
- }
-
- return 0;
-}
-
-/**
- * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area
- * @param mtd MTD data structure
- * @param area BufferRAM area
- * @param buffer the databuffer to put/get data
- * @param offset offset to read from or write to
- * @param count number of bytes to read/write
- *
- * Read the BufferRAM area
- */
-static int onenand_read_bufferram(struct mtd_info *mtd, loff_t addr, int area,
- unsigned char *buffer, int offset,
- size_t count)
-{
- struct onenand_chip *this = mtd->priv;
- void __iomem *bufferram;
-
- bufferram = this->base + area;
- bufferram += onenand_bufferram_offset(mtd, area);
-
- memcpy_16(buffer, bufferram + offset, count);
-
- return 0;
-}
-
-/**
- * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area
- * @param mtd MTD data structure
- * @param area BufferRAM area
- * @param buffer the databuffer to put/get data
- * @param offset offset to read from or write to
- * @param count number of bytes to read/write
- *
- * Write the BufferRAM area
- */
-static int onenand_write_bufferram(struct mtd_info *mtd, loff_t addr, int area,
- const unsigned char *buffer, int offset,
- size_t count)
-{
- struct onenand_chip *this = mtd->priv;
- void __iomem *bufferram;
-
- bufferram = this->base + area;
- bufferram += onenand_bufferram_offset(mtd, area);
-
- memcpy_16(bufferram + offset, buffer, count);
-
- return 0;
-}
-
-/**
- * onenand_get_2x_blockpage - [GENERIC] Get blockpage at 2x program mode
- * @param mtd MTD data structure
- * @param addr address to check
- * @return blockpage address
- *
- * Get blockpage address at 2x program mode
- */
-static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
-{
- struct onenand_chip *this = mtd->priv;
- int blockpage, block, page;
-
- /* Calculate the even block number */
- block = (int) (addr >> this->erase_shift) & ~1;
- /* Is it the odd plane? */
- if (addr & this->writesize)
- block++;
- page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
- blockpage = (block << 7) | page;
-
- return blockpage;
-}
-
-/**
- * onenand_check_bufferram - [GENERIC] Check BufferRAM information
- * @param mtd MTD data structure
- * @param addr address to check
- * @return 1 if there are valid data, otherwise 0
- *
- * Check bufferram if there is data we required
- */
-static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
-{
- struct onenand_chip *this = mtd->priv;
- int blockpage, found = 0;
- unsigned int i;
-
- if (ONENAND_IS_2PLANE(this))
- blockpage = onenand_get_2x_blockpage(mtd, addr);
- else
- blockpage = (int) (addr >> this->page_shift);
-
- /* Is there valid data? */
- i = ONENAND_CURRENT_BUFFERRAM(this);
- if (this->bufferram[i].blockpage == blockpage)
- found = 1;
- else {
- /* Check another BufferRAM */
- i = ONENAND_NEXT_BUFFERRAM(this);
- if (this->bufferram[i].blockpage == blockpage) {
- ONENAND_SET_NEXT_BUFFERRAM(this);
- found = 1;
- }
- }
-
- if (found && ONENAND_IS_DDP(this)) {
- /* Select DataRAM for DDP */
- int block = onenand_block(this, addr);
- int value = onenand_bufferram_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
- }
-
- return found;
-}
-
-/**
- * onenand_update_bufferram - [GENERIC] Update BufferRAM information
- * @param mtd MTD data structure
- * @param addr address to update
- * @param valid valid flag
- *
- * Update BufferRAM information
- */
-static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
- int valid)
-{
- struct onenand_chip *this = mtd->priv;
- int blockpage;
- unsigned int i;
-
- if (ONENAND_IS_2PLANE(this))
- blockpage = onenand_get_2x_blockpage(mtd, addr);
- else
- blockpage = (int)(addr >> this->page_shift);
-
- /* Invalidate another BufferRAM */
- i = ONENAND_NEXT_BUFFERRAM(this);
- if (this->bufferram[i].blockpage == blockpage)
- this->bufferram[i].blockpage = -1;
-
- /* Update BufferRAM */
- i = ONENAND_CURRENT_BUFFERRAM(this);
- if (valid)
- this->bufferram[i].blockpage = blockpage;
- else
- this->bufferram[i].blockpage = -1;
-
- return 0;
-}
-
-/**
- * onenand_invalidate_bufferram - [GENERIC] Invalidate BufferRAM information
- * @param mtd MTD data structure
- * @param addr start address to invalidate
- * @param len length to invalidate
- *
- * Invalidate BufferRAM information
- */
-static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
- unsigned int len)
-{
- struct onenand_chip *this = mtd->priv;
- int i;
- loff_t end_addr = addr + len;
-
- /* Invalidate BufferRAM */
- for (i = 0; i < MAX_BUFFERRAM; i++) {
- loff_t buf_addr = this->bufferram[i].blockpage << this->page_shift;
-
- if (buf_addr >= addr && buf_addr < end_addr)
- this->bufferram[i].blockpage = -1;
- }
-}
-
-/**
- * onenand_get_device - [GENERIC] Get chip for selected access
- * @param mtd MTD device structure
- * @param new_state the state which is requested
- *
- * Get the device and lock it for exclusive access
- */
-static void onenand_get_device(struct mtd_info *mtd, int new_state)
-{
- /* Do nothing */
-}
-
-/**
- * onenand_release_device - [GENERIC] release chip
- * @param mtd MTD device structure
- *
- * Deselect, release chip lock and wake up anyone waiting on the device
- */
-static void onenand_release_device(struct mtd_info *mtd)
-{
- /* Do nothing */
-}
-
-/**
- * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
- * @param mtd MTD device structure
- * @param buf destination address
- * @param column oob offset to read from
- * @param thislen oob length to read
- */
-static int onenand_transfer_auto_oob(struct mtd_info *mtd, uint8_t *buf,
- int column, int thislen)
-{
- struct onenand_chip *this = mtd->priv;
- struct nand_oobfree *free;
- int readcol = column;
- int readend = column + thislen;
- int lastgap = 0;
- unsigned int i;
- uint8_t *oob_buf = this->oob_buf;
-
- free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
- if (readcol >= lastgap)
- readcol += free->offset - lastgap;
- if (readend >= lastgap)
- readend += free->offset - lastgap;
- lastgap = free->offset + free->length;
- }
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
- free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
- int free_end = free->offset + free->length;
- if (free->offset < readend && free_end > readcol) {
- int st = max_t(int,free->offset,readcol);
- int ed = min_t(int,free_end,readend);
- int n = ed - st;
- memcpy(buf, oob_buf + st, n);
- buf += n;
- } else if (column == 0)
- break;
- }
- return 0;
-}
-
-/**
- * onenand_recover_lsb - [Flex-OneNAND] Recover LSB page data
- * @param mtd MTD device structure
- * @param addr address to recover
- * @param status return value from onenand_wait
- *
- * MLC NAND Flash cell has paired pages - LSB page and MSB page. LSB page has
- * lower page address and MSB page has higher page address in paired pages.
- * If power off occurs during MSB page program, the paired LSB page data can
- * become corrupt. LSB page recovery read is a way to read LSB page though page
- * data are corrupted. When uncorrectable error occurs as a result of LSB page
- * read after power up, issue LSB page recovery read.
- */
-static int onenand_recover_lsb(struct mtd_info *mtd, loff_t addr, int status)
-{
- struct onenand_chip *this = mtd->priv;
- int i;
-
- /* Recovery is only for Flex-OneNAND */
- if (!FLEXONENAND(this))
- return status;
-
- /* check if we failed due to uncorrectable error */
- if (status != -EBADMSG && status != ONENAND_BBT_READ_ECC_ERROR)
- return status;
-
- /* check if address lies in MLC region */
- i = flexonenand_region(mtd, addr);
- if (mtd->eraseregions[i].erasesize < (1 << this->erase_shift))
- return status;
-
- printk("onenand_recover_lsb:"
- "Attempting to recover from uncorrectable read\n");
-
- /* Issue the LSB page recovery command */
- this->command(mtd, FLEXONENAND_CMD_RECOVER_LSB, addr, this->writesize);
- return this->wait(mtd, FL_READING);
-}
-
-/**
- * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
- * @param mtd MTD device structure
- * @param from offset to read from
- * @param ops oob operation description structure
- *
- * OneNAND read main and/or out-of-band data
- */
-static int onenand_normal_read_ops_nolock(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
- struct mtd_ecc_stats stats;
- size_t len = ops->len;
- size_t ooblen = ops->ooblen;
- u_char *buf = ops->datbuf;
- u_char *oobbuf = ops->oobbuf;
- int read = 0, column, thislen;
- int oobread = 0, oobcolumn, thisooblen, oobsize;
- int ret = 0, boundary = 0;
- int writesize = this->writesize;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-
- if (ops->mode == MTD_OOB_AUTO)
- oobsize = this->ecclayout->oobavail;
- else
- oobsize = mtd->oobsize;
-
- oobcolumn = from & (mtd->oobsize - 1);
-
- /* Do not allow reads past end of device */
- if ((from + len) > mtd->size) {
- printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
- ops->retlen = 0;
- ops->oobretlen = 0;
- return -EINVAL;
- }
-
- stats = mtd->ecc_stats;
-
- /* Read-while-load method */
- /* Note: We can't use this feature in MLC */
-
- /* Do first load to bufferRAM */
- if (read < len) {
- if (!onenand_check_bufferram(mtd, from)) {
- this->command(mtd, ONENAND_CMD_READ, from, writesize);
- ret = this->wait(mtd, FL_READING);
- if (unlikely(ret))
- ret = onenand_recover_lsb(mtd, from, ret);
- onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
- ret = 0;
- }
- }
-
- thislen = min_t(int, writesize, len - read);
- column = from & (writesize - 1);
- if (column + thislen > writesize)
- thislen = writesize - column;
-
- while (!ret) {
- /* If there is more to load then start next load */
- from += thislen;
-
- if (ONENAND_IS_4KB_PAGE(this))
- goto skip_read_while_load;
-
- if (read + thislen < len) {
- this->command(mtd, ONENAND_CMD_READ, from, writesize);
- /*
- * Chip boundary handling in DDP
- * Now we issued chip 1 read and pointed chip 1
- * bufferam so we have to point chip 0 bufferam.
- */
- if (ONENAND_IS_DDP(this) &&
- unlikely(from == (this->chipsize >> 1))) {
- this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
- boundary = 1;
- } else
- boundary = 0;
- ONENAND_SET_PREV_BUFFERRAM(this);
- }
-skip_read_while_load:
- /* While load is going, read from last bufferRAM */
- this->read_bufferram(mtd, from - thislen, ONENAND_DATARAM, buf, column, thislen);
-
- /* Read oob area if needed */
- if (oobbuf) {
- thisooblen = oobsize - oobcolumn;
- thisooblen = min_t(int, thisooblen, ooblen - oobread);
-
- if (ops->mode == MTD_OOB_AUTO)
- onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
- else
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
- oobread += thisooblen;
- oobbuf += thisooblen;
- oobcolumn = 0;
- }
-
- /* See if we are done */
- read += thislen;
- if (read == len)
- break;
- /* Set up for next read from bufferRAM */
- if (unlikely(boundary))
- this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
- if (ONENAND_IS_4KB_PAGE(this))
- this->command(mtd, ONENAND_CMD_READ, from, writesize);
- else
- ONENAND_SET_NEXT_BUFFERRAM(this);
- buf += thislen;
- thislen = min_t(int, writesize, len - read);
- column = 0;
-
- if (ONENAND_IS_4KB_PAGE(this)) {
- /* Now wait for load */
- ret = this->wait(mtd, FL_READING);
- onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
- ret = 0;
- }
- }
-
- /*
- * Return success, if no ECC failures, else -EBADMSG
- * fs driver will take care of that, because
- * retlen == desired len and result == -EBADMSG
- */
- ops->retlen = read;
- ops->oobretlen = oobread;
-
- if (ret)
- return ret;
-
- if (mtd->ecc_stats.failed - stats.failed)
- return -EBADMSG;
-
- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
-}
-
-static int onenand_superload_read_ops_nolock(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
- struct mtd_ecc_stats stats;
- size_t len = ops->len;
- size_t ooblen = ops->ooblen;
- u_char *buf = ops->datbuf;
- u_char *oobbuf = ops->oobbuf;
- int read = 0, column, thislen;
- int oobread = 0, oobcolumn, thisooblen, oobsize;
- int ret = 0, boundary = 0;
- int writesize = this->writesize;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ops_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-
- if (ops->mode == MTD_OOB_AUTO)
- oobsize = this->ecclayout->oobavail;
- else
- oobsize = mtd->oobsize;
-
- oobcolumn = from & (mtd->oobsize - 1);
-
- /* Do not allow reads past end of device */
- if ((from + len) > mtd->size) {
- printk(KERN_ERR "onenand_read_ops_nolock: Attempt read beyond end of device\n");
- ops->retlen = 0;
- ops->oobretlen = 0;
- return -EINVAL;
- }
-
- stats = mtd->ecc_stats;
-
- this->command(mtd, ONENAND_CMD_READ, from, writesize);
- ret = this->wait(mtd, FL_READING);
- if (unlikely(ret))
- ret = onenand_recover_lsb(mtd, from, ret);
- onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
- ret = 0;
-
- thislen = min_t(int, writesize, len - read);
- column = from & (writesize - 1);
- if (column + thislen > writesize)
- thislen = writesize - column;
-
- while (!ret) {
- /* If there is more to load then start next load */
- from += thislen;
-
- if (read + thislen < len) {
- this->command(mtd, ONENAND_CMD_SUPERLOAD, from, writesize);
- /*
- * Chip boundary handling in DDP
- * Now we issued chip 1 read and pointed chip 1
- * bufferam so we have to point chip 0 bufferam.
- */
- if (ONENAND_IS_DDP(this) &&
- unlikely(from == (this->chipsize >> 1))) {
- this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
- boundary = 1;
- } else
- boundary = 0;
- }
- /* While load is going, read from last bufferRAM */
- this->read_bufferram(mtd, from - thislen, ONENAND_DATARAM, buf, column, thislen);
-
- /* Read oob area if needed */
- if (oobbuf) {
- thisooblen = oobsize - oobcolumn;
- thisooblen = min_t(int, thisooblen, ooblen - oobread);
-
- if (ops->mode == MTD_OOB_AUTO)
- onenand_transfer_auto_oob(mtd, oobbuf, oobcolumn, thisooblen);
- else
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, oobcolumn, thisooblen);
- oobread += thisooblen;
- oobbuf += thisooblen;
- oobcolumn = 0;
- } else {
- /* It should be read at least 4 bytes
- * to the end of the spare area
- */
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, this->oob_buf, 0, mtd->oobsize);
- }
-
- /* See if we are done */
- read += thislen;
- if (read == len)
- break;
- /* Set up for next read from bufferRAM */
- if (unlikely(boundary))
- this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
-
- buf += thislen;
- thislen = min_t(int, writesize, len - read);
- column = 0;
-
- /* Now wait for load */
- ret = this->wait(mtd, FL_READING);
- onenand_update_bufferram(mtd, from, !ret);
- if (ret == -EBADMSG)
- ret = 0;
- }
-
- /*
- * Return success, if no ECC failures, else -EBADMSG
- * fs driver will take care of that, because
- * retlen == desired len and result == -EBADMSG
- */
- ops->retlen = read;
- ops->oobretlen = oobread;
-
- if (ret)
- return ret;
-
- if (mtd->ecc_stats.failed - stats.failed)
- return -EBADMSG;
-
- return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
-}
-
-/**
- * onenand_read_ops_nolock - [OneNAND Interface] OneNAND read main and/or out-of-band
- * @param mtd MTD device structure
- * @param from offset to read from
- * @param ops oob operation description structure
- *
- * OneNAND read main and/or out-of-band data
- */
-static int onenand_read_ops_nolock(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
-
- if (ONENAND_IS_4KB_PAGE(this) && ONENAND_IS_SYNC_MODE(this))
- return onenand_superload_read_ops_nolock(mtd, from, ops);
-
- return onenand_normal_read_ops_nolock(mtd, from, ops);
-}
-
-
-/**
- * onenand_read_oob_nolock - [MTD Interface] OneNAND read out-of-band
- * @param mtd MTD device structure
- * @param from offset to read from
- * @param ops oob operation description structure
- *
- * OneNAND read out-of-band data from the spare area
- */
-static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
- struct mtd_ecc_stats stats;
- int read = 0, thislen, column, oobsize;
- size_t len = ops->ooblen;
- mtd_oob_mode_t mode = ops->mode;
- u_char *buf = ops->oobbuf;
- int ret = 0, readcmd;
-
- from += ops->ooboffs;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob_nolock: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
-
- /* Initialize return length value */
- ops->oobretlen = 0;
-
- if (mode == MTD_OOB_AUTO)
- oobsize = this->ecclayout->oobavail;
- else
- oobsize = mtd->oobsize;
-
- column = from & (mtd->oobsize - 1);
-
- if (unlikely(column >= oobsize)) {
- printk(KERN_ERR "onenand_read_oob_nolock: Attempted to start read outside oob\n");
- return -EINVAL;
- }
-
- /* Do not allow reads past end of device */
- if (unlikely(from >= mtd->size ||
- column + len > ((mtd->size >> this->page_shift) -
- (from >> this->page_shift)) * oobsize)) {
- printk(KERN_ERR "onenand_read_oob_nolock: Attempted to read beyond end of device\n");
- return -EINVAL;
- }
-
- stats = mtd->ecc_stats;
-
- readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
-
- while (read < len) {
- thislen = oobsize - column;
- thislen = min_t(int, thislen, len);
-
- this->command(mtd, readcmd, from, mtd->oobsize);
-
- onenand_update_bufferram(mtd, from, 0);
-
- ret = this->wait(mtd, FL_READING);
- if (unlikely(ret))
- ret = onenand_recover_lsb(mtd, from, ret);
-
- if (ret && ret != -EBADMSG) {
- printk(KERN_ERR "onenand_read_oob_nolock: read failed = 0x%x\n", ret);
- break;
- }
-
- if (mode == MTD_OOB_AUTO)
- onenand_transfer_auto_oob(mtd, buf, column, thislen);
- else
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
-
- read += thislen;
-
- if (read == len)
- break;
-
- buf += thislen;
-
- /* Read more? */
- if (read < len) {
- /* Page size */
- from += mtd->writesize;
- column = 0;
- }
- }
-
- ops->oobretlen = read;
-
- if (ret)
- return ret;
-
- if (mtd->ecc_stats.failed - stats.failed)
- return -EBADMSG;
-
- return 0;
-}
-
-/**
- * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
- * @param mtd MTD device structure
- * @param from offset to read from
- * @param len number of bytes to read
- * @param retlen pointer to variable to store the number of read bytes
- * @param buf the databuffer to put data
- *
- * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
-*/
-static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t * retlen, u_char * buf)
-{
- struct mtd_oob_ops ops = {
- .len = len,
- .ooblen = 0,
- .datbuf = buf,
- .oobbuf = NULL,
- };
- int ret;
-
- onenand_get_device(mtd, FL_READING);
- ret = onenand_read_ops_nolock(mtd, from, &ops);
- onenand_release_device(mtd);
-
- *retlen = ops.retlen;
- return ret;
-}
-
-/**
- * onenand_read_oob - [MTD Interface] OneNAND read out-of-band
- * @param mtd MTD device structure
- * @param from offset to read from
- * @param ops oob operations description structure
- *
- * OneNAND main and/or out-of-band
- */
-static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- int ret;
-
- switch (ops->mode) {
- case MTD_OOB_PLACE:
- case MTD_OOB_AUTO:
- break;
- case MTD_OOB_RAW:
- /* Not implemented yet */
- default:
- return -EINVAL;
- }
-
- onenand_get_device(mtd, FL_READING);
- if (ops->datbuf)
- ret = onenand_read_ops_nolock(mtd, from, ops);
- else
- ret = onenand_read_oob_nolock(mtd, from, ops);
- onenand_release_device(mtd);
-
- return ret;
-}
-
-/**
- * onenand_bbt_wait - [DEFAULT] wait until the command is done
- * @param mtd MTD device structure
- * @param state state to select the max. timeout value
- *
- * Wait for command done.
- */
-static int onenand_bbt_wait(struct mtd_info *mtd, int state)
-{
- struct onenand_chip *this = mtd->priv;
- unsigned int flags = ONENAND_INT_MASTER;
- unsigned int interrupt;
- unsigned int ctrl;
-
- while (1) {
- interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
- if (interrupt & flags)
- break;
- }
-
- /* To get correct interrupt status in timeout case */
- interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
- ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
-
- if (interrupt & ONENAND_INT_READ) {
- int ecc = onenand_read_ecc(this);
- if (ecc & ONENAND_ECC_2BIT_ALL) {
- printk(KERN_INFO "onenand_bbt_wait: ecc error = 0x%04x"
- ", controller = 0x%04x\n", ecc, ctrl);
- return ONENAND_BBT_READ_ERROR;
- }
- } else {
- printk(KERN_ERR "onenand_bbt_wait: read timeout!"
- "ctrl=0x%04x intr=0x%04x\n", ctrl, interrupt);
- return ONENAND_BBT_READ_FATAL_ERROR;
- }
-
- /* Initial bad block case: 0x2400 or 0x0400 */
- if (ctrl & ONENAND_CTRL_ERROR) {
- printk(KERN_DEBUG "onenand_bbt_wait: controller error = 0x%04x\n", ctrl);
- return ONENAND_BBT_READ_ERROR;
- }
-
- return 0;
-}
-
-/**
- * onenand_bbt_read_oob - [MTD Interface] OneNAND read out-of-band for bbt scan
- * @param mtd MTD device structure
- * @param from offset to read from
- * @param ops oob operation description structure
- *
- * OneNAND read out-of-band data from the spare area for bbt scan
- */
-int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
- int read = 0, thislen, column;
- int ret = 0, readcmd;
- size_t len = ops->ooblen;
- u_char *buf = ops->oobbuf;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_bbt_read_oob: from = 0x%08x, len = %zi\n", (unsigned int) from, len);
-
- readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
-
- /* Initialize return value */
- ops->oobretlen = 0;
-
- /* Do not allow reads past end of device */
- if (unlikely((from + len) > mtd->size)) {
- printk(KERN_ERR "onenand_bbt_read_oob: Attempt read beyond end of device\n");
- return ONENAND_BBT_READ_FATAL_ERROR;
- }
-
- /* Grab the lock and see if the device is available */
- onenand_get_device(mtd, FL_READING);
-
- column = from & (mtd->oobsize - 1);
-
- while (read < len) {
-
- thislen = mtd->oobsize - column;
- thislen = min_t(int, thislen, len);
-
- this->command(mtd, readcmd, from, mtd->oobsize);
-
- onenand_update_bufferram(mtd, from, 0);
-
- ret = this->bbt_wait(mtd, FL_READING);
- if (unlikely(ret))
- ret = onenand_recover_lsb(mtd, from, ret);
-
- if (ret)
- break;
-
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, buf, column, thislen);
- read += thislen;
- if (read == len)
- break;
-
- buf += thislen;
-
- /* Read more? */
- if (read < len) {
- /* Update Page size */
- from += this->writesize;
- column = 0;
- }
- }
-
- /* Deselect and wake up anyone waiting on the device */
- onenand_release_device(mtd);
-
- ops->oobretlen = read;
- return ret;
-}
-
-#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
-/**
- * onenand_verify_oob - [GENERIC] verify the oob contents after a write
- * @param mtd MTD device structure
- * @param buf the databuffer to verify
- * @param to offset to read from
- */
-static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to)
-{
- struct onenand_chip *this = mtd->priv;
- u_char *oob_buf = this->oob_buf;
- int status, i, readcmd;
-
- readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
-
- this->command(mtd, readcmd, to, mtd->oobsize);
- onenand_update_bufferram(mtd, to, 0);
- status = this->wait(mtd, FL_READING);
- if (status)
- return status;
-
- this->read_bufferram(mtd, 0, ONENAND_SPARERAM, oob_buf, 0, mtd->oobsize);
- for (i = 0; i < mtd->oobsize; i++)
- if (buf[i] != 0xFF && buf[i] != oob_buf[i])
- return -EBADMSG;
-
- return 0;
-}
-
-/**
- * onenand_verify - [GENERIC] verify the chip contents after a write
- * @param mtd MTD device structure
- * @param buf the databuffer to verify
- * @param addr offset to read from
- * @param len number of bytes to read and compare
- */
-static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr, size_t len)
-{
- struct onenand_chip *this = mtd->priv;
- int ret = 0;
- int thislen, column;
-
- while (len != 0) {
- thislen = min_t(int, this->writesize, len);
- column = addr & (this->writesize - 1);
- if (column + thislen > this->writesize)
- thislen = this->writesize - column;
-
- this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
-
- onenand_update_bufferram(mtd, addr, 0);
-
- ret = this->wait(mtd, FL_READING);
- if (ret)
- return ret;
-
- onenand_update_bufferram(mtd, addr, 1);
-
- this->read_bufferram(mtd, 0, ONENAND_DATARAM, this->verify_buf, 0, mtd->writesize);
-
- if (memcmp(buf, this->verify_buf, thislen))
- return -EBADMSG;
-
- len -= thislen;
- buf += thislen;
- addr += thislen;
- }
-
- return 0;
-}
-#else
-#define onenand_verify(...) (0)
-#define onenand_verify_oob(...) (0)
-#endif
-
-#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)
-
-/**
- * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
- * @param mtd MTD device structure
- * @param oob_buf oob buffer
- * @param buf source address
- * @param column oob offset to write to
- * @param thislen oob length to write
- */
-static int onenand_fill_auto_oob(struct mtd_info *mtd, u_char *oob_buf,
- const u_char *buf, int column, int thislen)
-{
- struct onenand_chip *this = mtd->priv;
- struct nand_oobfree *free;
- int writecol = column;
- int writeend = column + thislen;
- int lastgap = 0;
- unsigned int i;
-
- free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
- if (writecol >= lastgap)
- writecol += free->offset - lastgap;
- if (writeend >= lastgap)
- writeend += free->offset - lastgap;
- lastgap = free->offset + free->length;
- }
- free = this->ecclayout->oobfree;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free->length; i++, free++) {
- int free_end = free->offset + free->length;
- if (free->offset < writeend && free_end > writecol) {
- int st = max_t(int,free->offset,writecol);
- int ed = min_t(int,free_end,writeend);
- int n = ed - st;
- memcpy(oob_buf + st, buf, n);
- buf += n;
- } else if (column == 0)
- break;
- }
- return 0;
-}
-
-/**
- * onenand_write_ops_nolock - [OneNAND Interface] write main and/or out-of-band
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param ops oob operation description structure
- *
- * Write main and/or oob with ECC
- */
-static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
- int written = 0, column, thislen, subpage;
- int oobwritten = 0, oobcolumn, thisooblen, oobsize;
- size_t len = ops->len;
- size_t ooblen = ops->ooblen;
- const u_char *buf = ops->datbuf;
- const u_char *oob = ops->oobbuf;
- u_char *oobbuf;
- int ret = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ops_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
-
- /* Initialize retlen, in case of early exit */
- ops->retlen = 0;
- ops->oobretlen = 0;
-
- /* Do not allow writes past end of device */
- if (unlikely((to + len) > mtd->size)) {
- printk(KERN_ERR "onenand_write_ops_nolock: Attempt write to past end of device\n");
- return -EINVAL;
- }
-
- /* Reject writes, which are not page aligned */
- if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) {
- printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n");
- return -EINVAL;
- }
-
- if (ops->mode == MTD_OOB_AUTO)
- oobsize = this->ecclayout->oobavail;
- else
- oobsize = mtd->oobsize;
-
- oobcolumn = to & (mtd->oobsize - 1);
-
- column = to & (mtd->writesize - 1);
-
- /* Loop until all data write */
- while (written < len) {
- u_char *wbuf = (u_char *) buf;
-
- thislen = min_t(int, mtd->writesize - column, len - written);
- thisooblen = min_t(int, oobsize - oobcolumn, ooblen - oobwritten);
-
- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, thislen);
-
- /* Partial page write */
- subpage = thislen < mtd->writesize;
- if (subpage) {
- memset(this->page_buf, 0xff, mtd->writesize);
- memcpy(this->page_buf + column, buf, thislen);
- wbuf = this->page_buf;
- }
-
- this->write_bufferram(mtd, to, ONENAND_DATARAM, wbuf, 0, mtd->writesize);
-
- if (oob) {
- oobbuf = this->oob_buf;
-
- /* We send data to spare ram with oobsize
- * * to prevent byte access */
- memset(oobbuf, 0xff, mtd->oobsize);
- if (ops->mode == MTD_OOB_AUTO)
- onenand_fill_auto_oob(mtd, oobbuf, oob, oobcolumn, thisooblen);
- else
- memcpy(oobbuf + oobcolumn, oob, thisooblen);
-
- oobwritten += thisooblen;
- oob += thisooblen;
- oobcolumn = 0;
- } else
- oobbuf = (u_char *) ffchars;
-
- this->write_bufferram(mtd, to, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
-
- this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
-
- ret = this->wait(mtd, FL_WRITING);
-
- /* In partial page write we don't update bufferram */
- onenand_update_bufferram(mtd, to, !ret && !subpage);
- if (ONENAND_IS_2PLANE(this)) {
- ONENAND_SET_BUFFERRAM1(this);
- onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
- }
-
- if (ret) {
- printk(KERN_ERR "onenand_write_ops_nolock: write filaed %d\n", ret);
- break;
- }
-
- /* Only check verify write turn on */
- ret = onenand_verify(mtd, buf, to, thislen);
- if (ret) {
- printk(KERN_ERR "onenand_write_ops_nolock: verify failed %d\n", ret);
- break;
- }
-
- written += thislen;
-
- if (written == len)
- break;
-
- column = 0;
- to += thislen;
- buf += thislen;
- }
-
- ops->retlen = written;
-
- return ret;
-}
-
-/**
- * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of written bytes
- * @param buf the data to write
- * @param mode operation mode
- *
- * OneNAND write out-of-band
- */
-static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- struct onenand_chip *this = mtd->priv;
- int column, ret = 0, oobsize;
- int written = 0, oobcmd;
- u_char *oobbuf;
- size_t len = ops->ooblen;
- const u_char *buf = ops->oobbuf;
- mtd_oob_mode_t mode = ops->mode;
-
- to += ops->ooboffs;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob_nolock: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
-
- /* Initialize retlen, in case of early exit */
- ops->oobretlen = 0;
-
- if (mode == MTD_OOB_AUTO)
- oobsize = this->ecclayout->oobavail;
- else
- oobsize = mtd->oobsize;
-
- column = to & (mtd->oobsize - 1);
-
- if (unlikely(column >= oobsize)) {
- printk(KERN_ERR "onenand_write_oob_nolock: Attempted to start write outside oob\n");
- return -EINVAL;
- }
-
- /* For compatibility with NAND: Do not allow write past end of page */
- if (unlikely(column + len > oobsize)) {
- printk(KERN_ERR "onenand_write_oob_nolock: "
- "Attempt to write past end of page\n");
- return -EINVAL;
- }
-
- /* Do not allow reads past end of device */
- if (unlikely(to >= mtd->size ||
- column + len > ((mtd->size >> this->page_shift) -
- (to >> this->page_shift)) * oobsize)) {
- printk(KERN_ERR "onenand_write_oob_nolock: Attempted to write past end of device\n");
- return -EINVAL;
- }
-
- oobbuf = this->oob_buf;
-
- oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
-
- /* Loop until all data write */
- while (written < len) {
- int thislen = min_t(int, oobsize, len - written);
-
- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
-
- /* We send data to spare ram with oobsize
- * to prevent byte access */
- memset(oobbuf, 0xff, mtd->oobsize);
- if (mode == MTD_OOB_AUTO)
- onenand_fill_auto_oob(mtd, oobbuf, buf, column, thislen);
- else
- memcpy(oobbuf + column, buf, thislen);
- this->write_bufferram(mtd, 0, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
-
- if (ONENAND_IS_MLC(this)) {
- /* Set main area of DataRAM to 0xff*/
- memset(this->page_buf, 0xff, mtd->writesize);
- this->write_bufferram(mtd, 0, ONENAND_DATARAM,
- this->page_buf, 0, mtd->writesize);
- }
-
- this->command(mtd, oobcmd, to, mtd->oobsize);
-
- onenand_update_bufferram(mtd, to, 0);
- if (ONENAND_IS_2PLANE(this)) {
- ONENAND_SET_BUFFERRAM1(this);
- onenand_update_bufferram(mtd, to + this->writesize, 0);
- }
-
- ret = this->wait(mtd, FL_WRITING);
- if (ret) {
- printk(KERN_ERR "onenand_write_oob_nolock: write failed %d\n", ret);
- break;
- }
-
- ret = onenand_verify_oob(mtd, oobbuf, to);
- if (ret) {
- printk(KERN_ERR "onenand_write_oob_nolock: verify failed %d\n", ret);
- break;
- }
-
- written += thislen;
- if (written == len)
- break;
-
- to += mtd->writesize;
- buf += thislen;
- column = 0;
- }
-
- ops->oobretlen = written;
-
- return ret;
-}
-
-/**
- * onenand_write - [MTD Interface] compability function for onenand_write_ecc
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of written bytes
- * @param buf the data to write
- *
- * Write with ECC
- */
-static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t * retlen, const u_char * buf)
-{
- struct mtd_oob_ops ops = {
- .len = len,
- .ooblen = 0,
- .datbuf = (u_char *) buf,
- .oobbuf = NULL,
- .mode = MTD_OOB_AUTO,
- };
- int ret;
-
- onenand_get_device(mtd, FL_WRITING);
- ret = onenand_write_ops_nolock(mtd, to, &ops);
- onenand_release_device(mtd);
-
- *retlen = ops.retlen;
- return ret;
-}
-
-/**
- * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
- * @param mtd MTD device structure
- * @param to offset to write to
- * @param ops oob operation description structure
- *
- * OneNAND write main and/or out-of-band
- */
-int onenand_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
-{
- int ret;
-
- switch (ops->mode) {
- case MTD_OOB_PLACE:
- case MTD_OOB_AUTO:
- break;
- case MTD_OOB_RAW:
- /* Not implemented yet */
- default:
- return -EINVAL;
- }
-
- onenand_get_device(mtd, FL_WRITING);
- if (ops->datbuf)
- ret = onenand_write_ops_nolock(mtd, to, ops);
- else
- ret = onenand_write_oob_nolock(mtd, to, ops);
- onenand_release_device(mtd);
-
- return ret;
-
-}
-
-/**
- * onenand_block_isbad_nolock - [GENERIC] Check if a block is marked bad
- * @param mtd MTD device structure
- * @param ofs offset from device start
- * @param allowbbt 1, if its allowed to access the bbt area
- *
- * Check, if the block is bad, Either by reading the bad block table or
- * calling of the scan function.
- */
-static int onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm = this->bbm;
-
- /* Return info from the table */
- return bbm->isbad_bbt(mtd, ofs, allowbbt);
-}
-
-
-/**
- * onenand_erase - [MTD Interface] erase block(s)
- * @param mtd MTD device structure
- * @param instr erase instruction
- *
- * Erase one ore more blocks
- */
-static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
- struct onenand_chip *this = mtd->priv;
- unsigned int block_size;
- loff_t addr = instr->addr;
- unsigned int len = instr->len;
- int ret = 0, i;
- struct mtd_erase_region_info *region = NULL;
- unsigned int region_end = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
- (unsigned int) addr, len);
-
- /* Do not allow erase past end of device */
- if (unlikely((len + addr) > mtd->size)) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
- "Erase past end of device\n");
- return -EINVAL;
- }
-
- if (FLEXONENAND(this)) {
- /* Find the eraseregion of this address */
- i = flexonenand_region(mtd, addr);
- region = &mtd->eraseregions[i];
-
- block_size = region->erasesize;
- region_end = region->offset
- + region->erasesize * region->numblocks;
-
- /* Start address within region must align on block boundary.
- * Erase region's start offset is always block start address.
- */
- if (unlikely((addr - region->offset) & (block_size - 1))) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
- " Unaligned address\n");
- return -EINVAL;
- }
- } else {
- block_size = 1 << this->erase_shift;
-
- /* Start address must align on block boundary */
- if (unlikely(addr & (block_size - 1))) {
- MTDDEBUG(MTD_DEBUG_LEVEL0, "onenand_erase:"
- "Unaligned address\n");
- return -EINVAL;
- }
- }
-
- /* Length must align on block boundary */
- if (unlikely(len & (block_size - 1))) {
- MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Length not block aligned\n");
- return -EINVAL;
- }
-
- instr->fail_addr = 0xffffffff;
-
- /* Grab the lock and see if the device is available */
- onenand_get_device(mtd, FL_ERASING);
-
- /* Loop throught the pages */
- instr->state = MTD_ERASING;
-
- while (len) {
-
- /* Check if we have a bad block, we do not erase bad blocks */
- if (instr->priv == 0 && onenand_block_isbad_nolock(mtd, addr, 0)) {
- printk(KERN_WARNING "onenand_erase: attempt to erase"
- " a bad block at addr 0x%08x\n",
- (unsigned int) addr);
- instr->state = MTD_ERASE_FAILED;
- goto erase_exit;
- }
-
- this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
-
- onenand_invalidate_bufferram(mtd, addr, block_size);
-
- ret = this->wait(mtd, FL_ERASING);
- /* Check, if it is write protected */
- if (ret) {
- if (ret == -EPERM)
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Device is write protected!!!\n");
- else
- MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Failed erase, block %d\n",
- onenand_block(this, addr));
- instr->state = MTD_ERASE_FAILED;
- instr->fail_addr = addr;
- }
-
- len -= block_size;
- addr += block_size;
-
- if (addr == region_end) {
- if (!len)
- break;
- region++;
-
- block_size = region->erasesize;
- region_end = region->offset
- + region->erasesize * region->numblocks;
-
- if (len & (block_size - 1)) {
- /* This has been checked at MTD
- * partitioning level. */
- printk("onenand_erase: Unaligned address\n");
- goto erase_exit;
- }
- }
- }
-
- instr->state = MTD_ERASE_DONE;
-
-erase_exit:
-
- ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
-
- /* Deselect and wake up anyone waiting on the device */
- onenand_release_device(mtd);
-
- return ret;
-}
-
-/**
- * onenand_sync - [MTD Interface] sync
- * @param mtd MTD device structure
- *
- * Sync is actually a wait for chip ready function
- */
-static void onenand_sync(struct mtd_info *mtd)
-{
- MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_sync: called\n");
-
- /* Grab the lock and see if the device is available */
- onenand_get_device(mtd, FL_SYNCING);
-
- /* Release it and go back */
- onenand_release_device(mtd);
-}
-
-/**
- * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- *
- * Check whether the block is bad
- */
-static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
-{
- int ret;
-
- /* Check for invalid offset */
- if (ofs > mtd->size)
- return -EINVAL;
-
- onenand_get_device(mtd, FL_READING);
- ret = onenand_block_isbad_nolock(mtd, ofs, 0);
- onenand_release_device(mtd);
- return ret;
-}
-
-/**
- * onenand_default_block_markbad - [DEFAULT] mark a block bad
- * @param mtd MTD device structure
- * @param ofs offset from device start
- *
- * This is the default implementation, which can be overridden by
- * a hardware specific driver.
- */
-static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm = this->bbm;
- u_char buf[2] = {0, 0};
- struct mtd_oob_ops ops = {
- .mode = MTD_OOB_PLACE,
- .ooblen = 2,
- .oobbuf = buf,
- .ooboffs = 0,
- };
- int block;
-
- /* Get block number */
- block = onenand_block(this, ofs);
- if (bbm->bbt)
- bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
-
- /* We write two bytes, so we dont have to mess with 16 bit access */
- ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
- return onenand_write_oob_nolock(mtd, ofs, &ops);
-}
-
-/**
- * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- *
- * Mark the block as bad
- */
-static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- struct onenand_chip *this = mtd->priv;
- int ret;
-
- ret = onenand_block_isbad(mtd, ofs);
- if (ret) {
- /* If it was bad already, return success and do nothing */
- if (ret > 0)
- return 0;
- return ret;
- }
-
- ret = this->block_markbad(mtd, ofs);
- return ret;
-}
-
-/**
- * onenand_do_lock_cmd - [OneNAND Interface] Lock or unlock block(s)
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- * @param len number of bytes to lock or unlock
- * @param cmd lock or unlock command
- *
- * Lock or unlock one or more blocks
- */
-static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int cmd)
-{
- struct onenand_chip *this = mtd->priv;
- int start, end, block, value, status;
- int wp_status_mask;
-
- start = onenand_block(this, ofs);
- end = onenand_block(this, ofs + len);
-
- if (cmd == ONENAND_CMD_LOCK)
- wp_status_mask = ONENAND_WP_LS;
- else if (cmd == ONENAND_CMD_LOCK_TIGHT)
- wp_status_mask = ONENAND_WP_LTS;
- else
- wp_status_mask = ONENAND_WP_US;
-
- /* Continuous lock scheme */
- if (this->options & ONENAND_HAS_CONT_LOCK) {
- /* Set start block address */
- this->write_word(start,
- this->base + ONENAND_REG_START_BLOCK_ADDRESS);
- /* Set end block address */
- this->write_word(end - 1,
- this->base + ONENAND_REG_END_BLOCK_ADDRESS);
- /* Write lock command */
- this->command(mtd, cmd, 0, 0);
-
- /* There's no return value */
- this->wait(mtd, FL_LOCKING);
-
- /* Sanity check */
- while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
- & ONENAND_CTRL_ONGO)
- continue;
-
- /* Check lock status */
- status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
- if (!(status & wp_status_mask))
- printk(KERN_ERR "wp status = 0x%x\n", status);
-
- return 0;
- }
-
- /* Block lock scheme */
- for (block = start; block < end; block++) {
- /* Set block address */
- value = onenand_block_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
- /* Select DataRAM for DDP */
- value = onenand_bufferram_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
-
- /* Set start block address */
- this->write_word(block,
- this->base + ONENAND_REG_START_BLOCK_ADDRESS);
- /* Write lock command */
- this->command(mtd, cmd, 0, 0);
-
- /* There's no return value */
- this->wait(mtd, FL_LOCKING);
-
- /* Sanity check */
- while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
- & ONENAND_CTRL_ONGO)
- continue;
-
- /* Check lock status */
- status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
- if (!(status & wp_status_mask))
- printk(KERN_ERR "block = %d, wp status = 0x%x\n",
- block, status);
- }
-
- return 0;
-}
-
-#ifdef ONENAND_LINUX
-/**
- * onenand_lock - [MTD Interface] Lock block(s)
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- * @param len number of bytes to unlock
- *
- * Lock one or more blocks
- */
-static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
- int ret;
-
- onenand_get_device(mtd, FL_LOCKING);
- ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK);
- onenand_release_device(mtd);
- return ret;
-}
-
-/**
- * onenand_unlock - [MTD Interface] Unlock block(s)
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- * @param len number of bytes to unlock
- *
- * Unlock one or more blocks
- */
-static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
- int ret;
-
- onenand_get_device(mtd, FL_LOCKING);
- ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
- onenand_release_device(mtd);
- return ret;
-}
-#endif
-
-/**
- * onenand_check_lock_status - [OneNAND Interface] Check lock status
- * @param this onenand chip data structure
- *
- * Check lock status
- */
-static int onenand_check_lock_status(struct onenand_chip *this)
-{
- unsigned int value, block, status;
- unsigned int end;
-
- end = this->chipsize >> this->erase_shift;
- for (block = 0; block < end; block++) {
- /* Set block address */
- value = onenand_block_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
- /* Select DataRAM for DDP */
- value = onenand_bufferram_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
- /* Set start block address */
- this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
-
- /* Check lock status */
- status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
- if (!(status & ONENAND_WP_US)) {
- printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status);
- return 0;
- }
- }
-
- return 1;
-}
-
-/**
- * onenand_unlock_all - [OneNAND Interface] unlock all blocks
- * @param mtd MTD device structure
- *
- * Unlock all blocks
- */
-static void onenand_unlock_all(struct mtd_info *mtd)
-{
- struct onenand_chip *this = mtd->priv;
- loff_t ofs = 0;
- size_t len = mtd->size;
-
- if (this->options & ONENAND_HAS_UNLOCK_ALL) {
- /* Set start block address */
- this->write_word(0, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
- /* Write unlock command */
- this->command(mtd, ONENAND_CMD_UNLOCK_ALL, 0, 0);
-
- /* There's no return value */
- this->wait(mtd, FL_LOCKING);
-
- /* Sanity check */
- while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS)
- & ONENAND_CTRL_ONGO)
- continue;
-
- /* Check lock status */
- if (onenand_check_lock_status(this))
- return;
-
- /* Workaround for all block unlock in DDP */
- if (ONENAND_IS_DDP(this) && !FLEXONENAND(this)) {
- /* All blocks on another chip */
- ofs = this->chipsize >> 1;
- len = this->chipsize >> 1;
- }
- }
-
- onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK);
-}
-
-/**
- * onenand_lock_tight - [OneNAND Interface] Lock-tight block(s)
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- * @param len number of bytes to lock-tight
- *
- * Lock-tight one or more blocks
- */
-static int onenand_lock_tight(struct mtd_info *mtd, loff_t ofs, size_t len)
-{
- int ret;
-
- onenand_get_device(mtd, FL_LOCKING);
- ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK_TIGHT);
- onenand_release_device(mtd);
- return ret;
-}
-
-/**
- * onenand_block_islock - [MTD Interface] Check whether the block at the given offset is locked
- * @param mtd MTD device structure
- * @param ofs offset relative to mtd start
- *
- * Check whether the block is bad
- */
-static int onenand_block_islock(struct mtd_info *mtd, loff_t ofs)
-{
- struct onenand_chip *this = mtd->priv;
- int block, value, status;
-
- /* Check for invalid offset */
- if (ofs > mtd->size)
- return -EINVAL;
-
- onenand_get_device(mtd, FL_READING);
-
- block = onenand_block(this, ofs);
- /* Set block address */
- value = onenand_block_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
- /* Select DataRAM for DDP */
- value = onenand_bufferram_address(this, block);
- this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
- /* Set start block address */
- this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
-
- /* Check lock status */
- status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
-
- onenand_release_device(mtd);
-
- return status;
-}
-
-/**
- * onenand_check_features - Check and set OneNAND features
- * @param mtd MTD data structure
- *
- * Check and set OneNAND features
- * - lock scheme
- * - two plane
- */
-static void onenand_check_features(struct mtd_info *mtd)
-{
- struct onenand_chip *this = mtd->priv;
- unsigned int density, process;
- unsigned int syscfg;
-
- /* Lock scheme depends on density and process */
- density = onenand_get_density(this->device_id);
- process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
-
- /* Lock scheme */
- switch (density) {
- case ONENAND_DEVICE_DENSITY_4Gb:
- if (ONENAND_IS_DDP(this))
- this->options |= ONENAND_HAS_2PLANE;
- else
- this->options |= ONENAND_HAS_4KB_PAGE;
-
- case ONENAND_DEVICE_DENSITY_2Gb:
- /* 2Gb DDP don't have 2 plane */
- if (!ONENAND_IS_DDP(this))
- this->options |= ONENAND_HAS_2PLANE;
- this->options |= ONENAND_HAS_UNLOCK_ALL;
-
- case ONENAND_DEVICE_DENSITY_1Gb:
- /* A-Die has all block unlock */
- if (process)
- this->options |= ONENAND_HAS_UNLOCK_ALL;
- break;
-
- default:
- /* Some OneNAND has continuous lock scheme */
- if (!process)
- this->options |= ONENAND_HAS_CONT_LOCK;
- break;
- }
-
- if (ONENAND_IS_4KB_PAGE(this))
- this->options &= ~ONENAND_HAS_2PLANE;
-
- if (FLEXONENAND(this)) {
- this->options &= ~ONENAND_HAS_CONT_LOCK;
- this->options |= ONENAND_HAS_UNLOCK_ALL;
- }
-
- syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
- if (syscfg & ONENAND_SYS_CFG1_SYNC_READ) {
- printk(KERN_DEBUG "Sync Burst Mode\n");
- this->options |= ONENAND_SYNC_MODE;
- }
-
- if (this->options & ONENAND_HAS_CONT_LOCK)
- printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
- if (this->options & ONENAND_HAS_UNLOCK_ALL)
- printk(KERN_DEBUG "Chip support all block unlock\n");
-#ifdef ONENAND_LINUX
- if (this->options & ONENAND_HAS_2PLANE)
- printk(KERN_DEBUG "Chip has 2 plane\n");
-#endif
- if (this->options & ONENAND_HAS_4KB_PAGE)
- printk(KERN_DEBUG "Chip has 4KiB pagesize\n");
-}
-
-/**
- * onenand_print_device_info - Print device ID
- * @param device device ID
- *
- * Print device ID
- */
-char *onenand_print_device_info(int device, int version)
-{
- int vcc, demuxed, ddp, density, flexonenand;
- char *dev_info = malloc(80);
-#if 0
- char *p = dev_info;
-#endif
-
- vcc = device & ONENAND_DEVICE_VCC_MASK;
- demuxed = device & ONENAND_DEVICE_IS_DEMUX;
- ddp = device & ONENAND_DEVICE_IS_DDP;
- density = onenand_get_density(device);
- flexonenand = device & DEVICE_IS_FLEXONENAND;
-#if 0
- p += sprintf(dev_info, "%s%sOneNAND%s %dMB %sV 16-bit (0x%02x)",
- demuxed ? "" : "Muxed ",
- flexonenand ? "Flex-" : "",
- ddp ? "(DDP)" : "",
- (16 << density), vcc ? "2.65/3.3" : "1.8", device);
-
- sprintf(p, "\nOneNAND version = 0x%04x", version);
- printk("%s\n", dev_info);
-#endif
-
- return dev_info;
-}
-
-static const struct onenand_manufacturers onenand_manuf_ids[] = {
- {ONENAND_MFR_SAMSUNG, "Samsung"},
-};
-
-/**
- * onenand_check_maf - Check manufacturer ID
- * @param manuf manufacturer ID
- *
- * Check manufacturer ID
- */
-static int onenand_check_maf(int manuf)
-{
- int size = ARRAY_SIZE(onenand_manuf_ids);
- char *name;
- int i;
-
- for (i = 0; i < size; i++)
- if (manuf == onenand_manuf_ids[i].id)
- break;
-
- if (i < size)
- name = onenand_manuf_ids[i].name;
- else
- name = "Unknown";
-
-#ifdef ONENAND_DEBUG
- printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
-#endif
-
- return i == size;
-}
-
-/**
-* flexonenand_get_boundary - Reads the SLC boundary
-* @param onenand_info - onenand info structure
-*
-* Fill up boundary[] field in onenand_chip
-**/
-static int flexonenand_get_boundary(struct mtd_info *mtd)
-{
- struct onenand_chip *this = mtd->priv;
- unsigned int die, bdry;
- int ret, syscfg, locked;
-
- /* Disable ECC */
- syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
- this->write_word((syscfg | 0x0100), this->base + ONENAND_REG_SYS_CFG1);
-
- for (die = 0; die < this->dies; die++) {
- this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
- this->wait(mtd, FL_SYNCING);
-
- this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
- ret = this->wait(mtd, FL_READING);
-
- bdry = this->read_word(this->base + ONENAND_DATARAM);
- if ((bdry >> FLEXONENAND_PI_UNLOCK_SHIFT) == 3)
- locked = 0;
- else
- locked = 1;
- this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
-
- this->command(mtd, ONENAND_CMD_RESET, 0, 0);
- ret = this->wait(mtd, FL_RESETING);
-
- printk(KERN_INFO "Die %d boundary: %d%s\n", die,
- this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
- }
-
- /* Enable ECC */
- this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
- return 0;
-}
-
-/**
- * flexonenand_get_size - Fill up fields in onenand_chip and mtd_info
- * boundary[], diesize[], mtd->size, mtd->erasesize,
- * mtd->eraseregions
- * @param mtd - MTD device structure
- */
-static void flexonenand_get_size(struct mtd_info *mtd)
-{
- struct onenand_chip *this = mtd->priv;
- int die, i, eraseshift, density;
- int blksperdie, maxbdry;
- loff_t ofs;
-
- density = onenand_get_density(this->device_id);
- blksperdie = ((loff_t)(16 << density) << 20) >> (this->erase_shift);
- blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
- maxbdry = blksperdie - 1;
- eraseshift = this->erase_shift - 1;
-
- mtd->numeraseregions = this->dies << 1;
-
- /* This fills up the device boundary */
- flexonenand_get_boundary(mtd);
- die = 0;
- ofs = 0;
- i = -1;
- for (; die < this->dies; die++) {
- if (!die || this->boundary[die-1] != maxbdry) {
- i++;
- mtd->eraseregions[i].offset = ofs;
- mtd->eraseregions[i].erasesize = 1 << eraseshift;
- mtd->eraseregions[i].numblocks =
- this->boundary[die] + 1;
- ofs += mtd->eraseregions[i].numblocks << eraseshift;
- eraseshift++;
- } else {
- mtd->numeraseregions -= 1;
- mtd->eraseregions[i].numblocks +=
- this->boundary[die] + 1;
- ofs += (this->boundary[die] + 1) << (eraseshift - 1);
- }
- if (this->boundary[die] != maxbdry) {
- i++;
- mtd->eraseregions[i].offset = ofs;
- mtd->eraseregions[i].erasesize = 1 << eraseshift;
- mtd->eraseregions[i].numblocks = maxbdry ^
- this->boundary[die];
- ofs += mtd->eraseregions[i].numblocks << eraseshift;
- eraseshift--;
- } else
- mtd->numeraseregions -= 1;
- }
-
- /* Expose MLC erase size except when all blocks are SLC */
- mtd->erasesize = 1 << this->erase_shift;
- if (mtd->numeraseregions == 1)
- mtd->erasesize >>= 1;
-
- printk(KERN_INFO "Device has %d eraseregions\n", mtd->numeraseregions);
- for (i = 0; i < mtd->numeraseregions; i++)
- printk(KERN_INFO "[offset: 0x%08llx, erasesize: 0x%05x,"
- " numblocks: %04u]\n", mtd->eraseregions[i].offset,
- mtd->eraseregions[i].erasesize,
- mtd->eraseregions[i].numblocks);
-
- for (die = 0, mtd->size = 0; die < this->dies; die++) {
- this->diesize[die] = (loff_t) (blksperdie << this->erase_shift);
- this->diesize[die] -= (loff_t) (this->boundary[die] + 1)
- << (this->erase_shift - 1);
- mtd->size += this->diesize[die];
- }
-}
-
-/**
- * flexonenand_check_blocks_erased - Check if blocks are erased
- * @param mtd_info - mtd info structure
- * @param start - first erase block to check
- * @param end - last erase block to check
- *
- * Converting an unerased block from MLC to SLC
- * causes byte values to change. Since both data and its ECC
- * have changed, reads on the block give uncorrectable error.
- * This might lead to the block being detected as bad.
- *
- * Avoid this by ensuring that the block to be converted is
- * erased.
- */
-static int flexonenand_check_blocks_erased(struct mtd_info *mtd,
- int start, int end)
-{
- struct onenand_chip *this = mtd->priv;
- int i, ret;
- int block;
- struct mtd_oob_ops ops = {
- .mode = MTD_OOB_PLACE,
- .ooboffs = 0,
- .ooblen = mtd->oobsize,
- .datbuf = NULL,
- .oobbuf = this->oob_buf,
- };
- loff_t addr;
-
- printk(KERN_DEBUG "Check blocks from %d to %d\n", start, end);
-
- for (block = start; block <= end; block++) {
- addr = flexonenand_addr(this, block);
- if (onenand_block_isbad_nolock(mtd, addr, 0))
- continue;
-
- /*
- * Since main area write results in ECC write to spare,
- * it is sufficient to check only ECC bytes for change.
- */
- ret = onenand_read_oob_nolock(mtd, addr, &ops);
- if (ret)
- return ret;
-
- for (i = 0; i < mtd->oobsize; i++)
- if (this->oob_buf[i] != 0xff)
- break;
-
- if (i != mtd->oobsize) {
- printk(KERN_WARNING "Block %d not erased.\n", block);
- return 1;
- }
- }
-
- return 0;
-}
-
-/**
- * flexonenand_set_boundary - Writes the SLC boundary
- * @param mtd - mtd info structure
- */
-int flexonenand_set_boundary(struct mtd_info *mtd, int die,
- int boundary, int lock)
-{
- struct onenand_chip *this = mtd->priv;
- int ret, density, blksperdie, old, new, thisboundary;
- loff_t addr;
-
- if (die >= this->dies)
- return -EINVAL;
-
- if (boundary == this->boundary[die])
- return 0;
-
- density = onenand_get_density(this->device_id);
- blksperdie = ((16 << density) << 20) >> this->erase_shift;
- blksperdie >>= ONENAND_IS_DDP(this) ? 1 : 0;
-
- if (boundary >= blksperdie) {
- printk("flexonenand_set_boundary:"
- "Invalid boundary value. "
- "Boundary not changed.\n");
- return -EINVAL;
- }
-
- /* Check if converting blocks are erased */
- old = this->boundary[die] + (die * this->density_mask);
- new = boundary + (die * this->density_mask);
- ret = flexonenand_check_blocks_erased(mtd, min(old, new)
- + 1, max(old, new));
- if (ret) {
- printk(KERN_ERR "flexonenand_set_boundary: Please erase blocks before boundary change\n");
- return ret;
- }
-
- this->command(mtd, FLEXONENAND_CMD_PI_ACCESS, die, 0);
- this->wait(mtd, FL_SYNCING);
-
- /* Check is boundary is locked */
- this->command(mtd, FLEXONENAND_CMD_READ_PI, die, 0);
- ret = this->wait(mtd, FL_READING);
-
- thisboundary = this->read_word(this->base + ONENAND_DATARAM);
- if ((thisboundary >> FLEXONENAND_PI_UNLOCK_SHIFT) != 3) {
- printk(KERN_ERR "flexonenand_set_boundary: boundary locked\n");
- goto out;
- }
-
- printk(KERN_INFO "flexonenand_set_boundary: Changing die %d boundary: %d%s\n",
- die, boundary, lock ? "(Locked)" : "(Unlocked)");
-
- boundary &= FLEXONENAND_PI_MASK;
- boundary |= lock ? 0 : (3 << FLEXONENAND_PI_UNLOCK_SHIFT);
-
- addr = die ? this->diesize[0] : 0;
- this->command(mtd, ONENAND_CMD_ERASE, addr, 0);
- ret = this->wait(mtd, FL_ERASING);
- if (ret) {
- printk("flexonenand_set_boundary:"
- "Failed PI erase for Die %d\n", die);
- goto out;
- }
-
- this->write_word(boundary, this->base + ONENAND_DATARAM);
- this->command(mtd, ONENAND_CMD_PROG, addr, 0);
- ret = this->wait(mtd, FL_WRITING);
- if (ret) {
- printk("flexonenand_set_boundary:"
- "Failed PI write for Die %d\n", die);
- goto out;
- }
-
- this->command(mtd, FLEXONENAND_CMD_PI_UPDATE, die, 0);
- ret = this->wait(mtd, FL_WRITING);
-out:
- this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
- this->wait(mtd, FL_RESETING);
- if (!ret)
- /* Recalculate device size on boundary change*/
- flexonenand_get_size(mtd);
-
- return ret;
-}
-
-/**
- * onenand_probe - [OneNAND Interface] Probe the OneNAND device
- * @param mtd MTD device structure
- *
- * OneNAND detection method:
- * Compare the the values from command with ones from register
- */
-static int onenand_probe(struct mtd_info *mtd)
-{
- struct onenand_chip *this = mtd->priv;
- int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id;
- int density;
- int syscfg;
-#if defined(CONFIG_S5PC110) || defined(CONFIG_S5P6442)
- int onenand_if_ctrl_cfg;
-#endif
-
- /* Save system configuration 1 */
- syscfg = this->read_word(this->base + ONENAND_REG_SYS_CFG1);
-
-#if defined(CONFIG_S5PC110) || defined(CONFIG_S5P6442)
- if (syscfg & ONENAND_SYS_CFG1_WM) {
- this->write_word(syscfg & ~(ONENAND_SYS_CFG1_WM), this->base + ONENAND_REG_SYS_CFG1);
- onenand_if_ctrl_cfg = readl(0xB0600100);
- writel(onenand_if_ctrl_cfg & ~ONENAND_SYS_CFG1_WM, 0xB0600100);
- }
-#else
- /* Clear Sync. Burst Read mode to read BootRAM */
- this->write_word((syscfg & ~ONENAND_SYS_CFG1_SYNC_READ), this->base + ONENAND_REG_SYS_CFG1);
-#endif
-
- /* Send the command for reading device ID from BootRAM */
- this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM);
-
- /* Read manufacturer and device IDs from BootRAM */
- bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0);
- bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2);
-
- /* Reset OneNAND to read default register values */
- this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
-
- /* Wait reset */
- this->wait(mtd, FL_RESETING);
-
- /* Restore system configuration 1 */
- this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
-
-#if defined(CONFIG_S5PC110) || defined(CONFIG_S5P6442)
- if (syscfg & ONENAND_SYS_CFG1_WM)
- writel(onenand_if_ctrl_cfg, 0xB0600100);
-#endif
-
- /* Check manufacturer ID */
- if (onenand_check_maf(bram_maf_id))
- return -ENXIO;
-
- /* Read manufacturer and device IDs from Register */
- maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
- dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID);
- ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID);
- this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY);
-
- /* Check OneNAND device */
- if (maf_id != bram_maf_id || dev_id != bram_dev_id)
- return -ENXIO;
-
- /* Flash device information */
- mtd->name = onenand_print_device_info(dev_id, ver_id);
- this->device_id = dev_id;
- this->version_id = ver_id;
-
- /* Check OneNAND features */
- onenand_check_features(mtd);
-
- density = onenand_get_density(dev_id);
- if (FLEXONENAND(this)) {
- this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
- /* Maximum possible erase regions */
- mtd->numeraseregions = this->dies << 1;
- mtd->eraseregions = malloc(sizeof(struct mtd_erase_region_info)
- * (this->dies << 1));
- if (!mtd->eraseregions)
- return -ENOMEM;
- }
-
- /*
- * For Flex-OneNAND, chipsize represents maximum possible device size.
- * mtd->size represents the actual device size.
- */
- this->chipsize = (16 << density) << 20;
-
- /* OneNAND page size & block size */
- /* The data buffer size is equal to page size */
- mtd->writesize =
- this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
- /* We use the full BufferRAM */
- if (ONENAND_IS_4KB_PAGE(this))
- mtd->writesize <<= 1;
-
- mtd->oobsize = mtd->writesize >> 5;
- /* Pagers per block is always 64 in OneNAND */
- mtd->erasesize = mtd->writesize << 6;
- /*
- * Flex-OneNAND SLC area has 64 pages per block.
- * Flex-OneNAND MLC area has 128 pages per block.
- * Expose MLC erase size to find erase_shift and page_mask.
- */
- if (FLEXONENAND(this))
- mtd->erasesize <<= 1;
-
- this->erase_shift = ffs(mtd->erasesize) - 1;
- this->page_shift = ffs(mtd->writesize) - 1;
- this->ppb_shift = (this->erase_shift - this->page_shift);
- this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
- /* Set density mask. it is used for DDP */
- if (ONENAND_IS_DDP(this))
- this->density_mask = this->chipsize >> (this->erase_shift + 1);
- /* It's real page size */
- this->writesize = mtd->writesize;
-
- /* REVIST: Multichip handling */
-
- if (FLEXONENAND(this))
- flexonenand_get_size(mtd);
- else
- mtd->size = this->chipsize;
-
- mtd->flags = MTD_CAP_NANDFLASH;
- mtd->erase = onenand_erase;
- mtd->read = onenand_read;
- mtd->write = onenand_write;
- mtd->read_oob = onenand_read_oob;
- mtd->write_oob = onenand_write_oob;
- mtd->sync = onenand_sync;
- mtd->block_isbad = onenand_block_isbad;
- mtd->block_markbad = onenand_block_markbad;
-
- return 0;
-}
-
-/**
- * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
- * @param mtd MTD device structure
- * @param maxchips Number of chips to scan for
- *
- * This fills out all the not initialized function pointers
- * with the defaults.
- * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values.
- */
-
-int onenand_scan(struct mtd_info *mtd, int maxchips)
-{
- int i;
- struct onenand_chip *this = mtd->priv;
-
- if (!this->read_word)
- this->read_word = onenand_readw;
- if (!this->write_word)
- this->write_word = onenand_writew;
-
- if (!this->command)
- this->command = onenand_command;
- if (!this->wait)
- this->wait = onenand_wait;
- if (!this->bbt_wait)
- this->bbt_wait = onenand_bbt_wait;
- if (!this->unlock_all)
- this->unlock_all = onenand_unlock_all;
- if (!this->lock_tight)
- this->lock_tight = onenand_lock_tight;
- if (!this->block_islock)
- this->block_islock = onenand_block_islock;
-
- if (!this->read_bufferram)
- this->read_bufferram = onenand_read_bufferram;
- if (!this->write_bufferram)
- this->write_bufferram = onenand_write_bufferram;
-
- if (!this->block_markbad)
- this->block_markbad = onenand_default_block_markbad;
- if (!this->scan_bbt)
- this->scan_bbt = onenand_default_bbt;
-
- if (onenand_probe(mtd))
- return -ENXIO;
-
- /* Allocate buffers, if necessary */
- if (!this->page_buf) {
- this->page_buf = kzalloc(mtd->writesize, GFP_KERNEL);
- if (!this->page_buf) {
- printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
- return -ENOMEM;
- }
-#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
- this->verify_buf = kzalloc(mtd->writesize, GFP_KERNEL);
- if (!this->verify_buf) {
- kfree(this->page_buf);
- return -ENOMEM;
- }
-#endif
- this->options |= ONENAND_PAGEBUF_ALLOC;
- }
- if (!this->oob_buf) {
- this->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
- if (!this->oob_buf) {
- printk(KERN_ERR "onenand_scan: Can't allocate oob_buf\n");
- if (this->options & ONENAND_PAGEBUF_ALLOC) {
- this->options &= ~ONENAND_PAGEBUF_ALLOC;
- kfree(this->page_buf);
- }
- return -ENOMEM;
- }
- this->options |= ONENAND_OOBBUF_ALLOC;
- }
-
- this->state = FL_READY;
-
- /*
- * Allow subpage writes up to oobsize.
- */
- switch (mtd->oobsize) {
- case 128:
- this->ecclayout = &onenand_oob_128;
- mtd->subpage_sft = 0;
- break;
-
- case 64:
- this->ecclayout = &onenand_oob_64;
- mtd->subpage_sft = 2;
- break;
-
- case 32:
- this->ecclayout = &onenand_oob_32;
- mtd->subpage_sft = 1;
- break;
-
- default:
- printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
- mtd->oobsize);
- mtd->subpage_sft = 0;
- /* To prevent kernel oops */
- this->ecclayout = &onenand_oob_32;
- break;
- }
-
- this->subpagesize = mtd->writesize >> mtd->subpage_sft;
-
- /*
- * The number of bytes available for a client to place data into
- * the out of band area
- */
- this->ecclayout->oobavail = 0;
- for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES &&
- this->ecclayout->oobfree[i].length; i++)
- this->ecclayout->oobavail +=
- this->ecclayout->oobfree[i].length;
- mtd->oobavail = this->ecclayout->oobavail;
-
- mtd->ecclayout = this->ecclayout;
-
- return this->scan_bbt(mtd);
-}
-
-/**
- * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device
- * @param mtd MTD device structure
- */
-void onenand_release(struct mtd_info *mtd)
-{
-}
+++ /dev/null
-/*
- * linux/drivers/mtd/onenand/onenand_bbt.c
- *
- * Bad Block Table support for the OneNAND driver
- *
- * Copyright(c) 2005-2008 Samsung Electronics
- * Kyungmin Park <kyungmin.park@samsung.com>
- *
- * TODO:
- * Split BBT core and chip specific BBT.
- */
-
-#include <common.h>
-#include <linux/mtd/compat.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-#include <malloc.h>
-
-#include <asm/errno.h>
-
-#ifdef printk
-#undef printk
-#endif
-#define printk(fmt,args...) do{} while(0)
-#define puts(fmt,args...) do{} while(0)
-
-/**
- * check_short_pattern - [GENERIC] check if a pattern is in the buffer
- * @param buf the buffer to search
- * @param len the length of buffer to search
- * @param paglen the pagelength
- * @param td search pattern descriptor
- *
- * Check for a pattern at the given place. Used to search bad block
- * tables and good / bad block identifiers. Same as check_pattern, but
- * no optional empty check and the pattern is expected to start
- * at offset 0.
- */
-static int check_short_pattern(uint8_t * buf, int len, int paglen,
- struct nand_bbt_descr *td)
-{
- int i;
- uint8_t *p = buf;
-
- /* Compare the pattern */
- for (i = 0; i < td->len; i++) {
- if (p[i] != td->pattern[i])
- return -1;
- }
- return 0;
-}
-
-static int read_page_oob(struct mtd_info *mtd, loff_t from, u_char *buf)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm = this->bbm;
- struct nand_bbt_descr *bd = bbm->badblock_pattern;
- struct mtd_oob_ops ops;
- int ret, scanlen, block, j, res;
-
- scanlen = 0;
-
- ops.mode = MTD_OOB_PLACE;
- ops.ooblen = 32;
- ops.oobbuf = buf;
- ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
-
- /* Get block number * 2 */
- block = (int)(from >> (bbm->bbt_erase_shift - 1));
-
- /* Set as normal block */
- res = 0x00;
- bbm->bbt[block >> 3] &= ~(0x3 << (block & 0x6));
- bbm->bbt[block >> 3] |= res << (block & 0x6);
-
- for (j = 0; j < 2; j++) {
- ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
- if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
- res = 0x03;
- bbm->bbt[block >> 3] |= res << (block & 0x6);
- printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
- block >> 1, (unsigned int) from);
- mtd->ecc_stats.badblocks++;
- break;
- }
- }
-
- return res;
-}
-
-/**
- * create_bbt - [GENERIC] Create a bad block table by scanning the device
- * @param mtd MTD device structure
- * @param buf temporary buffer
- * @param bd descriptor for the good/bad block search pattern
- * @param chip create the table for a specific chip, -1 read all chips.
- * Applies only if NAND_BBT_PERCHIP option is set
- *
- * Create a bad block table by scanning the device
- * for the given good/bad block identify pattern
- */
-static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
- struct nand_bbt_descr *bd, int chip)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm = this->bbm;
- int i, j, numblocks, len, scanlen;
- int startblock;
- loff_t from;
- size_t readlen, ooblen;
- struct mtd_oob_ops ops;
- int rgn;
-
- printk(KERN_INFO "Scanning device for bad blocks\n");
-
- len = 1;
-
- /* We need only read few bytes from the OOB area */
- scanlen = ooblen = 0;
- readlen = bd->len;
-
- /* chip == -1 case only */
- /* Note that numblocks is 2 * (real numblocks) here;
- * see i += 2 below as it makses shifting and masking less painful
- */
- numblocks = this->chipsize >> (bbm->bbt_erase_shift - 1);
- startblock = 0;
- from = 0;
-
- ops.mode = MTD_OOB_PLACE;
- ops.ooblen = readlen;
- ops.oobbuf = buf;
- ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0;
-
- for (i = startblock; i < numblocks;) {
- int ret;
-
- for (j = 0; j < len; j++) {
- /* No need to read pages fully,
- * just read required OOB bytes */
- ret = onenand_bbt_read_oob(mtd,
- from + j * mtd->writesize +
- bd->offs, &ops);
-
- /* If it is a initial bad block, just ignore it */
- if (ret == ONENAND_BBT_READ_FATAL_ERROR)
- return -EIO;
-
- if (ret || check_short_pattern
- (&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
- bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
- printk(KERN_WARNING
- "Bad eraseblock %d at 0x%08x\n", i >> 1,
- (unsigned int)from);
- break;
- }
- }
- i += 2;
-
- if (FLEXONENAND(this)) {
- rgn = flexonenand_region(mtd, from);
- from += mtd->eraseregions[rgn].erasesize;
- } else
- from += (1 << bbm->bbt_erase_shift);
- }
-
- return 0;
-}
-
-/**
- * onenand_memory_bbt - [GENERIC] create a memory based bad block table
- * @param mtd MTD device structure
- * @param bd descriptor for the good/bad block search pattern
- *
- * The function creates a memory based bbt by scanning the device
- * for manufacturer / software marked good / bad blocks
- */
-static inline int onenand_memory_bbt(struct mtd_info *mtd,
- struct nand_bbt_descr *bd)
-{
- struct onenand_chip *this = mtd->priv;
-
- bd->options &= ~NAND_BBT_SCANEMPTY;
- return create_bbt(mtd, this->page_buf, bd, -1);
-}
-
-/**
- * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad
- * @param mtd MTD device structure
- * @param offs offset in the device
- * @param allowbbt allow access to bad block table region
- */
-static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm = this->bbm;
- int block;
- uint8_t res;
-
- /* Get block number * 2 */
- block = (int) (onenand_block(this, offs) << 1);
- res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
-
- if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
- if (res == 0x02)
- res = read_page_oob(mtd, offs, this->oob_buf);
- }
-
- MTDDEBUG (MTD_DEBUG_LEVEL2,
- "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
- (unsigned int)offs, block >> 1, res);
-
- switch ((int)res) {
- case 0x00:
- return 0;
- case 0x01:
- return 1;
- case 0x02:
- return allowbbt ? 0 : 1;
- }
-
- return 1;
-}
-
-/**
- * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s)
- * @param mtd MTD device structure
- * @param bd descriptor for the good/bad block search pattern
- *
- * The function checks, if a bad block table(s) is/are already
- * available. If not it scans the device for manufacturer
- * marked good / bad blocks and writes the bad block table(s) to
- * the selected place.
- *
- * The bad block table memory is allocated here. It must be freed
- * by calling the onenand_free_bbt function.
- *
- */
-int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm = this->bbm;
- int len, ret = 0;
-
- len = this->chipsize >> (this->erase_shift + 2);
- /* Allocate memory (2bit per block) */
- bbm->bbt = malloc(len);
- if (!bbm->bbt) {
- printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
- return -ENOMEM;
- }
- /* Clear the memory bad block table */
- memset(bbm->bbt, 0x00, len);
-
- /* Set the bad block position */
- bbm->badblockpos = ONENAND_BADBLOCK_POS;
-
- /* Set erase shift */
- bbm->bbt_erase_shift = this->erase_shift;
-
- if (!bbm->isbad_bbt)
- bbm->isbad_bbt = onenand_isbad_bbt;
-
- if (this->options & ONENAND_RUNTIME_BADBLOCK_CHECK) {
- printk(KERN_INFO "Scanning device for bad blocks (skipped)\n");
- memset(bbm->bbt, 0xaa, len);
- return 0;
- }
-
- /* Scan the device to build a memory based bad block table */
- if ((ret = onenand_memory_bbt(mtd, bd))) {
- printk(KERN_ERR
- "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
- free(bbm->bbt);
- bbm->bbt = NULL;
- }
-
- return ret;
-}
-
-/*
- * Define some generic bad / good block scan pattern which are used
- * while scanning a device for factory marked good / bad blocks.
- */
-static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
-
-static struct nand_bbt_descr largepage_memorybased = {
- .options = 0,
- .offs = 0,
- .len = 2,
- .pattern = scan_ff_pattern,
-};
-
-/**
- * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device
- * @param mtd MTD device structure
- *
- * This function selects the default bad block table
- * support for the device and calls the onenand_scan_bbt function
- */
-int onenand_default_bbt(struct mtd_info *mtd)
-{
- struct onenand_chip *this = mtd->priv;
- struct bbm_info *bbm;
-
- this->bbm = malloc(sizeof(struct bbm_info));
- if (!this->bbm)
- return -ENOMEM;
-
- bbm = this->bbm;
-
- memset(bbm, 0, sizeof(struct bbm_info));
-
- /* 1KB page has same configuration as 2KB page */
- if (!bbm->badblock_pattern)
- bbm->badblock_pattern = &largepage_memorybased;
-
- return onenand_scan_bbt(mtd, bbm->badblock_pattern);
-}
+++ /dev/null
-#
-# Copyright (C) 2010 Samsung Electronics.
-# Sanghee Kim <sh0130.kim@samsung.com>
-#
-
-include $(TOPDIR)/$(RECOVERY_BLOCK)/config.mk
-
-LIB := $(obj)libserial.a
-
-COBJS-$(CONFIG_S5P) += serial_s5pc1xx.o
-
-COBJS := $(sort $(COBJS-y))
-SRCS := $(COBJS:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+++ /dev/null
-/*
- * Copyright (C) 2009 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- * Heungjun Kim <riverful.kim@samsung.com>
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/uart.h>
-#include <asm/arch/clk.h>
-#include <serial.h>
-
-static inline struct s5p_uart *s5pc1xx_get_base_uart(int dev_index)
-{
- u32 offset = dev_index * sizeof(struct s5p_uart);
-
- return (struct s5p_uart *)(S5PC110_UART_BASE + offset);
-}
-
-/*
- * The coefficient, used to calculate the baudrate on S3C6400 UARTs is
- * calculated as
- * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT
- * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1,
- * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants:
- */
-static const int udivslot[] = {
- 0,
- 0x0080,
- 0x0808,
- 0x0888,
- 0x2222,
- 0x4924,
- 0x4a52,
- 0x54aa,
- 0x5555,
- 0xd555,
- 0xd5d5,
- 0xddd5,
- 0xdddd,
- 0xdfdd,
- 0xdfdf,
- 0xffdf,
-};
-
-void serial_setbrg_dev(const int dev_index)
-{
- struct s5p_uart *const uart = s5pc1xx_get_base_uart(dev_index);
-
- /* baudrate: 115200*/
- writel(0x23, &uart->ubrdiv);
- writew(udivslot[2], &uart->rest.slot);
-}
-
-/*
- * Initialise the serial port with the given baudrate. The settings
- * are always 8 data bits, no parity, 1 stop bit, no start bits.
- */
-int serial_init_dev(const int dev_index)
-{
- struct s5p_uart *const uart = s5pc1xx_get_base_uart(dev_index);
-
- /* reset and enable FIFOs, set triggers to the maximum */
- writel(0, &uart->ufcon);
- writel(0, &uart->umcon);
- /* 8N1 */
- writel(0x3, &uart->ulcon);
- /* No interrupts, no DMA, pure polling */
- writel(0x245, &uart->ucon);
-
- serial_setbrg_dev(dev_index);
-
- return 0;
-}
-
-static int serial_err_check(const int dev_index, int op)
-{
- struct s5p_uart *const uart = s5pc1xx_get_base_uart(dev_index);
- unsigned int mask;
-
- /*
- * UERSTAT
- * Break Detect [3]
- * Frame Err [2] : receive operation
- * Parity Err [1] : receive operation
- * Overrun Err [0] : receive operation
- */
- if (op)
- mask = 0x8;
- else
- mask = 0xf;
-
- return readl(&uart->uerstat) & mask;
-}
-
-/*
- * Read a single byte from the serial port. Returns 1 on success, 0
- * otherwise. When the function is succesfull, the character read is
- * written into its argument c.
- */
-int serial_getc_dev(const int dev_index)
-{
- struct s5p_uart *const uart = s5pc1xx_get_base_uart(dev_index);
-
- /* wait for character to arrive */
- while (!(readl(&uart->utrstat) & 0x1)) {
- if (serial_err_check(dev_index, 0))
- return 0;
- }
-
- return (int)(readl(&uart->urxh) & 0xff);
-}
-
-/*
- * Output a single byte to the serial port.
- */
-void serial_putc_dev(const char c, const int dev_index)
-{
- struct s5p_uart *const uart = s5pc1xx_get_base_uart(dev_index);
-
- /* wait for room in the tx FIFO */
- while (!(readl(&uart->utrstat) & 0x2)) {
- if (serial_err_check(dev_index, 1))
- return;
- }
-
- writel(c, &uart->utxh);
-
- /* If \n, also do \r */
- if (c == '\n')
- serial_putc_dev('\r', dev_index);
-}
-
-/*
- * Test whether a character is in the RX buffer
- */
-int serial_tstc_dev(const int dev_index)
-{
- struct s5p_uart *const uart = s5pc1xx_get_base_uart(dev_index);
-
- return (int)(readl(&uart->utrstat) & 0x1);
-}
-
-void serial_puts_dev(const char *s, const int dev_index)
-{
- while (*s)
- serial_putc_dev(*s++, dev_index);
-}
-
-/* Multi serial device functions */
-#define DECLARE_S5P_SERIAL_FUNCTIONS(port) \
-int s5p_serial##port##_init(void) { return serial_init_dev(port); } \
-void s5p_serial##port##_setbrg(void) { serial_setbrg_dev(port); } \
-int s5p_serial##port##_getc(void) { return serial_getc_dev(port); } \
-int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \
-void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \
-void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); }
-
-#define INIT_S5P_SERIAL_STRUCTURE(port, name, bus) { \
- name, \
- bus, \
- s5p_serial##port##_init, \
- NULL, \
- s5p_serial##port##_setbrg, \
- s5p_serial##port##_getc, \
- s5p_serial##port##_tstc, \
- s5p_serial##port##_putc, \
- s5p_serial##port##_puts, }
-
-DECLARE_S5P_SERIAL_FUNCTIONS(0);
-struct serial_device s5p_serial0_device =
- INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0", "S5PUART0");
-DECLARE_S5P_SERIAL_FUNCTIONS(1);
-struct serial_device s5p_serial1_device =
- INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1", "S5PUART1");
-DECLARE_S5P_SERIAL_FUNCTIONS(2);
-struct serial_device s5p_serial2_device =
- INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2", "S5PUART2");
-DECLARE_S5P_SERIAL_FUNCTIONS(3);
-struct serial_device s5p_serial3_device =
- INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3", "S5PUART3");
+++ /dev/null
-#
-# Copyright (C) 2010 Samsung Electronics.
-# Minkyu Kang <mk7.kang@samsung.com>
-#
-
-include $(TOPDIR)/$(RECOVERY_BLOCK)/config.mk
-
-LIB := $(obj)libusb.a
-
-COBJS-$(CONFIG_S5P) += s5p_usb_hs_otg.o s5p_usb_downloader.o
-
-SRCS := $(COBJS-y:.o=.c)
-OBJS := $(addprefix $(obj),$(COBJS-y))
-
-all: $(LIB)
-
-$(LIB): $(obj).depend $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-#########################################################################
-
-include $(SRCTREE)/rules.mk
-
-sinclude $(obj).depend
-
-#########################################################################
+++ /dev/null
-/*
- * Copyright (C) 2009 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- */
-
-#include <common.h>
-#include "recovery.h"
-#include "usbd.h"
-#include "s5p_usb_hs_otg.h"
-
-#ifdef RECOVERY_DEBUG
-#define PUTS(s) serial_puts (DEBUG_MARK"usb: "s)
-#else
-#define PUTS(s)
-#endif
-
-#define TX_DATA_LEN 4
-#define RX_DATA_LEN 64
-
-static char tx_data[TX_DATA_LEN] = "BSP";
-static char rx_data[RX_DATA_LEN];
-
-extern int s5p_receive_done;
-extern int s5p_usb_connected;
-extern otg_dev_t otg;
-
-static int __usb_board_init(void)
-{
- return 0;
-}
-
-int usb_board_init(void) __attribute__((weak, alias("__usb_board_init")));
-
-static void cpu_reset(void)
-{
- writel(0x1, S5PC110_SWRESET);
-}
-
-/* clear download informations */
-static void s5p_usb_clear_dnfile_info(void)
-{
- otg.dn_addr = 0;
- otg.dn_filesize = 0;
- otg.dn_ptr = 0;
-}
-
-/* start the usb controller */
-static void usb_init(void)
-{
- if (usb_board_init()) {
- PUTS("Failed to usb_board_init\n");
- return;
- }
-
- s5p_usbctl_init();
-
- PUTS("USB Start!!\n");
-
- while (!s5p_usb_connected) {
- if (s5p_usb_detect_irq()) {
- s5p_udc_int_hndlr();
- s5p_usb_clear_irq();
- }
- }
-
- s5p_usb_clear_dnfile_info();
-
- PUTS("Connected!!\n");
-}
-
-static void usb_stop(void)
-{
-}
-
-/*
- * receive the packet from host PC
- * return received size
- */
-static int usb_receive_packet(void)
-{
- while (1) {
- if (s5p_usb_detect_irq()) {
- s5p_udc_int_hndlr();
- s5p_usb_clear_irq();
- }
-
- if (s5p_receive_done) {
- s5p_receive_done = 0;
- return otg.dn_filesize;
- }
- }
-}
-
-/* setup the download informations */
-static void recv_setup(char *addr, int len)
-{
- s5p_usb_clear_dnfile_info();
-
- otg.dn_addr = (u32)addr;
- otg.dn_ptr = (u8 *) addr;
- otg.dn_filesize = len;
-}
-
-/*
- * This function is interfaced between
- * USB Device Controller and USB Downloader
- */
-struct usbd_ops *usbd_set_interface(struct usbd_ops *usbd)
-{
- usbd->usb_init = usb_init;
- usbd->usb_stop = usb_stop;
- usbd->send_data = s5p_usb_tx;
- usbd->recv_data = usb_receive_packet;
- usbd->recv_setup = recv_setup;
- usbd->tx_data = tx_data;
- usbd->rx_data = rx_data;
- usbd->tx_len = TX_DATA_LEN;
- usbd->rx_len = RX_DATA_LEN;
- usbd->ram_addr = CONFIG_SYS_DOWN_ADDR;
- usbd->cpu_reset = cpu_reset;
-
- return usbd;
-}
+++ /dev/null
-/*
- * Copyright (C) 2009 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- */
-
-#include <common.h>
-#include "s5p_usb_hs_otg.h"
-
-u32 remode_wakeup;
-u16 config_value;
-
-int s5p_receive_done;
-int s5p_usb_connected;
-
-USB_OPMODE op_mode = USB_CPU;
-USB_SPEED speed = USB_HIGH;
-
-otg_dev_t otg;
-get_status_t get_status;
-get_intf_t get_intf;
-
-enum EP_INDEX {
- EP0, EP1, EP2, EP3, EP4
-};
-
-/*------------------------------------------------*/
-/* EP0 state */
-enum EP0_STATE {
- EP0_STATE_INIT = 0,
- EP0_STATE_GD_DEV_0 = 11,
- EP0_STATE_GD_DEV_1 = 12,
- EP0_STATE_GD_DEV_2 = 13,
- EP0_STATE_GD_CFG_0 = 21,
- EP0_STATE_GD_CFG_1 = 22,
- EP0_STATE_GD_CFG_2 = 23,
- EP0_STATE_GD_CFG_3 = 24,
- EP0_STATE_GD_CFG_4 = 25,
- EP0_STATE_GD_STR_I0 = 30,
- EP0_STATE_GD_STR_I1 = 31,
- EP0_STATE_GD_STR_I2 = 32,
- EP0_STATE_GD_DEV_QUALIFIER = 33,
- EP0_STATE_INTERFACE_GET = 34,
- EP0_STATE_GET_STATUS0 = 35,
- EP0_STATE_GET_STATUS1 = 36,
- EP0_STATE_GET_STATUS2 = 37,
- EP0_STATE_GET_STATUS3 = 38,
- EP0_STATE_GET_STATUS4 = 39,
- EP0_STATE_GD_OTHER_SPEED = 40,
- EP0_STATE_GD_CFG_ONLY_0 = 41,
- EP0_STATE_GD_CFG_ONLY_1 = 42,
- EP0_STATE_GD_IF_ONLY_0 = 44,
- EP0_STATE_GD_IF_ONLY_1 = 45,
- EP0_STATE_GD_EP0_ONLY_0 = 46,
- EP0_STATE_GD_EP1_ONLY_0 = 47,
- EP0_STATE_GD_EP2_ONLY_0 = 48,
- EP0_STATE_GD_EP3_ONLY_0 = 49,
- EP0_STATE_GD_OTHER_SPEED_HIGH_1 = 51,
- EP0_STATE_GD_OTHER_SPEED_HIGH_2 = 52,
- EP0_STATE_GD_OTHER_SPEED_HIGH_3 = 53
-};
-
-/*definitions related to CSR setting */
-
-/* OTG_GOTGCTL*/
-#define B_SESSION_VALID (0x1 << 19)
-#define A_SESSION_VALID (0x1 << 18)
-
-/* OTG_GAHBCFG*/
-#define PTXFE_HALF (0<<8)
-#define PTXFE_ZERO (1<<8)
-#define NPTXFE_HALF (0<<7)
-#define NPTXFE_ZERO (1<<7)
-#define MODE_SLAVE (0<<5)
-#define MODE_DMA (1<<5)
-#define BURST_SINGLE (0<<1)
-#define BURST_INCR (1<<1)
-#define BURST_INCR4 (3<<1)
-#define BURST_INCR8 (5<<1)
-#define BURST_INCR16 (7<<1)
-#define GBL_INT_UNMASK (1<<0)
-#define GBL_INT_MASK (0<<0)
-
-/* OTG_GRSTCTL*/
-#define AHB_MASTER_IDLE (1u<<31)
-#define CORE_SOFT_RESET (0x1<<0)
-
-/* OTG_GINTSTS/OTG_GINTMSK core interrupt register */
-#define INT_RESUME (1u<<31)
-#define INT_DISCONN (0x1<<29)
-#define INT_CONN_ID_STS_CNG (0x1<<28)
-#define INT_OUT_EP (0x1<<19)
-#define INT_IN_EP (0x1<<18)
-#define INT_ENUMDONE (0x1<<13)
-#define INT_RESET (0x1<<12)
-#define INT_SUSPEND (0x1<<11)
-#define INT_TX_FIFO_EMPTY (0x1<<5)
-#define INT_RX_FIFO_NOT_EMPTY (0x1<<4)
-#define INT_SOF (0x1<<3)
-#define INT_DEV_MODE (0x0<<0)
-#define INT_HOST_MODE (0x1<<1)
-#define INT_OTG (0x1<<2)
-
-/* OTG_GRXSTSP STATUS*/
-#define GLOBAL_OUT_NAK (0x1<<17)
-#define OUT_PKT_RECEIVED (0x2<<17)
-#define OUT_TRNASFER_COMPLETED (0x3<<17)
-#define SETUP_TRANSACTION_COMPLETED (0x4<<17)
-#define SETUP_PKT_RECEIVED (0x6<<17)
-
-/* OTG_DCTL device control register */
-#define NORMAL_OPERATION (0x1<<0)
-#define SOFT_DISCONNECT (0x1<<1)
-#define TEST_J_MODE (TEST_J<<4)
-#define TEST_K_MODE (TEST_K<<4)
-#define TEST_SE0_NAK_MODE (TEST_SE0_NAK<<4)
-#define TEST_PACKET_MODE (TEST_PACKET<<4)
-#define TEST_FORCE_ENABLE_MODE (TEST_FORCE_ENABLE<<4)
-#define TEST_CONTROL_FIELD (0x7<<4)
-
-/* OTG_DAINT device all endpoint interrupt register */
-#define INT_IN_EP0 (0x1<<0)
-#define INT_IN_EP1 (0x1<<1)
-#define INT_IN_EP3 (0x1<<3)
-#define INT_OUT_EP0 (0x1<<16)
-#define INT_OUT_EP2 (0x1<<18)
-#define INT_OUT_EP4 (0x1<<20)
-
-/* OTG_DIEPCTL0/OTG_DOEPCTL0 */
-#define DEPCTL_EPENA (0x1<<31)
-#define DEPCTL_EPDIS (0x1<<30)
-#define DEPCTL_SNAK (0x1<<27)
-#define DEPCTL_CNAK (0x1<<26)
-#define DEPCTL_CTRL_TYPE (EP_TYPE_CONTROL<<18)
-#define DEPCTL_ISO_TYPE (EP_TYPE_ISOCHRONOUS<<18)
-#define DEPCTL_BULK_TYPE (EP_TYPE_BULK<<18)
-#define DEPCTL_INTR_TYPE (EP_TYPE_INTERRUPT<<18)
-#define DEPCTL_USBACTEP (0x1<<15)
-
-/*ep0 enable, clear nak, next ep0, max 64byte */
-#define EPEN_CNAK_EP0_64 (DEPCTL_EPENA|DEPCTL_CNAK|(CONTROL_EP<<11)|(0<<0))
-
-/*ep0 enable, clear nak, next ep0, 8byte */
-#define EPEN_CNAK_EP0_8 (DEPCTL_EPENA|DEPCTL_CNAK|(CONTROL_EP<<11)|(3<<0))
-
-/* DIEPCTLn/DOEPCTLn */
-#define BACK2BACK_SETUP_RECEIVED (0x1<<6)
-#define INTKN_TXFEMP (0x1<<4)
-#define NON_ISO_IN_EP_TIMEOUT (0x1<<3)
-#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1<<3)
-#define AHB_ERROR (0x1<<2)
-#define TRANSFER_DONE (0x1<<0)
-
-/* codes representing languages */
-const u8 string_desc0[] = {
- 4, STRING_DESCRIPTOR, LANGID_US_L, LANGID_US_H,
-};
-
-#ifdef CONFIG_SAMSUNG_USB
-const u8 string_desc1[] = /* Manufacturer */
-{
- (0x14 + 2), STRING_DESCRIPTOR,
- 'S', 0x0, '/', 0x0, 'W', 0x0, ' ', 0x0, 'C', 0x0,
- 'e', 0x0, 'n', 0x0, 't', 0x0, 'e', 0x0, 'r', 0x0,
-};
-#else
-const u8 string_desc1[] = /* Manufacturer */
-{
- (0x14 + 2), STRING_DESCRIPTOR,
- 'S', 0x0, 'y', 0x0, 's', 0x0, 't', 0x0, 'e', 0x0,
- 'm', 0x0, ' ', 0x0, 'M', 0x0, 'C', 0x0, 'U', 0x0,
-};
-#endif
-
-#ifdef CONFIG_SAMSUNG_USB
-const u8 string_desc2[] = /* Product */
-{
- (0x24 + 2), STRING_DESCRIPTOR,
- 'S', 0x0, 'A', 0x0, 'M', 0x0, 'S', 0x0, 'U', 0x0,
- 'N', 0x0, 'G', 0x0, ' ', 0x0, 'S', 0x0, 'L', 0x0,
- 'P', 0x0, ' ', 0x0, 'D', 0x0, 'R', 0x0, 'I', 0x0,
- 'V', 0x0, 'E', 0x0, 'R', 0x0
-};
-#else
-const u8 string_desc2[] = /* Product */
-{
- (0x2a + 2), STRING_DESCRIPTOR,
- 'S', 0x0, 'E', 0x0, 'C', 0x0, ' ', 0x0, 'S', 0x0,
- '3', 0x0, 'C', 0x0, '6', 0x0, '4', 0x0, '0', 0x0,
- '0', 0x0, 'X', 0x0, ' ', 0x0, 'T', 0x0, 'e', 0x0,
- 's', 0x0, 't', 0x0, ' ', 0x0, 'B', 0x0, '/', 0x0,
- 'D', 0x0
-};
-#endif
-
-/* setting the device qualifier descriptor and a string descriptor */
-const u8 qualifier_desc[] = {
- 0x0a, /* 0 desc size */
- 0x06, /* 1 desc type (DEVICE_QUALIFIER) */
- 0x00, /* 2 USB release */
- 0x02, /* 3 => 2.00 */
- 0xFF, /* 4 class */
- 0x00, /* 5 subclass */
- 0x00, /* 6 protocol */
- 64, /* 7 max pack size */
- 0x01, /* 8 number of other-speed configuration */
- 0x00, /* 9 reserved */
-};
-
-const u8 config_full[] = {
- 0x09, /* 0 desc size */
- 0x07, /* 1 desc type (other speed) */
- 0x20, /* 2 Total length of data returned */
- 0x00, /* 3 */
- 0x01, /* 4 Number of interfaces */
- 0x01, /* 5 value to use to select configuration */
- 0x00, /* 6 index of string desc */
- /* 7 same as configuration desc */
- CONF_ATTR_DEFAULT | CONF_ATTR_SELFPOWERED,
- 0x19, /* 8 same as configuration desc */
-
-};
-
-const u8 config_full_total[] = {
- 0x09, 0x07, 0x20, 0x00, 0x01, 0x01, 0x00, 0xC0, 0x19,
- 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x00,
- 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
- 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00
-};
-
-const u8 config_high[] = {
- 0x09, /* 0 desc size */
- 0x07, /* 1 desc type (other speed) */
- 0x20, /* 2 Total length of data returned */
- 0x00, /* 3 */
- 0x01, /* 4 Number of interfaces */
- 0x01, /* 5 value to use to select configuration */
- 0x00, /* 6 index of string desc */
- /* 7 same as configuration desc */
- CONF_ATTR_DEFAULT | CONF_ATTR_SELFPOWERED,
- 0x19, /* 8 same as configuration desc */
-
-};
-
-const u8 config_high_total[] = {
- 0x09, 0x07, 0x20, 0x00, 0x01, 0x01, 0x00, 0xC0, 0x19,
- 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0x00, 0x00, 0x00,
- 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00,
- 0x07, 0x05, 0x02, 0x02, 0x00, 0x02, 0x00
-};
-
-/* Descriptor size */
-enum DESCRIPTOR_SIZE {
- DEVICE_DESC_SIZE = sizeof(device_desc_t),
- STRING_DESC0_SIZE = sizeof(string_desc0),
- STRING_DESC1_SIZE = sizeof(string_desc1),
- STRING_DESC2_SIZE = sizeof(string_desc2),
- CONFIG_DESC_SIZE = sizeof(config_desc_t),
- INTERFACE_DESC_SIZE = sizeof(intf_desc_t),
- ENDPOINT_DESC_SIZE = sizeof(ep_desc_t),
- DEVICE_QUALIFIER_SIZE = sizeof(qualifier_desc),
- OTHER_SPEED_CFG_SIZE = 9
-};
-
-/*32 <cfg desc>+<if desc>+<endp0 desc>+<endp1 desc>*/
-#define CONFIG_DESC_TOTAL_SIZE \
- (CONFIG_DESC_SIZE+INTERFACE_DESC_SIZE+ENDPOINT_DESC_SIZE*2)
-
-void usleep(unsigned int t)
-{
- int i;
- for (i = 0; i < t * 1000; i++)
- ;
-}
-
-static unsigned int phy_base;
-static unsigned int otg_base;
-
-static inline void s5p_usb_init_base(void)
-{
- phy_base = samsung_get_base_usb_phy();
- otg_base = samsung_get_base_usb_otg();
-}
-
-static inline int s5pc1xx_phy_read_reg(int offset)
-{
- return readl(phy_base + offset);
-}
-
-static inline void s5pc1xx_phy_write_reg(int value, int offset)
-{
- writel(value, phy_base + offset);
-}
-
-static inline int s5pc1xx_otg_read_reg(int offset)
-{
- return readl(otg_base + offset);
-}
-
-static inline void s5pc1xx_otg_write_reg(int value, int offset)
-{
- writel(value, otg_base + offset);
-}
-
-static void s5p_usb_init_phy(void)
-{
- s5pc1xx_phy_write_reg(0xA0, OTG_PHYPWR);
- s5pc1xx_phy_write_reg(0x3, OTG_PHYCTRL);
-
- s5pc1xx_phy_write_reg(0x1, OTG_RSTCON);
- usleep(20);
- s5pc1xx_phy_write_reg(0x0, OTG_RSTCON);
- usleep(20);
-}
-
-int s5p_usb_detect_irq(void)
-{
- u32 status;
- status = s5pc1xx_otg_read_reg(OTG_GINTSTS);
- return (status & 0x800c3810);
-}
-
-void s5p_usb_clear_irq(void)
-{
- s5pc1xx_otg_write_reg(0xffffffff, OTG_GINTSTS);
-}
-
-static void s5p_usb_core_soft_reset(void)
-{
- u32 tmp;
-
- s5pc1xx_otg_write_reg(CORE_SOFT_RESET, OTG_GRSTCTL);
-
- do {
- tmp = s5pc1xx_otg_read_reg(OTG_GRSTCTL);
- } while (!(tmp & AHB_MASTER_IDLE));
-}
-
-static void s5p_usb_wait_cable_insert(void)
-{
- u32 tmp;
- int ucFirst = 1;
-
- do {
- usleep(50);
-
- tmp = s5pc1xx_otg_read_reg(OTG_GOTGCTL);
-
- if (tmp & (B_SESSION_VALID | A_SESSION_VALID))
- break;
- else if (ucFirst == 1)
- ucFirst = 0;
- } while (1);
-}
-
-static void s5p_usb_init_core(void)
-{
- s5pc1xx_otg_write_reg(PTXFE_HALF | NPTXFE_HALF | MODE_SLAVE |
- BURST_SINGLE | GBL_INT_UNMASK, OTG_GAHBCFG);
-
- s5pc1xx_otg_write_reg(
- 0x0 << 15 /* PHY Low Power Clock sel */
- | 0x1 << 14 /* Non-Periodic TxFIFO Rewind Enable */
- | 0x5 << 10 /* Turnaround time */
- | 0x0 << 9 /* 0:HNP disable, 1:HNP enable */
- | 0x0 << 8 /* 0:SRP disable, 1:SRP enable */
- | 0x0 << 7 /* ULPI DDR sel */
- | 0x0 << 6 /* 0: high speed utmi+, 1: full speed serial */
- | 0x0 << 4 /* 0: utmi+, 1:ulpi */
- | 0x1 << 3 /* phy i/f 0:8bit, 1:16bit */
- | 0x7 << 0, /* HS/FS Timeout* */
- OTG_GUSBCFG);
-}
-
-static void s5p_usb_check_current_mode(u8 *pucMode)
-{
- u32 tmp;
-
- tmp = s5pc1xx_otg_read_reg(OTG_GINTSTS);
- *pucMode = tmp & 0x1;
-}
-
-static void s5p_usb_soft_disconnect(int set)
-{
- u32 tmp;
-
- tmp = s5pc1xx_otg_read_reg(OTG_DCTL);
- if (set)
- tmp |= SOFT_DISCONNECT;
- else
- tmp &= ~SOFT_DISCONNECT;
- s5pc1xx_otg_write_reg(tmp, OTG_DCTL);
-}
-
-static void s5p_usb_init_device(void)
-{
- s5pc1xx_otg_write_reg(1 << 18 | otg.speed << 0, OTG_DCFG);
-
- s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP | INT_IN_EP |
- INT_ENUMDONE | INT_RESET | INT_SUSPEND |
- INT_RX_FIFO_NOT_EMPTY, OTG_GINTMSK);
-}
-
-int s5p_usbctl_init(void)
-{
- u8 ucMode;
- u32 reg;
-
- s5p_usb_init_base();
-
- reg = readl(S5PC110_USB_PHY_CON);
- reg |= (1 << 0); /* USB PHY0 enable */
- writel(reg, S5PC110_USB_PHY_CON);
-
- otg.speed = speed;
- otg.set_config = 0;
- otg.ep0_state = EP0_STATE_INIT;
- otg.ep0_substate = 0;
-
- s5p_usb_init_phy();
- s5p_usb_core_soft_reset();
- s5p_usb_wait_cable_insert();
- s5p_usb_init_core();
- s5p_usb_check_current_mode(&ucMode);
-
- if (ucMode == INT_DEV_MODE) {
- s5p_usb_soft_disconnect(1);
- usleep(10);
- s5p_usb_soft_disconnect(0);
- s5p_usb_init_device();
- return 0;
- } else {
- return 0;
- }
-}
-
-static void s5p_usb_set_inep_xfersize(EP_TYPE type, u32 pktcnt, u32 xfersize)
-{
- if (type == EP_TYPE_CONTROL) {
- s5pc1xx_otg_write_reg((pktcnt << 19) | (xfersize << 0),
- OTG_DIEPTSIZ0);
- } else if (type == EP_TYPE_BULK) {
- s5pc1xx_otg_write_reg((1 << 29) | (pktcnt << 19) |
- (xfersize << 0), OTG_DIEPTSIZ_IN);
- }
-}
-
-static void s5p_usb_set_outep_xfersize(EP_TYPE type, u32 pktcnt, u32 xfersize)
-{
- if (type == EP_TYPE_CONTROL) {
- s5pc1xx_otg_write_reg((1 << 29) | (pktcnt << 19) |
- (xfersize << 0), OTG_DOEPTSIZ0);
- } else if (type == EP_TYPE_BULK) {
- s5pc1xx_otg_write_reg((pktcnt << 19) | (xfersize << 0),
- OTG_DOEPTSIZ_OUT);
- }
-}
-
-/* works on both aligned and unaligned buffers */
-static void s5p_usb_write_ep0_fifo(u8 *buf, int num)
-{
- int i;
- u32 Wr_Data = 0;
-
- for (i = 0; i < num; i += 4) {
- Wr_Data = ((*(buf + 3)) << 24) |
- ((*(buf + 2)) << 16) |
- ((*(buf + 1)) << 8) |
- *buf;
- s5pc1xx_otg_write_reg(Wr_Data, OTG_EP0_FIFO);
- buf += 4;
- }
-}
-
-/* optimized fifo access routines, warning: only aligned buffers are supported */
-static inline void s5p_usb_write_in_fifo(u8 *buf, int num)
-{
- u32 fifo = otg_base + OTG_IN_FIFO;
- u32 *p = (u32 *)buf;
- int i;
-
- for (i = 0; i < num; i += 4)
- writel(*p++, fifo);
-}
-
-static inline void s5p_usb_read_out_fifo(u8 *buf, int num)
-{
- u32 fifo = otg_base + OTG_OUT_FIFO;
- u32 *p = (u32 *)buf;
- int i;
-
- for (i = 0; i < num; i += 4)
- *p++ = readl(fifo);
-}
-
-static void s5p_usb_get_desc(void)
-{
- switch (otg.dev_req.wValue_H) {
- case DEVICE_DESCRIPTOR:
- otg.req_length = (u32)((otg.dev_req.wLength_H << 8) |
- otg.dev_req.wLength_L);
- otg.ep0_state = EP0_STATE_GD_DEV_0;
- break;
-
- case CONFIGURATION_DESCRIPTOR:
- otg.req_length = (u32)((otg.dev_req.wLength_H << 8) |
- otg.dev_req.wLength_L);
-
- if (otg.req_length > CONFIG_DESC_SIZE)
- otg.ep0_state = EP0_STATE_GD_CFG_0;
- else
- otg.ep0_state = EP0_STATE_GD_CFG_ONLY_0;
- break;
-
- case STRING_DESCRIPTOR:
- switch (otg.dev_req.wValue_L) {
- case 0:
- otg.ep0_state = EP0_STATE_GD_STR_I0;
- break;
- case 1:
- otg.ep0_state = EP0_STATE_GD_STR_I1;
- break;
- case 2:
- otg.ep0_state = EP0_STATE_GD_STR_I2;
- break;
- default:
- break;
- }
- break;
-
- case ENDPOINT_DESCRIPTOR:
- switch (otg.dev_req.wValue_L & 0xf) {
- case 0:
- otg.ep0_state = EP0_STATE_GD_EP0_ONLY_0;
- break;
- case 1:
- otg.ep0_state = EP0_STATE_GD_EP1_ONLY_0;
- break;
- default:
- break;
- }
- break;
-
- case DEVICE_QUALIFIER:
- otg.req_length = (u32)((otg.dev_req.wLength_H << 8) |
- otg.dev_req.wLength_L);
- otg.ep0_state = EP0_STATE_GD_DEV_QUALIFIER;
- break;
-
- case OTHER_SPEED_CONFIGURATION:
- otg.req_length = (u32)((otg.dev_req.wLength_H << 8) |
- otg.dev_req.wLength_L);
- otg.ep0_state = EP0_STATE_GD_OTHER_SPEED;
- break;
- }
-}
-
-static void s5p_usb_clear_feature(void)
-{
- switch (otg.dev_req.bmRequestType) {
- case DEVICE_RECIPIENT:
- if (otg.dev_req.wValue_L == 1)
- remode_wakeup = 0;
- break;
-
- case ENDPOINT_RECIPIENT:
- if (otg.dev_req.wValue_L == 0) {
- if ((otg.dev_req.wIndex_L & 0x7f) == CONTROL_EP)
- get_status.ep_ctrl = 0;
-
- /* IN Endpoint */
- if ((otg.dev_req.wIndex_L & 0x7f) == BULK_IN_EP)
- get_status.ep_in = 0;
-
- /* OUT Endpoint */
- if ((otg.dev_req.wIndex_L & 0x7f) == BULK_OUT_EP)
- get_status.ep_out = 0;
- }
- break;
-
- default:
- break;
- }
- otg.ep0_state = EP0_STATE_INIT;
-}
-
-static void s5p_usb_set_feature(void)
-{
- switch (otg.dev_req.bmRequestType) {
- case DEVICE_RECIPIENT:
- if (otg.dev_req.wValue_L == 1)
- remode_wakeup = 1;
- break;
-
- case ENDPOINT_RECIPIENT:
- if (otg.dev_req.wValue_L == 0) {
- if ((otg.dev_req.wIndex_L & 0x7f) == CONTROL_EP)
- get_status.ep_ctrl = 1;
-
- if ((otg.dev_req.wIndex_L & 0x7f) == BULK_IN_EP)
- get_status.ep_in = 1;
-
- if ((otg.dev_req.wIndex_L & 0x7f) == BULK_OUT_EP)
- get_status.ep_out = 1;
- }
- break;
-
- default:
- break;
- }
-
- otg.ep0_state = EP0_STATE_INIT;
-}
-
-static void s5p_usb_get_status(void)
-{
- switch (otg.dev_req.bmRequestType) {
- case (0x80): /*device */
- get_status.Device = ((u8) remode_wakeup << 1) | 0x1;
- otg.ep0_state = EP0_STATE_GET_STATUS0;
- break;
-
- case (0x81): /*interface */
- get_status.Interface = 0;
- otg.ep0_state = EP0_STATE_GET_STATUS1;
- break;
-
- case (0x82): /*endpoint */
- if ((otg.dev_req.wIndex_L & 0x7f) == CONTROL_EP)
- otg.ep0_state = EP0_STATE_GET_STATUS2;
-
- if ((otg.dev_req.wIndex_L & 0x7f) == BULK_IN_EP)
- otg.ep0_state = EP0_STATE_GET_STATUS3;
-
- if ((otg.dev_req.wIndex_L & 0x7f) == BULK_OUT_EP)
- otg.ep0_state = EP0_STATE_GET_STATUS4;
- break;
-
- default:
- break;
- }
-}
-
-static void s5p_usb_ep0_int_hndlr(void)
-{
- u16 i;
- u32 buf[2] = {0x0000, };
- u16 addr;
-
- if (otg.ep0_state == EP0_STATE_INIT) {
- for (i = 0; i < 2; i++)
- buf[i] = s5pc1xx_otg_read_reg(OTG_EP0_FIFO);
-
- otg.dev_req.bmRequestType = buf[0];
- otg.dev_req.bRequest = buf[0] >> 8;
- otg.dev_req.wValue_L = buf[0] >> 16;
- otg.dev_req.wValue_H = buf[0] >> 24;
- otg.dev_req.wIndex_L = buf[1];
- otg.dev_req.wIndex_H = buf[1] >> 8;
- otg.dev_req.wLength_L = buf[1] >> 16;
- otg.dev_req.wLength_H = buf[1] >> 24;
-
- switch (otg.dev_req.bRequest) {
- case STANDARD_SET_ADDRESS:
- /* Set Address Update bit */
- addr = (otg.dev_req.wValue_L);
- s5pc1xx_otg_write_reg(1 << 18 | addr << 4 | otg.speed << 0,
- OTG_DCFG);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case STANDARD_SET_DESCRIPTOR:
- break;
-
- case STANDARD_SET_CONFIGURATION:
- /* Configuration value in configuration descriptor */
- config_value = otg.dev_req.wValue_L;
- otg.set_config = 1;
- otg.ep0_state = EP0_STATE_INIT;
-
- s5p_usb_connected = 1;
- break;
-
- case STANDARD_GET_CONFIGURATION:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
-
- /*ep0 enable, clear nak, next ep0, 8byte */
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5pc1xx_otg_write_reg(config_value, OTG_EP0_FIFO);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case STANDARD_GET_DESCRIPTOR:
- s5p_usb_get_desc();
- break;
-
- case STANDARD_CLEAR_FEATURE:
- s5p_usb_clear_feature();
- break;
-
- case STANDARD_SET_FEATURE:
- s5p_usb_set_feature();
- break;
-
- case STANDARD_GET_STATUS:
- s5p_usb_get_status();
- break;
-
- case STANDARD_GET_INTERFACE:
- otg.ep0_state = EP0_STATE_INTERFACE_GET;
- break;
-
- case STANDARD_SET_INTERFACE:
- get_intf.AlternateSetting = otg.dev_req.wValue_L;
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case STANDARD_SYNCH_FRAME:
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- default:
- break;
- }
- }
-
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, otg.ctrl_max_pktsize);
-
- /*clear nak, next ep0, 64byte */
- s5pc1xx_otg_write_reg(((1 << 26) | (CONTROL_EP << 11) | (0 << 0)),
- OTG_DIEPCTL0);
-}
-
-static void s5p_usb_set_otherspeed_conf_desc(u32 length)
-{
- /* Standard device descriptor */
- if (length == 9) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 9);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &config_full, 9);
- } else if (length == 32) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 32);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &config_full_total, 32);
- }
- otg.ep0_state = EP0_STATE_INIT;
-}
-
-static void s5p_usb_transfer_ep0(void)
-{
- switch (otg.ep0_state) {
- case EP0_STATE_INIT:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 0);
-
- /*ep0 enable, clear nak, next ep0, 8byte */
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- break;
-
- case EP0_STATE_GD_DEV_0:
- /*ep0 enable, clear nak, next ep0, max 64byte */
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- if (otg.req_length < DEVICE_DESC_SIZE) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- otg.req_length);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)),
- otg.req_length);
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- DEVICE_DESC_SIZE);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)),
- DEVICE_DESC_SIZE);
- }
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_DEV_1:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- if (otg.req_length < (2 * FS_CTRL_PKT_SIZE)) {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)) +
- FS_CTRL_PKT_SIZE,
- otg.req_length - FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- } else {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)) +
- FS_CTRL_PKT_SIZE, FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_GD_DEV_2;
- }
- break;
-
- case EP0_STATE_GD_DEV_2:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- if (otg.req_length < DEVICE_DESC_SIZE) {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)) +
- (2 * FS_CTRL_PKT_SIZE),
- otg.req_length - 2 * FS_CTRL_PKT_SIZE);
- } else {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)) +
- (2 * FS_CTRL_PKT_SIZE),
- DEVICE_DESC_SIZE - 2 * FS_CTRL_PKT_SIZE);
- }
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_CFG_0:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- if (otg.req_length < CONFIG_DESC_TOTAL_SIZE) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- otg.req_length);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)),
- otg.req_length);
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- CONFIG_DESC_TOTAL_SIZE);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)),
- CONFIG_DESC_TOTAL_SIZE);
- }
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_CFG_1:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- if (otg.req_length < (2 * FS_CTRL_PKT_SIZE)) {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- FS_CTRL_PKT_SIZE,
- (otg.req_length - FS_CTRL_PKT_SIZE));
- otg.ep0_state = EP0_STATE_INIT;
- } else {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- FS_CTRL_PKT_SIZE, FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_GD_CFG_2;
- }
- break;
-
- case EP0_STATE_GD_CFG_2:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- if (otg.req_length < (3 * FS_CTRL_PKT_SIZE)) {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- (2 * FS_CTRL_PKT_SIZE),
- otg.req_length - 2 * FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- } else {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- (2 * FS_CTRL_PKT_SIZE), FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_GD_CFG_3;
- }
- break;
-
- case EP0_STATE_GD_CFG_3:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- if (otg.req_length < (4 * FS_CTRL_PKT_SIZE)) {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- (3 * FS_CTRL_PKT_SIZE),
- otg.req_length - 3 * FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- } else {
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- (3 * FS_CTRL_PKT_SIZE), FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_GD_CFG_4;
- }
- break;
-
- case EP0_STATE_GD_CFG_4:
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_DEV_QUALIFIER:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- if (otg.req_length < 10) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- otg.req_length);
- s5p_usb_write_ep0_fifo((u8 *)qualifier_desc,
- otg.req_length);
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 10);
- s5p_usb_write_ep0_fifo((u8 *)qualifier_desc, 10);
- }
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_OTHER_SPEED:
- s5p_usb_set_otherspeed_conf_desc(otg.req_length);
- break;
-
- case EP0_STATE_GD_OTHER_SPEED_HIGH_1:
- if (otg.req_length == 9) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &config_high) + 8, 1);
- otg.ep0_state = EP0_STATE_INIT;
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 8);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &config_high) + 8, 8);
- otg.ep0_state = EP0_STATE_GD_OTHER_SPEED_HIGH_2;
- }
- break;
-
- case EP0_STATE_GD_OTHER_SPEED_HIGH_2:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 8);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &config_high) + 16, 8);
- otg.ep0_state = EP0_STATE_GD_OTHER_SPEED_HIGH_3;
- break;
-
- case EP0_STATE_GD_OTHER_SPEED_HIGH_3:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 8);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &config_high) + 24, 8);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_CFG_ONLY_0:
- if (otg.req_length < CONFIG_DESC_SIZE) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- otg.req_length);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)),
- otg.req_length);
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- CONFIG_DESC_SIZE);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)),
- CONFIG_DESC_SIZE);
- }
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_CFG_ONLY_1:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)) +
- FS_CTRL_PKT_SIZE,
- CONFIG_DESC_SIZE - FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_IF_ONLY_0:
- if (otg.req_length < INTERFACE_DESC_SIZE) {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- otg.req_length);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.intf)),
- otg.req_length);
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1,
- INTERFACE_DESC_SIZE);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.intf)),
- INTERFACE_DESC_SIZE);
- }
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_IF_ONLY_1:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.intf)) +
- FS_CTRL_PKT_SIZE,
- INTERFACE_DESC_SIZE - FS_CTRL_PKT_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_EP0_ONLY_0:
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, ENDPOINT_DESC_SIZE);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.ep1)),
- ENDPOINT_DESC_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_EP1_ONLY_0:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, ENDPOINT_DESC_SIZE);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.ep2)),
- ENDPOINT_DESC_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_STR_I0:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, STRING_DESC0_SIZE);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *)string_desc0, STRING_DESC0_SIZE);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GD_STR_I1:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, sizeof(string_desc1));
- if ((otg.ep0_substate * otg.ctrl_max_pktsize +
- otg.ctrl_max_pktsize) < sizeof(string_desc1)) {
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
-
- s5p_usb_write_ep0_fifo((u8 *)string_desc1 +
- (otg.ep0_substate * otg.ctrl_max_pktsize),
- otg.ctrl_max_pktsize);
- otg.ep0_state = EP0_STATE_GD_STR_I1;
- otg.ep0_substate++;
- } else {
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
-
- s5p_usb_write_ep0_fifo((u8 *)string_desc1 +
- (otg.ep0_substate * otg.ctrl_max_pktsize),
- sizeof(string_desc1) - (otg.ep0_substate *
- otg.ctrl_max_pktsize));
- otg.ep0_state = EP0_STATE_INIT;
- otg.ep0_substate = 0;
- }
- break;
-
- case EP0_STATE_GD_STR_I2:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, sizeof(string_desc2));
- if ((otg.ep0_substate * otg.ctrl_max_pktsize +
- otg.ctrl_max_pktsize) < sizeof(string_desc2)) {
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
-
- s5p_usb_write_ep0_fifo((u8 *) string_desc2 +
- (otg.ep0_substate * otg.ctrl_max_pktsize),
- otg.ctrl_max_pktsize);
- otg.ep0_state = EP0_STATE_GD_STR_I2;
- otg.ep0_substate++;
- } else {
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) string_desc2 +
- (otg.ep0_substate * otg.ctrl_max_pktsize),
- sizeof(string_desc2) - (otg.ep0_substate *
- otg.ctrl_max_pktsize));
- otg.ep0_state = EP0_STATE_INIT;
- otg.ep0_substate = 0;
- }
- break;
-
- case EP0_STATE_INTERFACE_GET:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &get_intf, 1);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GET_STATUS0:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &get_status, 1);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GET_STATUS1:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &get_status + 1, 1);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GET_STATUS2:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &get_status + 2, 1);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GET_STATUS3:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &get_status + 3, 1);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- case EP0_STATE_GET_STATUS4:
- s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 1);
- s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0);
- s5p_usb_write_ep0_fifo((u8 *) &get_status + 4, 1);
- otg.ep0_state = EP0_STATE_INIT;
- break;
-
- default:
- break;
- }
-}
-
-void s5p_usb_tx(char *tx_data, int tx_size)
-{
- otg.up_ptr = (u8 *) tx_data;
- otg.up_addr = (u32) tx_data;
- otg.up_size = tx_size;
-
- if (otg.op_mode == USB_CPU) {
- if (otg.up_size > otg.bulkin_max_pktsize) {
- s5p_usb_set_inep_xfersize(EP_TYPE_BULK, 1,
- otg.bulkin_max_pktsize);
- } else {
- s5p_usb_set_inep_xfersize(EP_TYPE_BULK, 1, otg.up_size);
- }
-
- /*ep1 enable, clear nak, bulk, usb active, max pkt */
- s5pc1xx_otg_write_reg(1u << 31 | 1 << 26 | 2 << 18 | 1 << 15 |
- otg.bulkin_max_pktsize << 0, OTG_DIEPCTL_IN);
-
- s5p_usb_write_in_fifo(otg.up_ptr, otg.up_size);
- }
-}
-
-static void s5p_usb_int_bulkout(u32 fifo_cnt_byte)
-{
- s5p_usb_read_out_fifo((u8 *)otg.dn_ptr, fifo_cnt_byte);
- otg.dn_ptr += fifo_cnt_byte;
-
- s5p_usb_set_outep_xfersize(EP_TYPE_BULK, 1,
- otg.bulkout_max_pktsize);
-
- /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt */
- s5pc1xx_otg_write_reg(1u << 31 | 1 << 26 | 2 << 18 | 1 << 15 |
- otg.bulkout_max_pktsize << 0, OTG_DOEPCTL_OUT);
-
- if (((u32)otg.dn_ptr - otg.dn_addr) >= (otg.dn_filesize))
- s5p_receive_done = 1;
-}
-
-static void s5p_usb_set_all_outep_nak(int set)
-{
- u8 i;
- u32 tmp;
-
- for (i = 0; i < 16; i++) {
- tmp = s5pc1xx_otg_read_reg(OTG_DOEPCTL0 + 0x20 * i);
- if (set)
- tmp |= DEPCTL_SNAK;
- else
- tmp |= (DEPCTL_EPENA | DEPCTL_CNAK);
- s5pc1xx_otg_write_reg(tmp, OTG_DOEPCTL0 + 0x20 * i);
- }
-}
-
-static void s5p_usb_set_max_pktsize(USB_SPEED speed)
-{
- otg.speed = USB_HIGH;
- otg.ctrl_max_pktsize = HS_CTRL_PKT_SIZE;
- otg.bulkin_max_pktsize = HS_BULK_PKT_SIZE;
- otg.bulkout_max_pktsize = HS_BULK_PKT_SIZE;
-}
-
-static void s5p_usb_set_endpoint(void)
-{
- /* Unmask OTG_DAINT source */
- s5pc1xx_otg_write_reg(0xff, OTG_DIEPINT0);
- s5pc1xx_otg_write_reg(0xff, OTG_DOEPINT0);
- s5pc1xx_otg_write_reg(0xff, OTG_DIEPINT_IN);
- s5pc1xx_otg_write_reg(0xff, OTG_DOEPINT_OUT);
-
- /* Init For Ep0 */
- /*MPS:64bytes */
- s5pc1xx_otg_write_reg(((1 << 26) | (CONTROL_EP << 11) | (0 << 0)),
- OTG_DIEPCTL0);
- /*ep0 enable, clear nak */
- s5pc1xx_otg_write_reg((1u << 31) | (1 << 26) | (0 << 0),
- OTG_DOEPCTL0);
-}
-
-static void s5p_usb_set_descriptors(void)
-{
-#if defined (CONFIG_SAMSUNG_USB)
- otg.desc.dev.bLength = DEVICE_DESC_SIZE;
- otg.desc.dev.bDescriptorType = DEVICE_DESCRIPTOR;
- otg.desc.dev.bDeviceClass = 0xFF;
- otg.desc.dev.bDeviceSubClass = 0x0;
- otg.desc.dev.bDeviceProtocol = 0x0;
- otg.desc.dev.bMaxPacketSize0 = otg.ctrl_max_pktsize;
- otg.desc.dev.idVendorL = 0xE8;
- otg.desc.dev.idVendorH = 0x04;
- otg.desc.dev.idProductL = 0x04;
- otg.desc.dev.idProductH = 0x12;
- otg.desc.dev.iManufacturer = 0x0;
- otg.desc.dev.iProduct = 0x2;
- otg.desc.dev.iSerialNumber = 0x0;
- otg.desc.dev.bNumConfigurations = 0x1;
- otg.desc.dev.bcdUSBL = 0x00;
- otg.desc.dev.bcdUSBH = 0x02;
-
- otg.desc.config.bLength = CONFIG_DESC_SIZE;
- otg.desc.config.bDescriptorType = CONFIGURATION_DESCRIPTOR;
- otg.desc.config.wTotalLengthL = CONFIG_DESC_TOTAL_SIZE;
- otg.desc.config.wTotalLengthH = 0;
- otg.desc.config.bNumInterfaces = 1;
- otg.desc.config.bConfigurationValue = 1;
- otg.desc.config.iConfiguration = 0;
- otg.desc.config.bmAttributes = CONF_ATTR_DEFAULT | CONF_ATTR_SELFPOWERED;
- otg.desc.config.maxPower = 50;
-#else
- otg.desc.dev.bLength = DEVICE_DESC_SIZE;
- otg.desc.dev.bDescriptorType = DEVICE_DESCRIPTOR;
- otg.desc.dev.bDeviceClass = 0xFF;
- otg.desc.dev.bDeviceSubClass = 0x0;
- otg.desc.dev.bDeviceProtocol = 0x0;
- otg.desc.dev.bMaxPacketSize0 = otg.ctrl_max_pktsize;
- otg.desc.dev.idVendorL = 0xE8;
- otg.desc.dev.idVendorH = 0x04;
- otg.desc.dev.idProductL = 0x34;
- otg.desc.dev.idProductH = 0x12;
- otg.desc.dev.bcdDeviceL = 0x00;
- otg.desc.dev.bcdDeviceH = 0x01;
- otg.desc.dev.iManufacturer = 0x1;
- otg.desc.dev.iProduct = 0x2;
- otg.desc.dev.iSerialNumber = 0x0;
- otg.desc.dev.bNumConfigurations = 0x1;
- otg.desc.dev.bcdUSBL = 0x00;
- otg.desc.dev.bcdUSBH = 0x02;
-
- otg.desc.config.bLength = CONFIG_DESC_SIZE;
- otg.desc.config.bDescriptorType = CONFIGURATION_DESCRIPTOR;
- otg.desc.config.wTotalLengthL = CONFIG_DESC_TOTAL_SIZE;
- otg.desc.config.wTotalLengthH = 0;
- otg.desc.config.bNumInterfaces = 1;
- otg.desc.config.bConfigurationValue = 1;
- otg.desc.config.iConfiguration = 0;
- otg.desc.config.bmAttributes = CONF_ATTR_DEFAULT | CONF_ATTR_SELFPOWERED;
- otg.desc.config.maxPower = 25;
-#endif
- otg.desc.intf.bLength = INTERFACE_DESC_SIZE;
- otg.desc.intf.bDescriptorType = INTERFACE_DESCRIPTOR;
- otg.desc.intf.bInterfaceNumber = 0x0;
- otg.desc.intf.bAlternateSetting = 0x0;
- otg.desc.intf.bNumEndpoints = 2;
- otg.desc.intf.bInterfaceClass = 0xff;
- otg.desc.intf.bInterfaceSubClass = 0xff;
- otg.desc.intf.bInterfaceProtocol = 0xff;
- otg.desc.intf.iInterface = 0x0;
-
- otg.desc.ep1.bLength = ENDPOINT_DESC_SIZE;
- otg.desc.ep1.bDescriptorType = ENDPOINT_DESCRIPTOR;
- otg.desc.ep1.bEndpointAddress = BULK_IN_EP | EP_ADDR_IN;
- otg.desc.ep1.bmAttributes = EP_ATTR_BULK;
- otg.desc.ep1.wMaxPacketSizeL = (u8)otg.bulkin_max_pktsize;
- otg.desc.ep1.wMaxPacketSizeH = (u8)(otg.bulkin_max_pktsize >> 8);
- otg.desc.ep1.bInterval = 0x0;
-
- otg.desc.ep2.bLength = ENDPOINT_DESC_SIZE;
- otg.desc.ep2.bDescriptorType = ENDPOINT_DESCRIPTOR;
- otg.desc.ep2.bEndpointAddress = BULK_OUT_EP | EP_ADDR_OUT;
- otg.desc.ep2.bmAttributes = EP_ATTR_BULK;
- otg.desc.ep2.wMaxPacketSizeL = (u8)otg.bulkout_max_pktsize;
- otg.desc.ep2.wMaxPacketSizeH = (u8)(otg.bulkout_max_pktsize >> 8);
- otg.desc.ep2.bInterval = 0x0;
-}
-
-static void s5p_usb_set_opmode(USB_OPMODE mode)
-{
- otg.op_mode = mode;
-
- s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP | INT_IN_EP | INT_ENUMDONE |
- INT_RESET | INT_SUSPEND | INT_RX_FIFO_NOT_EMPTY,
- OTG_GINTMSK);
-
- s5pc1xx_otg_write_reg(MODE_SLAVE | BURST_SINGLE | GBL_INT_UNMASK,
- OTG_GAHBCFG);
-
- s5p_usb_set_outep_xfersize(EP_TYPE_BULK, 1, otg.bulkout_max_pktsize);
- s5p_usb_set_inep_xfersize(EP_TYPE_BULK, 1, 0);
-
- /*bulk out ep enable, clear nak, bulk, usb active, next ep3, max pkt */
- s5pc1xx_otg_write_reg(1u << 31 | 1 << 26 | 2 << 18 | 1 << 15 |
- otg.bulkout_max_pktsize << 0, OTG_DOEPCTL_OUT);
-
- /*bulk in ep enable, clear nak, bulk, usb active, next ep1, max pkt */
- s5pc1xx_otg_write_reg(0u << 31 | 1 << 26 | 2 << 18 | 1 << 15 |
- otg.bulkin_max_pktsize << 0, OTG_DIEPCTL_IN);
-}
-
-static void s5p_usb_reset(void)
-{
- s5p_usb_set_all_outep_nak(1);
-
- otg.ep0_state = EP0_STATE_INIT;
- s5pc1xx_otg_write_reg(((1 << BULK_OUT_EP) | (1 << CONTROL_EP)) << 16 |
- ((1 << BULK_IN_EP) | (1 << CONTROL_EP)), OTG_DAINTMSK);
- s5pc1xx_otg_write_reg(CTRL_OUT_EP_SETUP_PHASE_DONE | AHB_ERROR |
- TRANSFER_DONE, OTG_DOEPMSK);
- s5pc1xx_otg_write_reg(INTKN_TXFEMP | NON_ISO_IN_EP_TIMEOUT | AHB_ERROR |
- TRANSFER_DONE, OTG_DIEPMSK);
-
- /* Rx FIFO Size */
- s5pc1xx_otg_write_reg(RX_FIFO_SIZE, OTG_GRXFSIZ);
-
- /* Non Periodic Tx FIFO Size */
- s5pc1xx_otg_write_reg(NPTX_FIFO_SIZE << 16 | NPTX_FIFO_START_ADDR << 0,
- OTG_GNPTXFSIZ);
-
- s5p_usb_set_all_outep_nak(0);
-
- /*clear device address */
- s5pc1xx_otg_write_reg(s5pc1xx_otg_read_reg(OTG_DCFG) & ~(0x7f << 4),
- OTG_DCFG);
-}
-
-static int s5p_usb_set_init(void)
-{
- u32 status;
-
- status = s5pc1xx_otg_read_reg(OTG_DSTS);
-
- /* Set if Device is High speed or Full speed */
- if (((status & 0x6) >> 1) == USB_HIGH)
- s5p_usb_set_max_pktsize(USB_HIGH);
- else if (((status & 0x6) >> 1) == USB_FULL)
- return 0;
- else
- return 0;
-
- s5p_usb_set_endpoint();
- s5p_usb_set_descriptors();
- s5p_usb_set_opmode(op_mode);
-
- return 1;
-}
-
-static void s5p_usb_pkt_receive(void)
-{
- u32 rx_status;
- u32 fifo_cnt_byte;
-
- rx_status = s5pc1xx_otg_read_reg(OTG_GRXSTSP);
-
- if ((rx_status & (0xf << 17)) == SETUP_PKT_RECEIVED) {
- s5p_usb_ep0_int_hndlr();
- } else if ((rx_status & (0xf << 17)) == OUT_PKT_RECEIVED) {
- fifo_cnt_byte = (rx_status & 0x7ff0) >> 4;
-
- if ((rx_status & BULK_OUT_EP) && (fifo_cnt_byte)) {
- s5p_usb_int_bulkout(fifo_cnt_byte);
- if (otg.op_mode == USB_CPU) {
- s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP |
- INT_IN_EP | INT_ENUMDONE | INT_RESET |
- INT_SUSPEND | INT_RX_FIFO_NOT_EMPTY,
- OTG_GINTMSK);
- }
- return;
- }
-
- }
-}
-
-static void s5p_usb_transfer(void)
-{
- u32 ep_int;
- u32 check_dma;
- u32 ep_int_status;
-
- ep_int = s5pc1xx_otg_read_reg(OTG_DAINT);
-
- if (ep_int & (1 << CONTROL_EP)) {
- ep_int_status = s5pc1xx_otg_read_reg(OTG_DIEPINT0);
-
- if (ep_int_status & INTKN_TXFEMP) {
- u32 uNTxFifoSpace;
- do {
- uNTxFifoSpace = s5pc1xx_otg_read_reg(OTG_GNPTXSTS)
- & 0xffff;
- } while (uNTxFifoSpace < otg.ctrl_max_pktsize);
-
- s5p_usb_transfer_ep0();
- }
-
- s5pc1xx_otg_write_reg(ep_int_status, OTG_DIEPINT0);
- }
-
- if (ep_int & ((1 << CONTROL_EP) << 16)) {
- ep_int_status = s5pc1xx_otg_read_reg(OTG_DOEPINT0);
-
- s5p_usb_set_outep_xfersize(EP_TYPE_CONTROL, 1, 8);
- s5pc1xx_otg_write_reg(1u << 31 | 1 << 26, OTG_DOEPCTL0);
-
- s5pc1xx_otg_write_reg(ep_int_status, OTG_DOEPINT0);
- }
-
- if (ep_int & (1 << BULK_IN_EP)) {
- ep_int_status = s5pc1xx_otg_read_reg(OTG_DIEPINT_IN);
-
- s5pc1xx_otg_write_reg(ep_int_status, OTG_DIEPINT_IN);
- check_dma = s5pc1xx_otg_read_reg(OTG_GAHBCFG);
- }
-
- if (ep_int & ((1 << BULK_OUT_EP) << 16)) {
- ep_int_status = s5pc1xx_otg_read_reg(OTG_DOEPINT_OUT);
-
- s5pc1xx_otg_write_reg(ep_int_status, OTG_DOEPINT_OUT);
- check_dma = s5pc1xx_otg_read_reg(OTG_GAHBCFG);
- }
-}
-
-void s5p_udc_int_hndlr(void)
-{
- u32 int_status;
- int tmp;
-
- int_status = s5pc1xx_otg_read_reg(OTG_GINTSTS);
- s5pc1xx_otg_write_reg(int_status, OTG_GINTSTS);
-
- if (int_status & INT_RESET) {
- s5pc1xx_otg_write_reg(INT_RESET, OTG_GINTSTS);
- s5p_usb_reset();
- }
-
- if (int_status & INT_ENUMDONE) {
- s5pc1xx_otg_write_reg(INT_ENUMDONE, OTG_GINTSTS);
-
- tmp = s5p_usb_set_init();
- if (tmp == 0)
- return;
- }
-
- if (int_status & INT_RESUME)
- s5pc1xx_otg_write_reg(INT_RESUME, OTG_GINTSTS);
-
- if (int_status & INT_SUSPEND)
- s5pc1xx_otg_write_reg(INT_SUSPEND, OTG_GINTSTS);
-
- if (int_status & INT_RX_FIFO_NOT_EMPTY) {
- s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP | INT_IN_EP |
- INT_ENUMDONE | INT_RESET | INT_SUSPEND,
- OTG_GINTMSK);
-
- s5p_usb_pkt_receive();
-
- s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP | INT_IN_EP |
- INT_ENUMDONE | INT_RESET | INT_SUSPEND |
- INT_RX_FIFO_NOT_EMPTY, OTG_GINTMSK);
- }
-
- if ((int_status & INT_IN_EP) || (int_status & INT_OUT_EP))
- s5p_usb_transfer();
-}
+++ /dev/null
-/*
- * Copyright (C) 2007 Samsung Electronics
- * Byungjae Lee <bjlee@samsung.com>
- */
-
-#ifndef __USBD_HS_OTG_H__
-#define __USBD_HS_OTG_H__
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-#include <asm/arch/usb-hs-otg.h>
-
-#define S5PC110_SWRESET 0xE0102000
-#define S5PC110_USB_PHY_CON 0xE010E80C
-
-#define make_word_c(w) __constant_cpu_to_le16(w)
-#define make_word(w) __cpu_to_le16(w)
-
-#define CONTROL_EP 0
-#define BULK_IN_EP 1
-#define BULK_OUT_EP 2
-#define INTR_IN_EP 3
-
-#define FS_CTRL_PKT_SIZE 8
-#define FS_BULK_PKT_SIZE 64
-
-#define HS_CTRL_PKT_SIZE 64
-#define HS_BULK_PKT_SIZE 512
-
-#define RX_FIFO_SIZE 512
-#define NPTX_FIFO_START_ADDR RX_FIFO_SIZE
-#define NPTX_FIFO_SIZE 512
-#define PTX_FIFO_SIZE 512
-
-/* string descriptor */
-#define LANGID_US_L (0x09)
-#define LANGID_US_H (0x04)
-
-/* Feature Selectors */
-#define EP_STALL 0
-#define DEVICE_REMOTE_WAKEUP 1
-#define TEST_MODE 2
-
-/* Test Mode Selector*/
-#define TEST_J 1
-#define TEST_K 2
-#define TEST_SE0_NAK 3
-#define TEST_PACKET 4
-#define TEST_FORCE_ENABLE 5
-
-#define OTG_DIEPCTL_IN (OTG_DIEPCTL0 + 0x20 * BULK_IN_EP)
-#define OTG_DIEPINT_IN (OTG_DIEPINT0 + 0x20 * BULK_IN_EP)
-#define OTG_DIEPTSIZ_IN (OTG_DIEPTSIZ0 + 0x20 * BULK_IN_EP)
-#define OTG_DIEPDMA_IN (OTG_DIEPDMA0 + 0x20 * BULK_IN_EP)
-#define OTG_DOEPCTL_OUT (OTG_DOEPCTL0 + 0x20 * BULK_OUT_EP)
-#define OTG_DOEPINT_OUT (OTG_DOEPINT0 + 0x20 * BULK_OUT_EP)
-#define OTG_DOEPTSIZ_OUT (OTG_DOEPTSIZ0 + 0x20 * BULK_OUT_EP)
-#define OTG_DOEPDMA_OUT (OTG_DOEPDMA0 + 0x20 * BULK_OUT_EP)
-#define OTG_IN_FIFO (OTG_EP0_FIFO + 0x1000 * BULK_IN_EP)
-#define OTG_OUT_FIFO (OTG_EP0_FIFO + 0x1000 * BULK_OUT_EP)
-
-typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u8 bcdUSBL;
- u8 bcdUSBH;
- u8 bDeviceClass;
- u8 bDeviceSubClass;
- u8 bDeviceProtocol;
- u8 bMaxPacketSize0;
- u8 idVendorL;
- u8 idVendorH;
- u8 idProductL;
- u8 idProductH;
- u8 bcdDeviceL;
- u8 bcdDeviceH;
- u8 iManufacturer;
- u8 iProduct;
- u8 iSerialNumber;
- u8 bNumConfigurations;
-} __attribute__ ((packed)) device_desc_t;
-
-typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u8 wTotalLengthL;
- u8 wTotalLengthH;
- u8 bNumInterfaces;
- u8 bConfigurationValue;
- u8 iConfiguration;
- u8 bmAttributes;
- u8 maxPower;
-} __attribute__ ((packed)) config_desc_t;
-
-typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u8 bInterfaceNumber;
- u8 bAlternateSetting;
- u8 bNumEndpoints;
- u8 bInterfaceClass;
- u8 bInterfaceSubClass;
- u8 bInterfaceProtocol;
- u8 iInterface;
-} __attribute__ ((packed)) intf_desc_t;
-
-typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u8 bEndpointAddress;
- u8 bmAttributes;
- u8 wMaxPacketSizeL;
- u8 wMaxPacketSizeH;
- u8 bInterval;
-} __attribute__ ((packed)) ep_desc_t;
-
-typedef struct {
- u8 bLength;
- u8 bDescriptorType;
- u16 bString[30];
-} __attribute__ ((packed)) string_desc_t;
-
-typedef struct {
- u8 bmRequestType;
- u8 bRequest;
- u8 wValue_L;
- u8 wValue_H;
- u8 wIndex_L;
- u8 wIndex_H;
- u8 wLength_L;
- u8 wLength_H;
-} __attribute__ ((packed)) device_req_t;
-
-typedef struct {
- device_desc_t dev;
- config_desc_t config;
- intf_desc_t intf;
- ep_desc_t ep1;
- ep_desc_t ep2;
- ep_desc_t ep3;
- ep_desc_t ep4;
-} __attribute__ ((packed)) descriptors_t;
-
-typedef struct {
- u8 Device;
- u8 Interface;
- u8 ep_ctrl;
- u8 ep_in;
- u8 ep_out;
-} __attribute__ ((packed)) get_status_t;
-
-typedef struct {
- u8 AlternateSetting;
-} __attribute__ ((packed)) get_intf_t;
-
-typedef enum {
- USB_CPU, USB_DMA
-} USB_OPMODE;
-
-typedef enum {
- USB_HIGH, USB_FULL, USB_LOW
-} USB_SPEED;
-
-typedef enum {
- EP_TYPE_CONTROL, EP_TYPE_ISOCHRONOUS, EP_TYPE_BULK, EP_TYPE_INTERRUPT
-} EP_TYPE;
-
-typedef struct {
- descriptors_t desc;
- device_req_t dev_req;
-
- u32 ep0_state;
- u32 ep0_substate;
- USB_OPMODE op_mode;
- USB_SPEED speed;
- u32 ctrl_max_pktsize;
- u32 bulkin_max_pktsize;
- u32 bulkout_max_pktsize;
- u32 dn_addr;
- u32 dn_filesize;
- u32 up_addr;
- u32 up_size;
- u8 *dn_ptr;
- u8 *up_ptr;
- u32 set_config;
- u32 req_length;
-} __attribute__ ((packed)) otg_dev_t;
-
-enum DEV_REQUEST_DIRECTION {
- HOST_TO_DEVICE = 0x00,
- DEVICE_TO_HOST = 0x80
-};
-
-enum DEV_REQUEST_TYPE {
- STANDARD_TYPE = 0x00,
- CLASS_TYPE = 0x20,
- VENDOR_TYPE = 0x40,
- RESERVED_TYPE = 0x60
-};
-
-enum DEV_REQUEST_RECIPIENT {
- DEVICE_RECIPIENT = 0,
- INTERFACE_RECIPIENT = 1,
- ENDPOINT_RECIPIENT = 2,
- OTHER_RECIPIENT = 3
-};
-
-enum DESCRIPTOR_TYPE {
- DEVICE_DESCRIPTOR = 1,
- CONFIGURATION_DESCRIPTOR = 2,
- STRING_DESCRIPTOR = 3,
- INTERFACE_DESCRIPTOR = 4,
- ENDPOINT_DESCRIPTOR = 5,
- DEVICE_QUALIFIER = 6,
- OTHER_SPEED_CONFIGURATION = 7,
- INTERFACE_POWER = 8
-};
-
-enum CONFIG_ATTRIBUTES {
- CONF_ATTR_DEFAULT = 0x80,
- CONF_ATTR_REMOTE_WAKEUP = 0x20,
- CONF_ATTR_SELFPOWERED = 0x40
-};
-
-enum ENDPOINT_ATTRIBUTES {
- EP_ADDR_IN = 0x80,
- EP_ADDR_OUT = 0x00,
- EP_ATTR_CONTROL = 0x0,
- EP_ATTR_ISOCHRONOUS = 0x1,
- EP_ATTR_BULK = 0x2,
- EP_ATTR_INTERRUPT = 0x3
-};
-
-enum STANDARD_REQUEST_CODE {
- STANDARD_GET_STATUS = 0,
- STANDARD_CLEAR_FEATURE = 1,
- STANDARD_RESERVED_1 = 2,
- STANDARD_SET_FEATURE = 3,
- STANDARD_RESERVED_2 = 4,
- STANDARD_SET_ADDRESS = 5,
- STANDARD_GET_DESCRIPTOR = 6,
- STANDARD_SET_DESCRIPTOR = 7,
- STANDARD_GET_CONFIGURATION = 8,
- STANDARD_SET_CONFIGURATION = 9,
- STANDARD_GET_INTERFACE = 10,
- STANDARD_SET_INTERFACE = 11,
- STANDARD_SYNCH_FRAME = 12
-};
-
-int s5p_usbctl_init(void);
-void s5p_udc_int_hndlr(void);
-void s5p_usb_tx(char *tx_data, int tx_size);
-int s5p_usb_detect_irq(void);
-void s5p_usb_clear_irq(void);
-
-/* in usbd-otg-hs.c */
-extern unsigned int s5p_usbd_dn_addr;
-extern unsigned int s5p_usbd_dn_cnt;
-extern int s5p_got_header;
-extern int s5p_receive_done;
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2005-2010 Samsung Electronics
- * Kyungmin Park <kyungmin.park@samsung.com>
- */
-
-#include <common.h>
-#include <malloc.h>
-
-#include <linux/mtd/compat.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/onenand.h>
-
-#include <asm/io.h>
-
-#include "recovery.h"
-#include "onenand.h"
-
-#ifdef RECOVERY_DEBUG
-#define PUTS(s) serial_puts(DEBUG_MARK"onenand: "s)
-#else
-#define PUTS(s)
-#endif
-
-struct mtd_info onenand_mtd;
-struct onenand_chip onenand_chip;
-struct onenand_op onenand_ops;
-
-static __attribute__((unused)) char dev_name[] = "onenand0";
-static struct mtd_info *mtd = &onenand_mtd;
-
-static loff_t next_ofs;
-static loff_t skip_ofs;
-
-static int onenand_block_read(loff_t from, ssize_t len,
- ssize_t *retlen, u_char *buf, int oob)
-{
- struct onenand_chip *this = mtd->priv;
- int blocksize = (1 << this->erase_shift);
- loff_t ofs = from;
- struct mtd_oob_ops ops = {
- .retlen = 0,
- };
- ssize_t thislen;
- int ret;
-
- while (len > 0) {
- thislen = min_t(ssize_t, len, blocksize);
- thislen = ALIGN(thislen, mtd->writesize);
- if (ofs > mtd->size) {
- PUTS(" range overflow\n");
- break;
- }
-
- ret = mtd->block_isbad(mtd, ofs);
- if (ret) {
- PUTS("Bad blocks\n");
- ofs += blocksize;
- /* FIXME need to check how to handle the 'len' */
- len -= blocksize;
- continue;
- }
-
- if (oob) {
- ops.oobbuf = buf;
- ops.ooblen = thislen;
- } else {
- ops.datbuf = buf;
- ops.len = thislen;
- }
-
- ops.retlen = 0;
- ret = mtd->read_oob(mtd, ofs, &ops);
- if (ret) {
- PUTS("read failed\n");
- ofs += thislen;
- continue;
- }
- ofs += thislen;
- buf += thislen;
- len -= thislen;
- if (retlen != NULL)
- *retlen += ops.retlen;
- }
-
- return 0;
-}
-
-static int onenand_block_write(loff_t to, ssize_t len,
- ssize_t *retlen, u_char * buf)
-{
- struct onenand_chip *this = mtd->priv;
- int blocksize = (1 << this->erase_shift);
- struct mtd_oob_ops ops = {
- .mode = MTD_OOB_PLACE,
- .retlen = 0,
- .oobbuf = NULL,
- };
- loff_t ofs;
- ssize_t thislen;
- int ret;
-
- if (to == next_ofs) {
- next_ofs = to + len;
- to += skip_ofs;
- } else {
- next_ofs = to + len;
- skip_ofs = 0;
- }
- ofs = to;
-
- while (len > 0) {
- thislen = min_t(ssize_t, len, blocksize);
- thislen = ALIGN(thislen, mtd->writesize);
- if (ofs > mtd->size) {
- PUTS(" range overflow\n");
- break;
- }
-
- ret = mtd->block_isbad(mtd, ofs);
- if (ret) {
- PUTS("bad blocks\n");
- skip_ofs += blocksize;
- goto next;
- }
-
- ops.datbuf = (u_char *) buf;
- ops.len = thislen;
- ops.retlen = 0;
- ret = mtd->write_oob(mtd, ofs, &ops);
- if (ret) {
- PUTS("write failed\n");
- skip_ofs += thislen;
- goto next;
- }
-
- buf += thislen;
- len -= thislen;
- if (retlen != NULL)
- *retlen += ops.retlen;
-next:
- ofs += blocksize;
- }
-
- return 0;
-}
-
-static int onenand_block_erase(u32 start, u32 size, int force)
-{
- struct onenand_chip *this = mtd->priv;
- struct erase_info instr = {
- .callback = NULL,
- };
- loff_t ofs;
- int ret;
- int blocksize = 1 << this->erase_shift;
-
- for (ofs = start; ofs < (start + size); ofs += blocksize) {
- ret = mtd->block_isbad(mtd, ofs);
- if (ret && !force) {
- PUTS("skip erase bad block \n");
- continue;
- }
-
- instr.addr = ofs;
- instr.len = blocksize;
- instr.priv = force;
- instr.mtd = mtd;
- ret = mtd->erase(mtd, &instr);
- if (ret) {
- PUTS("erase failed\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static int onenand_block_lock_tight(u32 start, u32 size)
-{
- struct onenand_chip *this = mtd->priv;
- int ret;
-
- ret = this->lock_tight(mtd, start, size);
-
- return ret;
-}
-
-void onenand_set_interface(struct onenand_op *onenand)
-{
- onenand->read = onenand_block_read;
- onenand->write = onenand_block_write;
- onenand->erase = onenand_block_erase;
- onenand->lock_tight = onenand_block_lock_tight;
-
- onenand->mtd = &onenand_mtd;
- onenand->this = &onenand_chip;
-}
-
-struct onenand_op *onenand_get_interface(void)
-{
- return &onenand_ops;
-}
-
-void onenand_init(void)
-{
- memset(&onenand_mtd, 0, sizeof(struct mtd_info));
- memset(&onenand_chip, 0, sizeof(struct onenand_chip));
- memset(&onenand_ops, 0, sizeof(struct onenand_op));
-
- onenand_mtd.priv = &onenand_chip;
-
- onenand_chip.base = (void *) CONFIG_SYS_ONENAND_BASE;
- /*onenand_chip.options |= ONENAND_RUNTIME_BADBLOCK_CHECK;*/
-
- onenand_scan(&onenand_mtd, 1);
-
- onenand_set_interface(&onenand_ops);
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2005-2010 Samsung Electronics
- * Kyungmin Park <kyungmin.park@samsung.com>
- */
-
-#ifndef _ONENAND_H
-#define _ONENAND_H
-
-struct onenand_op {
- int (*read)(loff_t, ssize_t, ssize_t *, u_char *, int);
- int (*write)(loff_t, ssize_t, ssize_t *, u_char *);
- int (*erase)(u32, u32, int);
- int (*lock_tight)(u32, u32);
-
- struct mtd_info *mtd;
- struct onenand_chip *this;
-};
-
-struct onenand_op *onenand_get_interface(void);
-void onenand_init(void);
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2010 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- */
-
-#include <common.h>
-#include <malloc.h>
-#include "recovery.h"
-#include "usbd.h"
-#include "onenand.h"
-
-#ifdef RECOVERY_DEBUG
-#define PUTS(s) serial_puts(DEBUG_MARK""s)
-#else
-#define PUTS(s)
-#endif
-
-typedef int (init_fnc_t)(void);
-
-static void normal_boot(void)
-{
- uchar *buf;
- int ret;
-
- buf = (uchar *)CONFIG_SYS_BOOT_ADDR;
-
- ret = board_load_bootloader(buf);
- if (ret)
- hang();
-
-#if 0
- /* this will be applied */
- ret = board_lock_recoveryblock();
- if (ret)
- PUTS("fail: lock-tight");
-#endif
- ((init_fnc_t *)CONFIG_SYS_BOOT_ADDR)();
-}
-
-static void recovery_boot(void)
-{
- PUTS("Recovery Mode\n");
-
- board_update_init();
-
- /* usb download and write image */
- do_usbd_down();
-
- /* reboot */
- /* reset_cpu(0); */
-}
-
-void start_recovery_boot(void)
-{
- /* armboot_start is defined in the board-specific linker script */
- mem_malloc_init(_armboot_start - CONFIG_SYS_MALLOC_LEN,
- CONFIG_SYS_MALLOC_LEN);
-
- board_recovery_init();
-
- onenand_init();
-
- serial_init();
- serial_puts("\n");
-
- if (board_check_condition())
- recovery_boot();
- else
- normal_boot();
-
- /* NOTREACHED - no way out of command loop except booting */
-}
-
-void hang(void)
-{
- PUTS("### ERROR ### Please RESET the board ###\n");
- for (;;);
-}
-
-/*
- * origin at lib_arm/eabi_compat.c to support EABI
- */
-int raise(int signum)
-{
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 Samsung Electronics
- * Sanghee Kim <sh0130.kim@samsung.com>
- *
- * Common header for Recovery Block
- */
-
-#ifndef _RECOVERY_H
-#define _RECOVERY_H
-
-#define DEBUG_MARK "Recovery: "
-
-/* board/.../... */
-
-int board_check_condition(void);
-int board_load_bootloader(unsigned char *buf);
-int board_lock_recoveryblock(void);
-void board_update_init(void);
-int board_update_image(u32 *buf, u32 len);
-void board_recovery_init(void);
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2010 Samsung Electronics
- * Sanghee Kim <sh0130.kim@samsung.com>
- */
-
-#include <common.h>
-#include <serial.h>
-
-static struct serial_device *serial_current = &s5p_serial2_device;
-
-struct serial_device *__default_serial_console(void)
-{
- return &s5p_serial2_device;
-}
-
-struct serial_device *default_serial_console(void)
- __attribute__((weak, alias("__default_serial_console")));
-
-void serial_putc(const char c)
-{
- if (!serial_current) {
- struct serial_device *dev = default_serial_console();
-
- dev->putc(c);
- return;
- }
-
- serial_current->putc(c);
-}
-
-void serial_puts(const char *s)
-{
- if (!serial_current) {
- struct serial_device *dev = default_serial_console();
-
- dev->puts(s);
- return;
- }
-
- serial_current->puts(s);
-}
-
-int serial_init(void)
-{
- if (!serial_current) {
- struct serial_device *dev = default_serial_console();
-
- return dev->init();
- }
-
- return serial_current->init();
-}
+++ /dev/null
-/*
- * USB Downloader for SAMSUNG Platform
- *
- * Copyright (C) 2007-2010 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- *
- */
-
-#include <common.h>
-#include "recovery.h"
-#include "usbd.h"
-
-#ifdef RECOVERY_DEBUG
-#define PUTS(s) serial_puts(DEBUG_MARK"usb: "s)
-#else
-#define PUTS(s)
-#endif
-
-static struct usbd_ops usbd_ops;
-static unsigned long down_ram_addr;
-
-/* Parsing received data packet and Process data */
-static int process_data(struct usbd_ops *usbd)
-{
- ulong cmd = 0, arg = 0, len = 0, flag = 0;
- int recvlen = 0;
- int ret = 0;
- int img_type;
-
- /* Parse command */
- cmd = *((ulong *) usbd->rx_data + 0);
- arg = *((ulong *) usbd->rx_data + 1);
- len = *((ulong *) usbd->rx_data + 2);
- flag = *((ulong *) usbd->rx_data + 3);
-
- /* Reset tx buffer */
- *((ulong *) usbd->tx_data) = 0;
-
- switch (cmd) {
- case COMMAND_DOWNLOAD_IMAGE:
- PUTS("COMMAND_DOWNLOAD_IMAGE\n");
- usbd->recv_setup((char *)down_ram_addr, (int)len);
-
- /* response */
- usbd->send_data(usbd->tx_data, usbd->tx_len);
-
- /* Receive image */
- recvlen = usbd->recv_data();
-
- /* Retry this commad */
- if (recvlen < len) {
- PUTS("Error: wrong image size\n");
- *((ulong *) usbd->tx_data) = STATUS_RETRY;
- } else
- *((ulong *) usbd->tx_data) = STATUS_DONE;
-
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- return 1;
-
- case COMMAND_PARTITION_SYNC:
- *((ulong *) usbd->tx_data) = CONFIG_RECOVERY_BOOT_BLOCKS - 1;
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- return 1;
-
- case COMMAND_WRITE_PART_1:
- PUTS("COMMAND_WRITE_PART_BOOT\n");
- img_type = IMG_BOOT;
- break;
-
- /* Download complete -> reset */
- case COMMAND_RESET_PDA:
- PUTS("Download finished and Auto reset!\n");
- PUTS("Wait........\n");
- /* Stop USB */
- usbd->usb_stop();
-
- if (usbd->cpu_reset)
- usbd->cpu_reset();
-
- return 0;
-
- /* Error */
- case COMMAND_RESET_USB:
- PUTS("Error is occured!(maybe previous step)->\
- Turn off and restart!\n");
- /* Stop USB */
- usbd->usb_stop();
- return 0;
-
- default:
- return 1;
- }
-
- /* Erase and Write to NAND */
- switch (img_type) {
- case IMG_BOOT:
- ret = board_update_image((u32 *)down_ram_addr, len);
- if (ret) {
- *((ulong *) usbd->tx_data) = STATUS_ERROR;
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- return 0;
- }
- break;
-
- default:
- /* Retry? */
- break;
- }
-
- if (ret) {
- /* Retry this commad */
- *((ulong *) usbd->tx_data) = STATUS_RETRY;
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- return 1;
- } else
- *((ulong *) usbd->tx_data) = STATUS_DONE;
-
- /* Write image success -> Report status */
- usbd->send_data(usbd->tx_data, usbd->tx_len);
-
- return 1;
-}
-
-int do_usbd_down(void)
-{
- struct usbd_ops *usbd;
-
- PUTS("USB Downloader\n");
- /* interface setting */
- usbd = usbd_set_interface(&usbd_ops);
- down_ram_addr = usbd->ram_addr;
-
- /* init the usb controller */
- usbd->usb_init();
-
- /* receive setting */
- usbd->recv_setup(usbd->rx_data, usbd->rx_len);
-
- /* detect the download request from Host PC */
- if (usbd->recv_data())
- usbd->send_data(usbd->tx_data, usbd->tx_len);
- else
- return 0;
-
- PUTS("Receive the packet\n");
-
- /* receive the data from Host PC */
- while (1) {
- usbd->recv_setup(usbd->rx_data, usbd->rx_len);
-
- if (usbd->recv_data()) {
- if (process_data(usbd) == 0)
- return 0;
- }
- }
-
- return 0;
-}
+++ /dev/null
-/*
- * USB Downloader for SAMSUNG Platform
- *
- * Copyright (C) 2007-2009 Samsung Electronics
- * Minkyu Kang <mk7.kang@samsung.com>
- */
-
-#define msleep(a) udelay(a * 1000)
-#define WAIT_TIME 2
-
-#undef CMD_USBD_DEBUG
-#ifdef CMD_USBD_DEBUG
-#define PRINTF(fmt, args...) printf(fmt, ##args)
-#else
-#define PRINTF(fmt, args...)
-#endif
-
-/* partition info for partition sync - typically not use */
-enum {
- BOOT_PART_ID = 0,
- PARAMS_PART_ID,
- KERNEL_PART_ID,
- RAMDISK_PART_ID,
- FILESYSTEM_PART_ID,
- FILESYSTEM2_PART_ID,
- FILESYSTEM3_PART_ID,
- MODEM_PART_ID,
- MMC_PART_ID,
- NUM_PARTITION,
-};
-
-/* image type definition */
-enum {
- IMG_BOOT = 0,
- IMG_KERNEL,
- IMG_FILESYSTEM,
- IMG_MODEM,
- IMG_MMC,
-};
-
-/* Download command definition */
-#define COMMAND_DOWNLOAD_IMAGE 200
-#define COMMAND_WRITE_PART_0 201
-#define COMMAND_WRITE_PART_1 202
-#define COMMAND_WRITE_PART_2 203
-#define COMMAND_WRITE_PART_3 204
-#define COMMAND_WRITE_PART_4 205
-#define COMMAND_WRITE_PART_5 206
-#define COMMAND_WRITE_PART_6 207
-#define COMMAND_WRITE_PART_7 208
-#define COMMAND_WRITE_PART_8 209
-#define COMMAND_WRITE_PART_9 210
-#define COMMAND_WRITE_UBI_INFO 211
-#define COMMAND_PARTITION_SYNC 212
-#define COMMAND_ERASE_PARAMETER 213
-#define COMMAND_RESET_PDA 214
-#define COMMAND_RESET_USB 215
-#define COMMAND_RAM_BOOT 216
-#define COMMAND_RAMDISK_MODE 217
-#ifdef CONFIG_DOWN_PHONE
-#define COMMAND_DOWN_PHONE 220
-#define COMMAND_CHANGE_USB 221
-#endif
-#define COMMAND_CSA_CLEAR 222
-#define COMMAND_PROGRESS 230
-
-/* status definition */
-enum {
- STATUS_DONE = 0,
- STATUS_RETRY,
- STATUS_ERROR,
-};
-
-/* download mode definition */
-enum {
- MODE_NORMAL = 0,
- MODE_FORCE,
-};
-
-/*
- * USB Downloader Operations
- * All functions and valuable are mandatory
- *
- * usb_init : initialize the USB Controller and check the connection
- * usb_stop : stop and release USB
- * send_data : send the data (BULK ONLY!!)
- * recv_data : receive the data and returns received size (BULK ONLY!!)
- * recv_setup : setup download address, length and DMA setting for receive
- * tx_data : send data address
- * rx_data : receive data address
- * tx_len : size of send data
- * rx_len : size of receive data
- * ram_addr : address of will be stored data on RAM
- *
- * mmc_dev : device number of mmc
- * mmc_max : number of max blocks
- * mmc_blk : mmc block size
- * mmc_total : mmc total blocks
- */
-struct usbd_ops {
- void (*usb_init)(void);
- void (*usb_stop)(void);
- void (*send_data)(char *, int);
- int (*recv_data)(void);
- void (*recv_setup)(char *, int);
- char *tx_data;
- char *rx_data;
- ulong tx_len;
- ulong rx_len;
- ulong ram_addr;
-
- /* mmc device info */
- uint mmc_dev;
- ulong mmc_max;
- ulong mmc_blk;
- ulong mmc_total;
-
- void (*set_progress)(int);
- void (*cpu_reset)(void);
-};
-
-int do_usbd_down(void);
-/* This function is interfaced between USB Device Controller and USB Downloader
- * Must Implementation this function at USB Controller!! */
-struct usbd_ops *usbd_set_interface(struct usbd_ops *);