From c181c5bdf7028ece8b08bf747793733b291c80ae Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Wed, 13 Jan 2010 13:20:53 +0900 Subject: [PATCH] s5p6442: smdk6442: initial work Signed-off-by: Joonyoung Shim --- Makefile | 3 + board/samsung/smdk6442/Makefile | 55 + board/samsung/smdk6442/config.mk | 6 + board/samsung/smdk6442/lowlevel_init.S | 188 +++ board/samsung/smdk6442/mem_setup.S | 198 ++++ board/samsung/smdk6442/onenand.c | 85 ++ board/samsung/smdk6442/smdk6442.c | 51 + common/serial.c | 2 +- cpu/arm1176/cpu.c | 2 + cpu/arm1176/s5p64xx/Makefile | 58 + cpu/arm1176/s5p64xx/clock.c | 160 +++ cpu/arm1176/s5p64xx/cpu_info.c | 57 + cpu/arm1176/s5p64xx/gpio.c | 255 ++++ cpu/arm1176/s5p64xx/i2c-gpio.c | 101 ++ cpu/arm1176/s5p64xx/reset.S | 34 + cpu/arm1176/s5p64xx/sleep.c | 490 ++++++++ cpu/arm1176/s5p64xx/sleep.h | 67 ++ cpu/arm1176/s5p64xx/sleep_asm.S | 160 +++ cpu/arm1176/s5p64xx/timer.c | 206 ++++ cpu/arm1176/s5p64xx/usb-hs-otg.c | 1816 +++++++++++++++++++++++++++++ cpu/arm1176/s5p64xx/usb-hs-otg.h | 277 +++++ cpu/arm1176/s5p64xx/usb_downloader.c | 190 +++ cpu/arm1176/start.S | 2 + drivers/serial/Makefile | 1 + drivers/serial/serial_s5pc1xx.c | 5 + include/asm-arm/arch-s5p64xx/clk.h | 31 + include/asm-arm/arch-s5p64xx/clock.h | 83 ++ include/asm-arm/arch-s5p64xx/cpu.h | 57 + include/asm-arm/arch-s5p64xx/gpio.h | 110 ++ include/asm-arm/arch-s5p64xx/i2c.h | 43 + include/asm-arm/arch-s5p64xx/keypad.h | 34 + include/asm-arm/arch-s5p64xx/mem.h | 51 + include/asm-arm/arch-s5p64xx/mmc.h | 77 ++ include/asm-arm/arch-s5p64xx/power.h | 76 ++ include/asm-arm/arch-s5p64xx/pwm.h | 57 + include/asm-arm/arch-s5p64xx/regs-fb.h | 388 ++++++ include/asm-arm/arch-s5p64xx/sys_proto.h | 32 + include/asm-arm/arch-s5p64xx/uart.h | 46 + include/asm-arm/arch-s5p64xx/usb-hs-otg.h | 122 ++ include/configs/smdk6442.h | 319 +++++ include/serial.h | 2 +- 41 files changed, 5995 insertions(+), 2 deletions(-) create mode 100644 board/samsung/smdk6442/Makefile create mode 100644 board/samsung/smdk6442/config.mk create mode 100644 board/samsung/smdk6442/lowlevel_init.S create mode 100644 board/samsung/smdk6442/mem_setup.S create mode 100644 board/samsung/smdk6442/onenand.c create mode 100644 board/samsung/smdk6442/smdk6442.c create mode 100644 cpu/arm1176/s5p64xx/Makefile create mode 100644 cpu/arm1176/s5p64xx/clock.c create mode 100644 cpu/arm1176/s5p64xx/cpu_info.c create mode 100644 cpu/arm1176/s5p64xx/gpio.c create mode 100644 cpu/arm1176/s5p64xx/i2c-gpio.c create mode 100644 cpu/arm1176/s5p64xx/reset.S create mode 100644 cpu/arm1176/s5p64xx/sleep.c create mode 100644 cpu/arm1176/s5p64xx/sleep.h create mode 100644 cpu/arm1176/s5p64xx/sleep_asm.S create mode 100644 cpu/arm1176/s5p64xx/timer.c create mode 100644 cpu/arm1176/s5p64xx/usb-hs-otg.c create mode 100644 cpu/arm1176/s5p64xx/usb-hs-otg.h create mode 100644 cpu/arm1176/s5p64xx/usb_downloader.c create mode 100644 include/asm-arm/arch-s5p64xx/clk.h create mode 100644 include/asm-arm/arch-s5p64xx/clock.h create mode 100644 include/asm-arm/arch-s5p64xx/cpu.h create mode 100644 include/asm-arm/arch-s5p64xx/gpio.h create mode 100644 include/asm-arm/arch-s5p64xx/i2c.h create mode 100644 include/asm-arm/arch-s5p64xx/keypad.h create mode 100644 include/asm-arm/arch-s5p64xx/mem.h create mode 100644 include/asm-arm/arch-s5p64xx/mmc.h create mode 100644 include/asm-arm/arch-s5p64xx/power.h create mode 100644 include/asm-arm/arch-s5p64xx/pwm.h create mode 100644 include/asm-arm/arch-s5p64xx/regs-fb.h create mode 100644 include/asm-arm/arch-s5p64xx/sys_proto.h create mode 100644 include/asm-arm/arch-s5p64xx/uart.h create mode 100644 include/asm-arm/arch-s5p64xx/usb-hs-otg.h create mode 100644 include/configs/smdk6442.h diff --git a/Makefile b/Makefile index 4a00934..5c0b984 100644 --- a/Makefile +++ b/Makefile @@ -3295,6 +3295,9 @@ smdk6400_config : unconfig fi @echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk +smdk6442_config: unconfig + @$(MKCONFIG) $(@:_config=) arm arm1176 smdk6442 samsung s5p64xx + #======================================================================== # i386 #======================================================================== diff --git a/board/samsung/smdk6442/Makefile b/board/samsung/smdk6442/Makefile new file mode 100644 index 0000000..9700ffb --- /dev/null +++ b/board/samsung/smdk6442/Makefile @@ -0,0 +1,55 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Guennadi Liakhovetki, DENX Software Engineering, +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS-y := smdk6442.o +COBJS-$(CONFIG_SAMSUNG_ONENAND) += onenand.o +SOBJS := lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(SOBJS) $(OBJS) + $(AR) $(ARFLAGS) $@ $(SOBJS) $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/samsung/smdk6442/config.mk b/board/samsung/smdk6442/config.mk new file mode 100644 index 0000000..453e034 --- /dev/null +++ b/board/samsung/smdk6442/config.mk @@ -0,0 +1,6 @@ +# +# Copyright (C) 2010 Samsung Elecgtronics +# Minkyu Kang +# + +TEXT_BASE = 0x24800000 diff --git a/board/samsung/smdk6442/lowlevel_init.S b/board/samsung/smdk6442/lowlevel_init.S new file mode 100644 index 0000000..2167795 --- /dev/null +++ b/board/samsung/smdk6442/lowlevel_init.S @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Kyungmin Park + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* + * Register usages: + * + * r5 has zero always + */ + +_TEXT_BASE: + .word TEXT_BASE + + .globl lowlevel_init +lowlevel_init: + mov r9, lr + + /* r5 has always zero */ + mov r5, #0 + + ldr r8, =S5P6442_GPIO_BASE + + /* IO retension release */ + ldr r0, =S5P6442_OTHERS @0xE010E000 + ldr r1, [r0] + ldreq r2, =(1 << 31) @IO_RET_REL + ldrne r2, =((1 << 31) | (1 << 29) | (1 << 28)) @ GPIO, UART_IO + orr r1, r1, r2 + str r1, [r0] + +#ifndef CONFIG_ONENAND_IPL + /* Disable Watchdog */ + ldr r0, =S5P6442_WATCHDOG_BASE @0xEA200000 + orr r0, r0, #0x0 + str r5, [r0] + + /* setting SRAM */ + ldr r0, =S5P6442_SROMC_BASE + ldr r1, =0x9 + str r1, [r0] +#endif + + /* S5P6442 has 3 groups of interrupt sources */ + ldr r0, =S5P6442_VIC0_BASE @0xE4000000 + ldr r1, =S5P6442_VIC1_BASE @0xE4000000 + ldr r2, =S5P6442_VIC2_BASE @0xE4000000 + + /* Disable all interrupts (VIC0, VIC1 and VIC2) */ + mvn r3, #0x0 + str r3, [r0, #0x14] @INTENCLEAR + str r3, [r1, #0x14] @INTENCLEAR + str r3, [r2, #0x14] @INTENCLEAR + +#ifndef CONFIG_ONENAND_IPL + /* Set all interrupts as IRQ */ + str r5, [r0, #0xc] @INTSELECT + str r5, [r1, #0xc] @INTSELECT + str r5, [r2, #0xc] @INTSELECT + + /* Pending Interrupt Clear */ + str r5, [r0, #0xf00] @INTADDRESS + str r5, [r1, #0xf00] @INTADDRESS + str r5, [r2, #0xf00] @INTADDRESS +#endif + +#ifndef CONFIG_ONENAND_IPL + /* for UART */ + bl uart_asm_init +#endif + +#ifdef CONFIG_ONENAND_IPL + /* init system clock */ + bl system_clock_init + + bl mem_ctrl_asm_init + + /* Wakeup support. Don't know if it's going to be used, untested. */ + ldr r0, =S5P6442_RST_STAT + ldr r1, [r0] + bic r1, r1, #0xfffffff7 + cmp r1, #0x8 + beq wakeup_reset +#endif + +1: + mov lr, r9 + mov pc, lr + +#ifdef CONFIG_ONENAND_IPL +wakeup_reset: + + /* Clear wakeup status register */ + ldr r0, =S5P6442_WAKEUP_STAT + ldr r1, [r0] + str r1, [r0] + + /* Load return address and jump to kernel */ + ldr r0, =S5P6442_INFORM0 + + /* r1 = physical address of s5p6442_cpu_resume function */ + ldr r1, [r0] + + /* Jump to kernel (sleep.S) */ + mov pc, r1 + nop + nop +#endif + +/* + * system_clock_init: Initialize core clock and bus clock. + * void system_clock_init(void) + */ +system_clock_init: + ldr r8, =S5P64XX_CLOCK_BASE @ 0xE0100000 + + /* Set Clock divider */ + ldr r1, =0x10100000 + str r1, [r8, #0x300] + + /* Set Lock Time */ + ldr r1, =0xe10 @ Locktime : 0xe10 = 3600 + str r1, [r8, #0x000] @ APLL_LOCK + str r1, [r8, #0x008] @ MPLL_LOCK + str r1, [r8, #0x010] @ EPLL_LOCK + str r1, [r8, #0x020] @ VPLL_LOCK + + /* APLL_CON */ + ldr r1, =0x82150c01 @ SDIV 1, PDIV 0xc, MDIV 0x215 + str r1, [r8, #0x100] + /* MPLL_CON */ + ldr r1, =0x810a0303 @ SDIV 3, PDIV 3, MDIV 0x10a + str r1, [r8, #0x108] + /* EPLL_CON */ + ldr r1, =0x80600303 @ SDIV 3, PDIV 3, MDIV 0x60 + str r1, [r8, #0x110] + /* VPLL_CON */ + ldr r1, =0x806c0303 @ SDIV 3, PDIV 3, MDIV 0x6c + str r1, [r8, #0x120] + + /* Set Source Clock */ + ldr r1, =0x1111 @ A, M, E, VPLL Muxing + str r1, [r8, #0x200] @ CLK_SRC0 + + /* wait at least 200us to stablize all clock */ + mov r2, #0x10000 +1: subs r2, r2, #1 + bne 1b + + mov pc, lr + +#ifndef CONFIG_ONENAND_IPL +/* + * uart_asm_init: Initialize UART's pins + */ +uart_asm_init: + mov r0, r8 + ldr r1, =0x22222222 + str r1, [r0, #0x0] @ GPA0_CON + ldr r1, =0x00022222 + str r1, [r0, #0x20] @ GPA1_CON + + mov pc, lr +#endif diff --git a/board/samsung/smdk6442/mem_setup.S b/board/samsung/smdk6442/mem_setup.S new file mode 100644 index 0000000..741d894 --- /dev/null +++ b/board/samsung/smdk6442/mem_setup.S @@ -0,0 +1,198 @@ +/* + * Originates from Samsung's u-boot 1.1.6 port to S5PC1xx + * + * Copyright (C) 2009 Samsung Electrnoics + * Minkyu Kang + * Kyungmin Park + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + + .globl mem_ctrl_asm_init +mem_ctrl_asm_init: + ldr r6, =S5P5442_DMC_BASE @ 0xE6000000 + + /* DLL parameter setting */ + ldr r1, =0x00141408 + str r1, [r6, #0x018] @ PHYCONTROL0 + ldr r1, =0x00008044 + str r1, [r6, #0x01C] @ PHYCONTROL1 + ldr r1, =0x0 + str r1, [r6, #0x020] @ PHYCONTROL2 + + /* DLL on */ + ldr r1, =0x0014140a + str r1, [r6, #0x018] @ PHYCONTROL0 + + /* DLL start */ + ldr r1, =0x0014140b + str r1, [r6, #0x018] @ PHYCONTROL0 + + /* Force value locking for DLL off */ + str r1, [r6, #0x018] @ PHYCONTROL0 + + /* DLL off */ + ldr r1, =0x00141409 + str r1, [r6, #0x018] @ PHYCONTROL0 + + /* auto refresh off */ + ldr r1, =0x0f0010d0 + str r1, [r6, #0x000] @ CONCONTROL + + /* + * Burst Length 4, 2 chips, 32-bit, LPDDR + * OFF: dynamic self refresh, force precharge, dynamic power down off + */ + ldr r1, =0x00202100 + str r1, [r6, #0x004] @ MEMCONTROL + + /* + * Note: + * If Bank0 has OneDRAM we place it at 0x2800'0000 + * So finally Bank1 should address start at at 0x2000'0000 + */ + mov r4, #0x0 + +#if 0 +swap_memory: + /* + * Bank0 + * 0x30 -> 0x30000000 + * 0xf8 -> 0x37FFFFFF + * [15:12] 0: Linear + * [11:8 ] 2: 9 bits + * [ 7:4 ] 2: 14 bits + * [ 3:0 ] 2: 4 banks + */ + ldr r1, =0x30f80222 + /* if r4 is 1, swap the bank */ + cmp r4, #0x1 + orreq r1, r1, #0x08000000 + str r1, [r6, #0x008] @ MEMCONFIG0 + + /* + * Bank1 + * 0x38 -> 0x38000000 + * 0xf8 -> 0x3fFFFFFF + * [15:12] 0: Linear + * [11:8 ] 2: 9 bits + * [ 7:4 ] 2: 14 bits + * [ 3:0 ] 2: 4 banks + */ + ldr r1, =0x38f80222 + /* if r4 is 1, swap the bank */ + cmp r4, #0x1 + biceq r1, r1, #0x08000000 + str r1, [r6, #0x00c] @ MEMCONFIG1 + + ldr r1, =0x20000000 + str r1, [r6, #0x014] @ PRECHCONFIG +#endif + + /* + * FIXME: Please verify these values + * 7.8us * 166MHz %LE %LONG1294(0x50E) + * 7.8us * 133MHz %LE %LONG1038(0x40E), + * 7.8us * 100MHz %LE %LONG780(0x30C), + * 7.8us * 20MHz %LE %LONG156(0x9C), + * 7.8us * 10MHz %LE %LONG78(0x4E) + */ + ldr r1, =0x0000040e + str r1, [r6, #0x030] @ TIMINGAREF + + /* 166 MHz */ + ldr r1, =0x0c233286 + str r1, [r6, #0x034] @ TIMINGROW + + /* twtr=3 twr=2 trtp=3 cl=3 wl=3 rl=3 */ + ldr r1, =0x12130005 + str r1, [r6, #0x038] @ TIMINGDATA + + /* tfaw=4 sxsr=0x14 txp=0x14 tcke=3 tmrd=3 */ + ldr r1, =0x0e120222 + str r1, [r6, #0x03C] @ TIMINGPOWER + + /* chip0 Deselect */ + ldr r1, =0x07000000 + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip0 PALL */ + ldr r1, =0x01000000 + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip0 REFA */ + ldr r1, =0x05000000 + str r1, [r6, #0x010] @ DIRECTCMD + /* chip0 REFA */ + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip0 MRS, CL%LE %LONG3, BL%LE %LONG4 */ + ldr r1, =0x00000032 + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip1 Deselect */ + ldr r1, =0x07100000 + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip1 PALL */ + ldr r1, =0x01100000 + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip1 REFA */ + ldr r1, =0x05100000 + str r1, [r6, #0x010] @ DIRECTCMD + /* chip1 REFA */ + str r1, [r6, #0x010] @ DIRECTCMD + + /* chip1 MRS, CL%LE %LONG3, BL%LE %LONG4 */ + ldr r1, =0x00100032 + str r1, [r6, #0x010] @ DIRECTCMD + + /* auto refresh on */ + ldr r1, =0x0f0010f0 + str r1, [r6, #0x000] @ CONCONTROL + + /* PwrdnConfig */ + ldr r1, =0x00100002 + str r1, [r6, #0x028] @ PWRDNCONFIG + + /* BL%LE %LONG */ + ldr r1, =0x00212100 + str r1, [r6, #0x004] @ MEMCONTROL + +#if 0 + /* Try to test memory area */ + cmp r4, #0x1 + beq 1f + + mov r4, #0x1 + ldr r1, =0x37ffff00 + str r4, [r1] + str r4, [r1, #0x4] @ dummy write + ldr r0, [r1] + cmp r0, r4 + bne swap_memory +#endif + +1: + mov pc, lr + + .ltorg diff --git a/board/samsung/smdk6442/onenand.c b/board/samsung/smdk6442/onenand.c new file mode 100644 index 0000000..cfa0c46 --- /dev/null +++ b/board/samsung/smdk6442/onenand.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2009 Samsung Electronics + * Kyungmin Park + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +void onenand_board_init(struct mtd_info *mtd) +{ +#if 0 + struct onenand_chip *this = mtd->priv; + struct s5pc100_clock *clk = (struct s5pc100_clock *)S5PC1XX_CLOCK_BASE; + struct samsung_onenand *onenand; + int value; + + this->base = (void *)S5PC100_ONENAND_BASE; + onenand = (struct samsung_onenand *)this->base; + + /* D0 Domain memory clock gating */ + value = readl(&clk->gate_d01); + value &= ~(1 << 2); /* CLK_ONENANDC */ + value |= (1 << 2); + writel(value, &clk->gate_d01); + + value = readl(&clk->src0); + value &= ~(1 << 24); /* MUX_1nand: 0 from HCLKD0 */ + value &= ~(1 << 20); /* MUX_HREF: 0 from FIN_27M */ + writel(value, &clk->src0); + + value = readl(&clk->div1); + value &= ~(3 << 16); /* PCLKD1_RATIO */ + value |= (1 << 16); + writel(value, &clk->div1); + + writel(ONENAND_MEM_RESET_COLD, &onenand->mem_reset); + + while (!(readl(&onenand->int_err_stat) & RST_CMP)) + continue; + + writel(RST_CMP, &onenand->int_err_ack); + + /* + * Access_Clock [2:0] + * 166 MHz, 134 Mhz : 3 + * 100 Mhz, 60 Mhz : 2 + */ + writel(0x3, &onenand->acc_clock); + + writel(INT_ERR_ALL, &onenand->int_err_mask); + writel(1 << 0, &onenand->int_pin_en); /* Enable */ + + value = readl(&onenand->int_err_mask); + value &= ~RDY_ACT; + writel(value, &onenand->int_err_mask); + + s3c_onenand_init(mtd); +#endif +} diff --git a/board/samsung/smdk6442/smdk6442.c b/board/samsung/smdk6442/smdk6442.c new file mode 100644 index 0000000..e1b319d --- /dev/null +++ b/board/samsung/smdk6442/smdk6442.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2009 Samsung Electronics + * Minkyu Kang + * Kyungmin Park + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + gd->bd->bi_arch_number = MACH_TYPE_SMDKC100; + gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + + return 0; +} + +int dram_init(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1, + PHYS_SDRAM_1_SIZE); + + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + printf("Board:\t6442\n"); + return 0; +} +#endif diff --git a/common/serial.c b/common/serial.c index 5f9ffd7..ab8e0e3 100644 --- a/common/serial.c +++ b/common/serial.c @@ -69,7 +69,7 @@ struct serial_device *__default_serial_console (void) #else #error "CONFIG_SERIAL? missing." #endif -#elif defined(CONFIG_S5PC1XX) +#elif defined(CONFIG_S5PC1XX) || defined(CONFIG_S5P64XX) #if defined(CONFIG_SERIAL0) return &s5pc1xx_serial0_device; #elif defined(CONFIG_SERIAL1) diff --git a/cpu/arm1176/cpu.c b/cpu/arm1176/cpu.c index 2c0014f..befa0cd 100644 --- a/cpu/arm1176/cpu.c +++ b/cpu/arm1176/cpu.c @@ -33,7 +33,9 @@ #include #include +#ifdef CONFIG_S3C64XX #include +#endif #include static void cache_flush (void); diff --git a/cpu/arm1176/s5p64xx/Makefile b/cpu/arm1176/s5p64xx/Makefile new file mode 100644 index 0000000..0626af2 --- /dev/null +++ b/cpu/arm1176/s5p64xx/Makefile @@ -0,0 +1,58 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2008 +# Guennadi Liakhovetki, DENX Software Engineering, +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +SOBJS = reset.o +#SOBJS += cache.o + +COBJS-y += clock.o +COBJS-y += cpu_info.o +COBJS-y += gpio.o +COBJS-y += timer.o +#COBJS-$(CONFIG_CMD_SLEEP) += sleep.o +#COBJS-$(CONFIG_CMD_SLEEP) += sleep_asm.o +COBJS-$(CONFIG_SOFT_I2C) += i2c-gpio.o +#COBJS-$(CONFIG_CMD_USBDOWN) += usb-hs-otg.o usb_downloader.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y) $(SOBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm1176/s5p64xx/clock.c b/cpu/arm1176/s5p64xx/clock.c new file mode 100644 index 0000000..c289b1e --- /dev/null +++ b/cpu/arm1176/s5p64xx/clock.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +#ifndef CONFIG_SYS_CLK_FREQ_6442 +#define CONFIG_SYS_CLK_FREQ_6442 12000000 +#endif + +unsigned long (*get_pclk)(void); +unsigned long (*get_arm_clk)(void); +unsigned long (*get_pll_clk)(int); + +/* s5p6442: return pll clock frequency */ +static unsigned long s5p6442_get_pll_clk(int pllreg) +{ + struct s5p6442_clock *clk = (struct s5p6442_clock *)S5P64XX_CLOCK_BASE; + unsigned long r, m, p, s, mask, fout; + unsigned int freq; + + switch (pllreg) { + case APLL: + r = readl(&clk->apll_con); + break; + case MPLL: + r = readl(&clk->mpll_con); + break; + case EPLL: + r = readl(&clk->epll_con); + break; + case VPLL: + r = readl(&clk->vpll_con); + break; + default: + printf("Unsupported PLL (%d)\n", pllreg); + return 0; + } + + /* + * APLL_CON: MIDV [25:16] + * MPLL_CON: MIDV [25:16] + * EPLL_CON: MIDV [24:16] + * VPLL_CON: MIDV [24:16] + */ + if (pllreg == APLL || pllreg == MPLL) + mask = 0x3ff; + else + mask = 0x1ff; + + m = (r >> 16) & mask; + + /* PDIV [13:8] */ + p = (r >> 8) & 0x3f; + /* SDIV [2:0] */ + s = r & 0x7; + + freq = CONFIG_SYS_CLK_FREQ_6442; + if (pllreg == APLL) { + if (s < 1) + s = 1; + /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */ + fout = m * (freq / (p * (1 << (s - 1)))); + } else + /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */ + fout = m * (freq / (p * (1 << s))); + + return fout; +} + +/* s5p6442: return ARM clock frequency */ +static unsigned long s5p6442_get_arm_clk(void) +{ + struct s5p6442_clock *clk = (struct s5p6442_clock *)S5P64XX_CLOCK_BASE; + unsigned long div; + unsigned long dout_apll, armclk; + unsigned int apll_ratio; + + div = readl(&clk->div0); + + /* APLL_RATIO: [2:0] */ + apll_ratio = div & 0x7; + + dout_apll = get_pll_clk(APLL) / (apll_ratio + 1); + armclk = dout_apll; + + return armclk; +} + +/* s5p6442: return D0CLK frequency */ +static unsigned long get_d0clk(void) +{ + struct s5p6442_clock *clk = (struct s5p6442_clock *)S5P64XX_CLOCK_BASE; + unsigned long d0clk; + uint div, d0_bus_ratio; + + div = readl(&clk->div0); + /* D0CLK_RATIO: [19:16] */ + d0_bus_ratio = (div >> 16) & 0xf; + + d0clk = get_arm_clk() / (d0_bus_ratio + 1); + + return d0clk; +} + +/* s5p6442: return P1CLK frequency */ +static unsigned long get_p1clk(void) +{ + struct s5p6442_clock *clk = (struct s5p6442_clock *)S5P64XX_CLOCK_BASE; + unsigned long d1_bus, p1clk; + uint div, d1_bus_ratio, p1clk_ratio; + + div = readl(&clk->div0); + /* D1CLK_RATIO: [27:24] */ + d1_bus_ratio = (div >> 24) & 0xf; + /* P1CLK_RATIO: [30:28] */ + p1clk_ratio = (div >> 28) & 0x7; + + /* ASYNC Mode */ + d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1); + p1clk = d1_bus / (p1clk_ratio + 1); + + return p1clk; +} + +/* s5p6442: return peripheral clock frequency */ +static unsigned long s5p6442_get_pclk(void) +{ + return get_p1clk(); +} + +void s5p64xx_clock_init(void) +{ + if (cpu_is_s5p6442()) { + get_pll_clk = s5p6442_get_pll_clk; + get_arm_clk = s5p6442_get_arm_clk; + get_pclk = s5p6442_get_pclk; + } +} diff --git a/cpu/arm1176/s5p64xx/cpu_info.c b/cpu/arm1176/s5p64xx/cpu_info.c new file mode 100644 index 0000000..f9d0fcc --- /dev/null +++ b/cpu/arm1176/s5p64xx/cpu_info.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include +#include +#include + +/* Default is s5p6442 */ +unsigned int s5p64xx_cpu_id = 0x6442; + +#ifdef CONFIG_ARCH_CPU_INIT +int arch_cpu_init(void) +{ + s5p64xx_cpu_id = readl(S5P64XX_PRO_ID); + s5p64xx_cpu_id = (s5p64xx_cpu_id & 0x0FFFF000) >> 12; + + s5p64xx_clock_init(); + + return 0; +} +#endif + +u32 get_device_type(void) +{ + return s5p64xx_cpu_id; +} + +#ifdef CONFIG_DISPLAY_CPUINFO +int print_cpuinfo(void) +{ + char buf[32]; + + printf("CPU:\tS5P%X@%sMHz\n", + s5p64xx_cpu_id, strmhz(buf, get_arm_clk())); + + return 0; +} +#endif diff --git a/cpu/arm1176/s5p64xx/gpio.c b/cpu/arm1176/s5p64xx/gpio.c new file mode 100644 index 0000000..b2b034e --- /dev/null +++ b/cpu/arm1176/s5p64xx/gpio.c @@ -0,0 +1,255 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +#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)) +#define DRV_SET(x, m) ((m) << (x)) +#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); +} + +void gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int enable) +{ + unsigned int value; + + gpio_cfg_pin(bank, gpio, GPIO_OUTPUT); + + value = readl(&bank->dat); + value &= ~DAT_MASK(gpio); + if (enable) + value |= DAT_SET(gpio); + writel(value, &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 enable) +{ + unsigned int value; + + value = readl(&bank->dat); + value &= ~DAT_MASK(gpio); + if (enable) + value |= DAT_SET(gpio); + writel(value, &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); +} + +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: + break; + } + + writel(value, &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: + break; + } + + writel(value, &bank->drv); +} + +#ifdef CONFIG_CMD_GPIO +static char *gpio_name[] = { + "GPA0", "GPA1", "GPB", "GPC0", "GPC1", "GPD0", "GPD1", "GPE0", "GPE1", + "GPF0", "GPF1", "GPF2", "GPF3", "GPG0", "GPG1", "GPG2", "GPJ0", "GPJ1", + "GPJ2", "GPJ3", "GPJ4", "MP01", "MP02", "MP03", "MP04", "MP05", "MP06", + "MP07", "MP10", "MP11", "MP12", "MP13", "MP14", "MP15", "MP16", "MP17", + "MP18", +}; + +static char *gpio_name1[] = { + "GPH0", "GPH1", "GPH2", "GPH3", +}; + +static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + struct s5pc110_gpio *gpio = + (struct s5pc110_gpio *)S5PC110_GPIO_BASE; + int i = 0; + int j; + + if (argc == 1) { + cmd_usage(cmdtp); + return 1; + } + + if (strcmp(argv[1], "show") == 0) { + while (1) { + printf("%s\n", gpio_name[i]); + + for (j = 0; j < 8; j++) { + printf("[%d] %s", j, + gpio_get_value(&gpio->gpio_a0 + i, j) ? + "hi" : "lo"); + if ((j + 1) & (8 - 1)) + printf("\t"); + else + printf("\n"); + } + printf("\n"); + + i++; + if ((&gpio->gpio_a0 + i) == &gpio->res1) + break; + } + + for (i = 0; i < 4; i++) { + printf("%s\n", gpio_name1[i]); + + for (j = 0; j < 8; j++) { + printf("[%d] %s", j, + gpio_get_value(&gpio->gpio_h0 + i, j) ? + "hi" : "lo"); + if ((j + 1) & (8 - 1)) + printf("\t"); + else + printf("\n"); + } + printf("\n"); + } + + return 1; + } else if (strcmp(argv[1], "set") == 0) { + int num, value; + + if (argc != 5) { + cmd_usage(cmdtp); + return 1; + } + + if (strcmp(argv[2], "GPH0") == 0) { + i = 48 + 48 + 0; + } else if (strcmp(argv[2], "GPH1") == 0) { + i = 48 + 48 + 1; + } else if (strcmp(argv[2], "GPH2") == 0) { + i = 48 + 48 + 2; + } else if (strcmp(argv[2], "GPH3") == 0) { + i = 48 + 48 + 3; + } else { + while (1) { + if (strcmp(argv[2], gpio_name[i]) == 0) + break; + i++; + + if ((&gpio->gpio_a0 + i) == &gpio->res1) { + printf("Can't found %s bank\n", argv[2]); + return 1; + } + } + } + num = simple_strtoul(argv[3], NULL, 10); + value = simple_strtoul(argv[4], NULL, 10); + + gpio_set_value(&gpio->gpio_a0 + i, num, value); + + printf("%s[%d] set to %s\n", argv[2], num, + value ? "hi" : "lo"); + + return 1; + } + + cmd_usage(cmdtp); + return 1; +} + +U_BOOT_CMD( + gpio, CONFIG_SYS_MAXARGS, 1, do_gpio, + "GPIO Control", + "show - show all banks\n" + "gpio set bank num value - set gpio value\n" +); +#endif diff --git a/cpu/arm1176/s5p64xx/i2c-gpio.c b/cpu/arm1176/s5p64xx/i2c-gpio.c new file mode 100644 index 0000000..cbe7155 --- /dev/null +++ b/cpu/arm1176/s5p64xx/i2c-gpio.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +static struct i2c_gpio_bus *i2c_gpio; + +void i2c_gpio_init(struct i2c_gpio_bus *bus, int len, int index) +{ + int i; + struct s5p_gpio_bank *bank; + + i2c_gpio = bus; + + /* init all i2c gpio buses */ + for (i = 0; i < len; i++) { + bank = (struct s5p_gpio_bank *)i2c_gpio[i].bus->gpio_base; + + /* SDA */ + gpio_direction_output(bank, + i2c_gpio[i].bus->sda_pin, 1); + + /* SCL */ + gpio_direction_output(bank, + i2c_gpio[i].bus->scl_pin, 1); + } + + /* set default bus */ + i2c_set_bus_num(index); +} + +void i2c_gpio_set(int line, int value) +{ + struct s5p_gpio_bank *bank; + unsigned int bus_index; + + bus_index = i2c_get_bus_num(); + + bank = (struct s5p_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base; + + if (line) + line = i2c_gpio[bus_index].bus->sda_pin; + else + line = i2c_gpio[bus_index].bus->scl_pin; + + gpio_set_value(bank, line, value); +} + +int i2c_gpio_get(void) +{ + struct s5p_gpio_bank *bank; + unsigned int bus_index; + + bus_index = i2c_get_bus_num(); + + bank = (struct s5p_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base; + + return gpio_get_value(bank, i2c_gpio[bus_index].bus->sda_pin); +} + +void i2c_gpio_dir(int dir) +{ + struct s5p_gpio_bank *bank; + unsigned int bus_index; + + bus_index = i2c_get_bus_num(); + + bank = (struct s5p_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base; + + if (dir) { + gpio_direction_output(bank, + i2c_gpio[bus_index].bus->sda_pin, 0); + } else { + gpio_direction_input(bank, + i2c_gpio[bus_index].bus->sda_pin); + } +} diff --git a/cpu/arm1176/s5p64xx/reset.S b/cpu/arm1176/s5p64xx/reset.S new file mode 100644 index 0000000..002286f --- /dev/null +++ b/cpu/arm1176/s5p64xx/reset.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009 Samsung Electronics. + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#define S5P6442_SWRESET 0xE0102000 + +.globl reset_cpu +reset_cpu: + ldr r1, =S5P6442_SWRESET + mov r2, #1 + str r2, [r1] +_loop_forever: + b _loop_forever diff --git a/cpu/arm1176/s5p64xx/sleep.c b/cpu/arm1176/s5p64xx/sleep.c new file mode 100644 index 0000000..47ec48b --- /dev/null +++ b/cpu/arm1176/s5p64xx/sleep.c @@ -0,0 +1,490 @@ +/* + * Sleep command for S5PC110 + * + * Copyright (C) 2005-2008 Samsung Electronics + * Kyungmin Park + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sleep.h" + +struct stack { + u32 irq[3]; + u32 abt[3]; + u32 und[3]; +} ____cacheline_aligned; + +static struct stack stacks[1]; + +enum { + SLEEP_WFI, + SLEEP_REGISTER, +}; + +static void __board_sleep_init(void) { } + +void board_sleep_init(void) + __attribute__((weak, alias("__board_sleep_init"))); + +struct regs_to_save { + unsigned int start_address; + unsigned int size; +}; + +static struct regs_to_save core_save[] = { + { .start_address = 0xE0100200, .size = 7 }, + { .start_address = 0xE0100280, .size = 2 }, + { .start_address = 0xE0100300, .size = 8 }, + { .start_address = 0xE0100460, .size = 5 }, + { .start_address = 0xE0100480, .size = 3 }, + { .start_address = 0xE0100500, .size = 1 }, + { .start_address = 0xE0107008, .size = 1 }, + { .start_address = 0xE0103000, .size = 3 }, /* DCGIDC_MAP* */ + { .start_address = 0xE0103020, .size = 2 }, /* DCGPREF_MAP* */ + { .start_address = 0xE0103040, .size = 1 }, /* DVCIDX_MAP */ + { .start_address = 0xE0103060, .size = 2 }, /* FREQ_CPU/DPM */ + { .start_address = 0xE0103080, .size = 1 }, /* DVSEMCLK_EN */ + { .start_address = 0xE0103084, .size = 1 }, /* MAXPERF */ +}; + +static unsigned int buf_core_save[7 + 2 + 8 + 5 + 3 + 1 + 1 + + 3 + 2 + 1 + 2 + 1 + 1]; + +static struct regs_to_save gpio_save[] = { + { .start_address = 0xE0200000, .size = 6 }, + { .start_address = 0xE0200020, .size = 6 }, + { .start_address = 0xE0200040, .size = 6 }, + { .start_address = 0xE0200060, .size = 6 }, + { .start_address = 0xE0200080, .size = 6 }, + { .start_address = 0xE02000A0, .size = 6 }, + { .start_address = 0xE02000C0, .size = 6 }, + { .start_address = 0xE02000E0, .size = 6 }, + { .start_address = 0xE0200100, .size = 6 }, + { .start_address = 0xE0200120, .size = 6 }, + { .start_address = 0xE0200140, .size = 6 }, + { .start_address = 0xE0200160, .size = 6 }, + { .start_address = 0xE0200180, .size = 6 }, + { .start_address = 0xE02001A0, .size = 6 }, + { .start_address = 0xE02001C0, .size = 6 }, + { .start_address = 0xE02001E0, .size = 6 }, + { .start_address = 0xE0200200, .size = 6 }, + { .start_address = 0xE0200220, .size = 6 }, + { .start_address = 0xE0200240, .size = 6 }, + { .start_address = 0xE0200260, .size = 6 }, + { .start_address = 0xE0200280, .size = 6 }, + { .start_address = 0xE02002A0, .size = 6 }, + { .start_address = 0xE02002C0, .size = 6 }, + { .start_address = 0xE02002E0, .size = 6 }, + { .start_address = 0xE0200300, .size = 6 }, + { .start_address = 0xE0200320, .size = 6 }, + { .start_address = 0xE0200340, .size = 6 }, + { .start_address = 0xE0200360, .size = 6 }, + { .start_address = 0xE0200380, .size = 6 }, + { .start_address = 0xE02003A0, .size = 6 }, + { .start_address = 0xE02003C0, .size = 6 }, + { .start_address = 0xE02003E0, .size = 6 }, + { .start_address = 0xE0200400, .size = 6 }, + { .start_address = 0xE0200420, .size = 6 }, + { .start_address = 0xE0200440, .size = 6 }, + { .start_address = 0xE0200460, .size = 6 }, + { .start_address = 0xE0200480, .size = 6 }, + { .start_address = 0xE02004A0, .size = 6 }, + { .start_address = 0xE02004C0, .size = 6 }, + { .start_address = 0xE02004E0, .size = 6 }, + { .start_address = 0xE0200500, .size = 6 }, + { .start_address = 0xE0200520, .size = 6 }, + { .start_address = 0xE0200540, .size = 6 }, + { .start_address = 0xE0200560, .size = 6 }, + { .start_address = 0xE0200580, .size = 6 }, + { .start_address = 0xE02005A0, .size = 6 }, + { .start_address = 0xE02005C0, .size = 6 }, + { .start_address = 0xE02005E0, .size = 6 }, + { .start_address = 0xE0200608, .size = 2 }, + { .start_address = 0xE0200628, .size = 2 }, + { .start_address = 0xE0200648, .size = 2 }, + { .start_address = 0xE0200700, .size = 22 }, + { .start_address = 0xE0200900, .size = 22 }, + { .start_address = 0xE0200A00, .size = 22 }, +}; + +static unsigned int buf_gpio_save[6 * 8 * 6 + 2 * 3 + 22 * 3]; + +static struct regs_to_save irq_save[] = { + { .start_address = 0xF200000C, .size = 2 }, + { .start_address = 0xF2000018, .size = 1 }, + { .start_address = 0xF210000C, .size = 2 }, + { .start_address = 0xF2100018, .size = 1 }, + { .start_address = 0xF220000C, .size = 2 }, + { .start_address = 0xF2200018, .size = 1 }, + { .start_address = 0xF230000C, .size = 2 }, + { .start_address = 0xF2300018, .size = 1 }, +}; + +static unsigned int buf_irq_save[(2 + 1) * 4]; + +static struct regs_to_save sromc_save[] = { + { .start_address = 0xE8000000, .size = 7 }, +}; + +static unsigned int buf_sromc_save[7]; + +static struct regs_to_save uart_save[] = { + { .start_address = 0xE2900000, .size = 4 }, + { .start_address = 0xE2900028, .size = 2 }, + { .start_address = 0xE2900038, .size = 1 }, + { .start_address = 0xE2900400, .size = 4 }, + { .start_address = 0xE2900428, .size = 2 }, + { .start_address = 0xE2900438, .size = 1 }, + { .start_address = 0xE2900800, .size = 4 }, + { .start_address = 0xE2900828, .size = 2 }, + { .start_address = 0xE2900838, .size = 1 }, + { .start_address = 0xE2900C00, .size = 4 }, + { .start_address = 0xE2900C28, .size = 2 }, + { .start_address = 0xE2900C38, .size = 1 }, +}; +static unsigned int buf_uart_save[(4 + 2 + 1) * 4]; + +static struct regs_to_save power_setting_save[] = { + { .start_address = S5PC110_OSC_CON, .size = 1}, /* OSC_CON */ + { .start_address = S5PC110_PWR_CFG, .size = 5}, /* PWR_CFG ~ NORMAL_CFG */ + { .start_address = S5PC110_IDLE_CFG, .size = 1}, + { .start_address = S5PC110_STOP_CFG, .size = 2}, /* ~ STOP_MEM_CFG */ + { .start_address = S5PC110_SLEEP_CFG, .size = 1}, + + { .start_address = S5PC110_OSC_FREQ, .size = 3}, /* ~ PWR_STABLE */ + { .start_address = S5PC110_MTC_STABLE, .size = 2}, /* ~ CLAMP_STABLE */ + { .start_address = S5PC110_OTHERS, .size = 1}, + { .start_address = S5PC110_MIE_CONTROL, .size = 2}, /* ~ HDMI_CONTROL */ + { .start_address = S5PC110_USB_PHY_CON, .size = 5}, /* ~ PS_HOLD_CONTROL */ + { .start_address = S5PC110_INFORM0, .size = 8}, /* ~ INFORM7 */ +}; +static unsigned int buf_power_setting_save[1 + 5 + 1 + 2 + 1 + + 3 + 2 + 1 + 2 + 5 + 8]; + +static struct regs_to_save clock_setting_save[] = { + { .start_address = S5PC110_APLL_LOCK, .size = 1}, + { .start_address = S5PC110_MPLL_LOCK, .size = 1}, + { .start_address = S5PC110_EPLL_LOCK, .size = 1}, + { .start_address = S5PC110_VPLL_LOCK, .size = 1}, + { .start_address = S5PC110_APLL_CON, .size = 1}, + { .start_address = S5PC110_MPLL_CON, .size = 1}, + { .start_address = S5PC110_EPLL_CON, .size = 1}, + { .start_address = S5PC110_VPLL_CON, .size = 1}, +}; +static unsigned int buf_clock_setting_save[8]; + +static unsigned int reg_others; + +void s5pc110_save_reg(struct regs_to_save *list, + unsigned int *buf, int length) +{ + int i; + int j; + int counter = 0; + + for (i = 0; i < length; i++) { + for (j = 0; j < list[i].size; j++) { + *buf = readl((unsigned int *) + (list[i].start_address+j * 4)); + buf++; + counter++; + } + } +} + +void s5pc110_save_regs(void) +{ + reg_others = readl(S5PC110_OTHERS); + s5pc110_save_reg(gpio_save, buf_gpio_save, ARRAY_SIZE(gpio_save)); + s5pc110_save_reg(irq_save, buf_irq_save, ARRAY_SIZE(irq_save)); + s5pc110_save_reg(core_save, buf_core_save, ARRAY_SIZE(core_save)); + s5pc110_save_reg(sromc_save, buf_sromc_save, ARRAY_SIZE(sromc_save)); + s5pc110_save_reg(uart_save, buf_uart_save, ARRAY_SIZE(uart_save)); + + s5pc110_save_reg(power_setting_save, buf_power_setting_save, + ARRAY_SIZE(power_setting_save)); + s5pc110_save_reg(clock_setting_save, buf_clock_setting_save, + ARRAY_SIZE(clock_setting_save)); +} + +void s5pc110_restore_reg(struct regs_to_save *list, + unsigned int *buf, int length) +{ + int i; + int j; + + for (i = 0; i < length; i++) { + for (j = 0; j < list[i].size; j++) { + writel(*buf, (unsigned int *) + (list[i].start_address+j * 4)); + + if (s5pc1xx_get_cpu_rev() == 0) { + unsigned int tmp; + tmp = readl((unsigned int *) + (list[i].start_address+j * 4)); + } + + buf++; + } + } + +} + +void s5pc110_restore_regs(void) +{ + s5pc110_restore_reg(uart_save, buf_uart_save, ARRAY_SIZE(uart_save)); + s5pc110_restore_reg(sromc_save, buf_sromc_save, ARRAY_SIZE(sromc_save)); + s5pc110_restore_reg(core_save, buf_core_save, ARRAY_SIZE(core_save)); + s5pc110_restore_reg(irq_save, buf_irq_save, ARRAY_SIZE(irq_save)); + s5pc110_restore_reg(gpio_save, buf_gpio_save, ARRAY_SIZE(gpio_save)); + + s5pc110_restore_reg(power_setting_save, buf_power_setting_save, + ARRAY_SIZE(power_setting_save)); + s5pc110_restore_reg(clock_setting_save, buf_clock_setting_save, + ARRAY_SIZE(clock_setting_save)); +} + +void s5pc110_wakeup(void) +{ + struct stack *stk = &stacks[0]; + __asm__ ( + "msr cpsr_c, %1\n\t" + "add sp, %0, %2\n\t" + "msr cpsr_c, %3\n\t" + "add sp, %0, %4\n\t" + "msr cpsr_c, %5\n\t" + "add sp, %0, %6\n\t" + "msr cpsr_c, %7" + : + : "r" (stk), + "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), + "I" (offsetof(struct stack, irq[0])), + "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE), + "I" (offsetof(struct stack, abt[0])), + "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE), + "I" (offsetof(struct stack, und[0])), + "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE) + : "r14"); + + s5pc110_restore_regs(); + + reg_others |= (1 << 31); /* GPIO */ + reg_others |= (1 << 30); /* CF I/O */ + reg_others |= (1 << 29); /* MMC */ + reg_others |= (1 << 28); /* UART */ + writel(reg_others, S5PC110_OTHERS); + + printf("%s: Waking up...\n", __func__); + + timer_init(); +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) + /* init_func_i2c */ + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); +#endif +#if defined(CONFIG_CMD_ONENAND) + onenand_init(); +#endif +#ifdef CONFIG_SERIAL_MULTI + serial_initialize(); +#endif + stdio_init_resume(); /* get the devices list going. */ + + return; +} + +static int s5pc110_sleep(int mode) +{ + unsigned long regs_save[16]; + unsigned int value; + int i; + + printf("Entering s5pc110_sleep();\n"); + + board_sleep_init(); + + value = readl(S5PC110_WAKEUP_MASK); + value |= (1 << 15); + value |= (1 << 14); + value |= (1 << 13); + value |= (1 << 12); + value |= (1 << 11); + value |= (1 << 10); + value |= (1 << 9); + value |= (1 << 5); + value |= (1 << 4); + value |= (1 << 3); + value |= (1 << 2); + value |= (1 << 1); + + writel(value, S5PC110_WAKEUP_MASK); + + value = readl(S5PC110_EINT_WAKEUP_MASK); + value = 0xFFFFFFFF; + value &= ~(1 << 7); /* AP_PMIC_IRQ */ + value &= ~(1 << 22); /* nPOWER */ + /* value &= ~(1 << 23);*/ /* JACK_nINT */ + value &= ~(1 << 24); /* KBR(0) */ + value &= ~(1 << 25); /* KBR(1) */ + /* value &= ~(1 << 28);*/ /* T-Flash */ + writel(value, S5PC110_EINT_WAKEUP_MASK); + + if (s5pc1xx_get_cpu_rev() == 0) { + value = readl(S5PC110_EINT_WAKEUP_MASK); + for (i = 0; i < 4; i++) + value = readl(0xE0200F40 + i * 4); + } + + s5pc110_save_regs(); + + board_sleep_init_late(); + + writel((unsigned long) s5pc110_cpu_resume, S5PC110_INFORM0); + + if (s5pc1xx_get_cpu_rev() == 0) { + value = readl(S5PC110_SLEEP_CFG); + value &= ~(1 << 0); /* OSC_EN off */ + value &= ~(1 << 1); /* USBOSC_EN off */ + writel(value, S5PC110_SLEEP_CFG); + } + + value = readl(S5PC110_PWR_CFG); + value &= ~S5PC110_CFG_STANDBYWFI_MASK; + if (mode == SLEEP_WFI) { + if (s5pc1xx_get_cpu_rev() == 0) { + printf("ERRATA MODE\n"); + value |= S5PC110_CFG_STANDBYWFI_IGNORE; + } else { + value |= S5PC110_CFG_STANDBYWFI_SLEEP; + } + } else { + value |= S5PC110_CFG_STANDBYWFI_IGNORE; + } + + writel(value, S5PC110_PWR_CFG); + + /* F2000000: VICIRQSTATUS-irq0 */ + writel(0xffffffff, 0xF2000000 + 0x14); /* VIC_INT_ENABLE_CLEAR */ + writel(0xffffffff, 0xF2100000 + 0x14); + writel(0xffffffff, 0xF2200000 + 0x14); + writel(0xffffffff, 0xF2300000 + 0x14); + writel(0xffffffff, 0xF2000000 + 0x1c); /* VIC_INT_SOFT_CLEAR */ + writel(0xffffffff, 0xF2100000 + 0x1c); + writel(0xffffffff, 0xF2200000 + 0x1c); + writel(0xffffffff, 0xF2300000 + 0x1c); + + /* Clear all EINT PENDING bit */ + writel(0xff, 0xE0200000 + 0xF40); + value = readl(0xE0200000 + 0xF40); + writel(0xff, 0xE0200000 + 0xF44); + value = readl(0xE0200000 + 0xF44); + writel(0xff, 0xE0200000 + 0xF48); + value = readl(0xE0200000 + 0xF48); + writel(0xff, 0xE0200000 + 0xF4C); + value = readl(0xE0200000 + 0xF4C); + + value = readl(S5PC110_WAKEUP_STAT); + writel(value, S5PC110_WAKEUP_STAT); + + + value = readl(S5PC110_OTHERS); + value |= S5PC110_OTHERS_SYSCON_INT_DISABLE; + writel(value, S5PC110_OTHERS); + + s5pc110_sleep_save_phys = (unsigned int) regs_save; + + value = readl(S5PC110_OTHERS); + value |= 1; + writel(value, S5PC110_OTHERS); + + /* cache flush */ + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); + l2_cache_disable(); + invalidate_dcache(get_device_type()); + + if (s5pc110_cpu_save(regs_save) == 0) { + /* cache flush */ + asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0)); + l2_cache_disable(); + invalidate_dcache(get_device_type()); + + if (mode == SLEEP_WFI) { + if (s5pc1xx_get_cpu_rev() == 0) { + printf("Warn: Entering SLEEP_WFI mode with" + "EVT0_ERRATA. \n"); + printf("Warn: This sleep will probably fail\n"); + } + + value = readl(S5PC110_PWR_CFG); + value &= ~S5PC110_CFG_STANDBYWFI_MASK; + value |= S5PC110_CFG_STANDBYWFI_SLEEP; + writel(value, S5PC110_PWR_CFG); + + asm ("b 1f\n\t" + ".align 5\n\t" + "1:\n\t" + "mcr p15, 0, %0, c7, c10, 5\n\t" + "mcr p15, 0, %0, c7, c10, 4\n\t" + ".word 0xe320f003" :: "r" (value)); + + } else { /* SLEEP_REGISTER */ + value = (1 << 2); + writel(value, S5PC110_PWR_MODE); + + while (1) + ; + } + } + + + s5pc110_wakeup(); + + writel(0, S5PC110_EINT_WAKEUP_MASK); + readl(S5PC110_EINT_WAKEUP_MASK); + + for (i = 0; i < 4; i++) + readl(0xE0200F40 + i * 4); + + value = readl(S5PC110_WAKEUP_STAT); + writel(0xFFFF & value, S5PC110_WAKEUP_STAT); + + printf("Wakeup Source: 0x%08x\n", value); + value = readl(S5PC110_WAKEUP_STAT); + + board_sleep_resume(); + return 0; +} + +int do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int mode = SLEEP_WFI; + + if (argc >= 2) + mode = SLEEP_REGISTER; + + if (cpu_is_s5pc110()) + return s5pc110_sleep(mode); + + cmd_usage(cmdtp); + return 1; +} + +U_BOOT_CMD( + sleep, CONFIG_SYS_MAXARGS, 1, do_sleep, + "S5PC110 sleep", + "- Sleep with SLEEP_WFI mode\n" + "sleep 1 - Sleep with SLEEP_REGISTER mode\n" +); diff --git a/cpu/arm1176/s5p64xx/sleep.h b/cpu/arm1176/s5p64xx/sleep.h new file mode 100644 index 0000000..ce8cb1a --- /dev/null +++ b/cpu/arm1176/s5p64xx/sleep.h @@ -0,0 +1,67 @@ +/* + * Copied and modified from linux/arch/arm/plat-s5pc11x/pm.c + * Copyright (c) 2004,2009 Simtec Electronics + * boyko.lee + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Parts based on arch/arm/mach-pxa/pm.c + * + * Thanks to Dimitry Andric for debugging +*/ + +#ifndef __S5PC110_SLEEP_H +#define __S5PC110_SLEEP_H + +#include +#include + +/* + * PSR bits + */ +/* #define USR26_MODE 0x00000000 */ +/* #define FIQ26_MODE 0x00000001 */ +/* #define IRQ26_MODE 0x00000002 */ +/* #define SVC26_MODE 0x00000003 */ +/* #define USR_MODE 0x00000010 */ +/* #define FIQ_MODE 0x00000011 */ +/* #define IRQ_MODE 0x00000012 */ +/* #define SVC_MODE 0x00000013 */ +/* #define ABT_MODE 0x00000017 */ +/* #define UND_MODE 0x0000001b */ +/* #define SYSTEM_MODE 0x0000001f */ +#define MODE32_BIT 0x00000010 +/* #define MODE_MASK 0x0000001f */ +#define PSR_T_BIT 0x00000020 +#define PSR_F_BIT 0x00000040 +#define PSR_I_BIT 0x00000080 +#define PSR_A_BIT 0x00000100 +#define PSR_J_BIT 0x01000000 +#define PSR_Q_BIT 0x08000000 +#define PSR_V_BIT 0x10000000 +#define PSR_C_BIT 0x20000000 +#define PSR_Z_BIT 0x40000000 +#define PSR_N_BIT 0x80000000 + +#ifndef __ASSEMBLY__ +extern void board_sleep_resume(void); +extern int s5pc110_cpu_save(unsigned long *saveblk); +extern void s5pc110_cpu_resume(void); +extern unsigned int s5pc110_sleep_return_addr; +extern unsigned int s5pc110_sleep_save_phys; + +#endif + +#endif diff --git a/cpu/arm1176/s5p64xx/sleep_asm.S b/cpu/arm1176/s5p64xx/sleep_asm.S new file mode 100644 index 0000000..a29c48d --- /dev/null +++ b/cpu/arm1176/s5p64xx/sleep_asm.S @@ -0,0 +1,160 @@ +/* linux/arch/arm/plat-s3c64xx/sleep.S + * + * Copyright (c) 2004 Simtec Electronics + * Ben Dooks + * + * S3C6410 Power Manager (Suspend-To-RAM) support + * + * Based on PXA/SA1100 sleep code by: + * Nicolas Pitre, (c) 2002 Monta Vista Software Inc + * Cliff Brake, (c) 2001 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#define ENTRY(name) \ + .global name; \ + .align 4,0x90; \ +name: + +#include "sleep.h" +#define SWRESET_VALUE 0xE0102000 + +/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not + * reset the UART configuration, only enable if you really need this! +*/ + .text + + /* s5pc110_cpu_save + * + * save enough of the CPU state to allow us to re-start + * pm.c code. as we store items like the sp/lr, we will + * end up returning from this function when the cpu resumes + * so the return value is set to mark this. + * + * This arangement means we avoid having to flush the cache + * from this code. + * + * entry: + * r0 = pointer to save block + * + * exit: + * r0 = 0 => we stored everything + * 1 => resumed from sleep + */ + +ENTRY(s5pc110_cpu_save) + + stmfd sp!, { r3 - r12, lr } + + mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID + mrc p15, 0, r5, c3, c0, 0 @ Domain ID + mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 + mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 + mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control + mrc p15, 0, r9, c1, c0, 0 @ Control register + mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register + mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls + mrc p15, 0, r12, c10, c2, 0 @ Read PRRR + mrc p15, 0, r3, c10, c2, 1 @ READ NMRR + + stmia r0, { r3 - r13 } + + mov r0, #0 + ldmfd sp, { r3 - r12, pc } + + @@ return to the caller, after having the MMU + @@ turned on, this restores the last bits from the + @@ stack + .align 4 +resume_without_mmu: + mov r0, #1 + + ldmfd sp!, { r3 - r12, pc } + + .ltorg + + @@ the next bits sit in the .data segment, even though they + @@ happen to be code... the s5pc110_sleep_save_phys needs to be + @@ accessed by the resume code before it can restore the MMU. + @@ This means that the variable has to be close enough for the + @@ code to read it... since the .text segment needs to be RO, + @@ the data segment can be the only place to put this code. + + .data + + + + .global s5pc110_sleep_save_phys +s5pc110_sleep_save_phys: + .word 0 + + + /* sleep magic, to allow the bootloader to check for an valid + * image to resume to. Must be the first word before the + * s5pc110_cpu_resume entry. + */ + + .word 0x2bedf00d + + /* s5pc110_cpu_resume + * + * resume code entry for bootloader to call + * + * we must put this code here in the data segment as we have no + * other way of restoring the stack pointer after sleep, and we + * must not write to the code segment (code is read-only) + */ + +ENTRY(s5pc110_cpu_resume) + mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE + msr cpsr_c, r0 + + @@ load UART to allow us to print the two characters for + @@ resume debug + + mov r1, #0 + mcr p15, 0, r1, c8, c7, 0 @@ invalidate TLBs + mcr p15, 0, r1, c7, c5, 0 @@ invalidate I Cache + + ldr r0, s5pc110_sleep_save_phys @ address of restore block + ldmia r0, { r3 - r13 } + + mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID + mcr p15, 0, r5, c3, c0, 0 @ Domain ID + + mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control + mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 + mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 + + mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register + + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB + + mov r0, #0 @ restore copro access controls + mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls + mcr p15, 0, r0, c7, c5, 4 + + mcr p15, 0, r12, c10, c2, 0 @ write PRRR + mcr p15, 0, r3, c10, c2, 1 @ write NMRR + + ldr r2, =resume_without_mmu + mov pc, r2 + + .ltorg + diff --git a/cpu/arm1176/s5p64xx/timer.c b/cpu/arm1176/s5p64xx/timer.c new file mode 100644 index 0000000..a99af78 --- /dev/null +++ b/cpu/arm1176/s5p64xx/timer.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Heungjun Kim + * Inki Dae + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#define PRESCALER_1 (16 - 1) /* prescaler of timer 2, 3, 4 */ +#define MUX_DIV_2 1 /* 1/2 period */ +#define MUX_DIV_4 2 /* 1/4 period */ +#define MUX_DIV_8 3 /* 1/8 period */ +#define MUX_DIV_16 4 /* 1/16 period */ +#define MUX4_DIV_SHIFT 16 + +#define TCON_TIMER4_SHIFT 20 + +static unsigned long count_value; + +/* Internal tick units */ +static unsigned long long timestamp; /* Monotonic incrementing timer */ +static unsigned long lastdec; /* Last decremneter snapshot */ + +/* macro to read the 16 bit timer */ +static inline struct s5p64xx_timer *s5p64xx_get_base_timer(void) +{ + if (cpu_is_s5p6442()) + return (struct s5p64xx_timer *)S5P6442_TIMER_BASE; + else + return NULL; +} + +int timer_init(void) +{ + struct s5p64xx_timer *const timer = s5p64xx_get_base_timer(); + u32 val; + + /* + * @ PWM Timer 4 + * Timer Freq(HZ) = + * PCLK / { (prescaler_value + 1) * (divider_value) } + */ + + /* set prescaler : 16 */ + /* set divider : 2 */ + val = readl(&timer->tcfg0); + val &= ~(0xff << 8); + val |= (PRESCALER_1 & 0xff) << 8; + writel(val, &timer->tcfg0); + val = readl(&timer->tcfg1); + val &= ~(0xf << MUX4_DIV_SHIFT); + val |= (MUX_DIV_2 & 0xF) << MUX4_DIV_SHIFT; + writel(val, &timer->tcfg1); + + if (count_value == 0) { + /* reset initial value */ + /* count_value = 2085937.5(HZ) (per 1 sec)*/ + count_value = get_pclk() / ((PRESCALER_1 + 1) * + (MUX_DIV_2 + 1)); + + /* count_value / 100 = 20859.375(HZ) (per 10 msec) */ + count_value = count_value / 100; + } + + /* set count value */ + writel(count_value, &timer->tcntb4); + lastdec = count_value; + + val = (readl(&timer->tcon) & ~(0x07 << TCON_TIMER4_SHIFT)) | + S5P64XX_TCON4_AUTO_RELOAD; + + /* auto reload & manual update */ + writel(val | S5P64XX_TCON4_UPDATE, &timer->tcon); + + /* start PWM timer 4 */ + writel(val | S5P64XX_TCON4_START, &timer->tcon); + + timestamp = 0; + + return 0; +} + +/* + * timer without interrupts + */ +void reset_timer(void) +{ + reset_timer_masked(); +} + +unsigned long get_timer(unsigned long base) +{ + return get_timer_masked() - base; +} + +void set_timer(unsigned long t) +{ + timestamp = t; +} + +/* delay x useconds */ +void udelay(unsigned long usec) +{ + unsigned long tmo, tmp, now, until; + + if (usec >= 1000) { + /* + * if "big" number, spread normalization + * to seconds + * 1. start to normalize for usec to ticks per sec + * 2. find number of "ticks" to wait to achieve target + * 3. finish normalize. + */ + tmo = usec / 1000; + tmo *= (CONFIG_SYS_HZ * count_value / 10); + tmo /= 1000; + } else { + /* else small number, don't kill it prior to HZ multiply */ + tmo = usec * CONFIG_SYS_HZ * count_value / 10; + tmo /= (1000 * 1000); + } + + /* get current timestamp */ + tmp = get_timer_masked(); + + /* if setting this fordward will roll time stamp */ + /* reset "advancing" timestamp to 0, set lastdec value */ + /* else, set advancing stamp wake up time */ + until = tmo + tmp + count_value; + if (until < tmp) { + reset_timer_masked(); + tmp = get_timer_masked(); + tmo += tmp; + + } + else + tmo += tmp; + + /* loop till event */ /* FIX: consider the overflow case */ + while ((now = get_timer_masked()) < tmo && now >= tmp) + ; /* nop */ +} + +void reset_timer_masked(void) +{ + struct s5p64xx_timer *const timer = s5p64xx_get_base_timer(); + + /* reset time */ + lastdec = readl(&timer->tcnto4); + timestamp = 0; +} + +unsigned long get_timer_masked(void) +{ + struct s5p64xx_timer *const timer = s5p64xx_get_base_timer(); + unsigned long now = readl(&timer->tcnto4); + + if (lastdec >= now) + timestamp += lastdec - now; + else + timestamp += lastdec + count_value - now; + + lastdec = now; + + return timestamp; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/cpu/arm1176/s5p64xx/usb-hs-otg.c b/cpu/arm1176/s5p64xx/usb-hs-otg.c new file mode 100644 index 0000000..7851b2d --- /dev/null +++ b/cpu/arm1176/s5p64xx/usb-hs-otg.c @@ -0,0 +1,1816 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#include +#include +#include +#include "usb-hs-otg.h" + +#define SUSPEND_RESUME_ON 0 + +u32 remode_wakeup; +u16 config_value; + +int s5p_receive_done; +int s5p_got_header; +int s5p_usb_connected; + +USB_OPMODE op_mode = USB_CPU; +USB_SPEED speed = USB_HIGH; +/* +USB_OPMODE op_mode = USB_DMA; +USB_SPEED speed = USB_FULL; +*/ + +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 */ +{ + (0x22 + 2), STRING_DESCRIPTOR, + 'S', 0x0, 'A', 0x0, 'M', 0x0, 'S', 0x0, 'U', 0x0, + 'N', 0x0, 'G', 0x0, ' ', 0x0, 'X', 0x0, 'O', 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 +++*/ +#define CONFIG_DESC_TOTAL_SIZE \ + (CONFIG_DESC_SIZE+INTERFACE_DESC_SIZE+ENDPOINT_DESC_SIZE*2) + +static unsigned int phy_base; +static unsigned int otg_base; + +static inline void s5p_usb_init_base(void) +{ + if (cpu_is_s5pc110()) { + phy_base = S5PC110_PHY_BASE; + otg_base = S5PC110_OTG_BASE; + } else { + phy_base = S5PC100_PHY_BASE; + otg_base = S5PC100_OTG_BASE; + } +} + +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); +} + +void s5p_usb_init_phy(void) +{ + if (cpu_is_s5pc110()) { + s5pc1xx_phy_write_reg(0xA0, OTG_PHYPWR); + s5pc1xx_phy_write_reg(0x3, OTG_PHYCTRL); + } else { + s5pc1xx_phy_write_reg(0x0, OTG_PHYPWR); +#ifdef CONFIG_OTG_CLK_OSCC + s5pc1xx_phy_write_reg(0x22, OTG_PHYCTRL); +#else + s5pc1xx_phy_write_reg(0x2, OTG_PHYCTRL); +#endif + } + + s5pc1xx_phy_write_reg(0x1, OTG_RSTCON); + udelay(20); + s5pc1xx_phy_write_reg(0x0, OTG_RSTCON); + udelay(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); +} + +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)); +} + +void s5p_usb_wait_cable_insert(void) +{ + u32 tmp; + int ucFirst = 1; + + do { + udelay(50); + + tmp = s5pc1xx_otg_read_reg(OTG_GOTGCTL); + + if (tmp & (B_SESSION_VALID | A_SESSION_VALID)) { + break; + } else if (ucFirst == 1) { + printf("Insert a OTG cable into the connector!\n"); + ucFirst = 0; + } + } while (1); +} + +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); +} + +void s5p_usb_check_current_mode(u8 *pucMode) +{ + u32 tmp; + + tmp = s5pc1xx_otg_read_reg(OTG_GINTSTS); + *pucMode = tmp & 0x1; +} + +void s5p_usb_set_soft_disconnect(void) +{ + u32 tmp; + + tmp = s5pc1xx_otg_read_reg(OTG_DCTL); + tmp |= SOFT_DISCONNECT; + s5pc1xx_otg_write_reg(tmp, OTG_DCTL); +} + +void s5p_usb_clear_soft_disconnect(void) +{ + u32 tmp; + + tmp = s5pc1xx_otg_read_reg(OTG_DCTL); + tmp &= ~SOFT_DISCONNECT; + s5pc1xx_otg_write_reg(tmp, OTG_DCTL); +} + +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(); + + if (cpu_is_s5pc110()) { + reg = readl(S5PC110_USB_PHY_CON); + reg |= (1 << 0); /* USB PHY0 enable */ + writel(reg, S5PC110_USB_PHY_CON); + } else { + reg = readl(S5PC100_OTHERS); + reg |= (1 << 16); /* unmask usb signal */ + writel(reg, S5PC100_OTHERS); + } + + 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_set_soft_disconnect(); + udelay(10); + s5p_usb_clear_soft_disconnect(); + s5p_usb_init_device(); + return 0; + } else { + printf("Error : Current Mode is Host\n"); + return 0; + } +} + +int s5p_usbc_activate(void) +{ + return 0; +} + +void s5p_usb_stop(void) +{ +} + +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); + } +} + +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 */ +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); +} + +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; + } +} + +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; +} + +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; + } + + switch (otg.dev_req.wValue_L) { + case EP_STALL: + /* TBD: additional processing if required */ + break; + + case TEST_MODE: + /* not support */ + break; + + default: + break; + } + otg.ep0_state = EP0_STATE_INIT; +} + +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; + } +} + +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); + + if (otg.speed == USB_HIGH) { + /*clear nak, next ep0, 64byte */ + s5pc1xx_otg_write_reg(((1 << 26) | (CONTROL_EP << 11) | (0 << 0)), + OTG_DIEPCTL0); + } else { + /*clear nak, next ep0, 8byte */ + s5pc1xx_otg_write_reg(((1 << 26) | (CONTROL_EP << 11) | (3 << 0)), + OTG_DIEPCTL0); + } + +} + +void s5p_usb_set_otherspeed_conf_desc(u32 length) +{ + /* Standard device descriptor */ + if (otg.speed == USB_HIGH) { + 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; + } else { + if (length == 9) { + 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); + } else if (length == 32) { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, 8); + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0); + s5p_usb_write_ep0_fifo((u8 *) &config_high_total, 8); + } + otg.ep0_state = EP0_STATE_GD_OTHER_SPEED_HIGH_1; + } +} + +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: + if (otg.speed == USB_HIGH) { + /*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; + } else { + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0); + if (otg.req_length < DEVICE_DESC_SIZE) { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + otg.req_length); + } else { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + DEVICE_DESC_SIZE); + } + + if (otg.req_length < FS_CTRL_PKT_SIZE) { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)), + otg.req_length); + otg.ep0_state = EP0_STATE_INIT; + } else { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.dev)), + FS_CTRL_PKT_SIZE); + otg.ep0_state = EP0_STATE_GD_DEV_1; + } + } + 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: + if (otg.speed == USB_HIGH) { + 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; + } else { + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0); + if (otg.req_length < CONFIG_DESC_TOTAL_SIZE) { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + otg.req_length); + } else { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + CONFIG_DESC_TOTAL_SIZE); + } + if (otg.req_length < FS_CTRL_PKT_SIZE) { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)), + otg.req_length); + otg.ep0_state = EP0_STATE_INIT; + } else { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)), + FS_CTRL_PKT_SIZE); + otg.ep0_state = EP0_STATE_GD_CFG_1; + } + } + 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.speed == USB_HIGH) { + 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; + } else { + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0); + if (otg.req_length < CONFIG_DESC_SIZE) { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + otg.req_length); + } else { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + CONFIG_DESC_SIZE); + } + if (otg.req_length < FS_CTRL_PKT_SIZE) { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)), + otg.req_length); + otg.ep0_state = EP0_STATE_INIT; + } else { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.config)), + FS_CTRL_PKT_SIZE); + otg.ep0_state = EP0_STATE_GD_CFG_ONLY_1; + } + } + 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.speed == USB_HIGH) { + 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; + } else { + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, OTG_DIEPCTL0); + if (otg.req_length < INTERFACE_DESC_SIZE) { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + otg.req_length); + } else { + s5p_usb_set_inep_xfersize(EP_TYPE_CONTROL, 1, + INTERFACE_DESC_SIZE); + } + if (otg.req_length < FS_CTRL_PKT_SIZE) { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.intf)), + otg.req_length); + otg.ep0_state = EP0_STATE_INIT; + } else { + s5p_usb_write_ep0_fifo(((u8 *) &(otg.desc.intf)), + FS_CTRL_PKT_SIZE); + otg.ep0_state = EP0_STATE_GD_IF_ONLY_1; + } + } + 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)) { + if (otg.speed == USB_HIGH) + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0); + else + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, 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 { + if (otg.speed == USB_HIGH) + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0); + else + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, 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)) { + if (otg.speed == USB_HIGH) + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0); + else + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, 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 { + if (otg.speed == USB_HIGH) + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_64, OTG_DIEPCTL0); + else + s5pc1xx_otg_write_reg(EPEN_CNAK_EP0_8, 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); + } else if ((otg.op_mode == USB_DMA) && (otg.up_size > 0)) { + u32 pktcnt, remainder; + + s5pc1xx_otg_write_reg(MODE_DMA | BURST_INCR4 | GBL_INT_UNMASK, + OTG_GAHBCFG); + s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP | INT_IN_EP | + INT_ENUMDONE | INT_RESET | INT_SUSPEND, + OTG_GINTMSK); + + s5pc1xx_otg_write_reg((u32) otg.up_ptr, OTG_DIEPDMA_IN); + + pktcnt = (u32) (otg.up_size / otg.bulkin_max_pktsize); + remainder = (u32) (otg.up_size % otg.bulkin_max_pktsize); + if (remainder != 0) + pktcnt += 1; + + if (pktcnt > 1023) { + s5p_usb_set_inep_xfersize(EP_TYPE_BULK, 1023, + otg.bulkin_max_pktsize * 1023); + } else { + s5p_usb_set_inep_xfersize(EP_TYPE_BULK, pktcnt, + otg.up_size); + } + + /*ep1 enable, clear nak, bulk, usb active, next ep1, max pkt */ + s5pc1xx_otg_write_reg(1u << 31 | 1 << 26 | 2 << 18 | 1 << 15 | + BULK_IN_EP << 11 | otg.bulkin_max_pktsize << 0, + OTG_DIEPCTL_IN); + } +} + +void s5p_usb_rx(u32 fifo_cnt_byte) +{ + if (otg.op_mode == USB_CPU) { + 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; + } else if (otg.dn_filesize > otg.bulkout_max_pktsize) { + u32 pkt_cnt, remain_cnt; + + s5pc1xx_otg_write_reg(INT_RESUME | INT_OUT_EP | INT_IN_EP | + INT_ENUMDONE | INT_RESET | INT_SUSPEND, + OTG_GINTMSK); + s5pc1xx_otg_write_reg(MODE_DMA | BURST_INCR4 | GBL_INT_UNMASK, + OTG_GAHBCFG); + s5pc1xx_otg_write_reg((u32) otg.dn_ptr, OTG_DOEPDMA_OUT); + pkt_cnt = (u32)(otg.dn_filesize - otg.bulkout_max_pktsize) / + otg.bulkout_max_pktsize; + remain_cnt = (u32)((otg.dn_filesize - otg.bulkout_max_pktsize) % + otg.bulkout_max_pktsize); + + if (remain_cnt != 0) + pkt_cnt += 1; + + if (pkt_cnt > 1023) { + s5p_usb_set_outep_xfersize(EP_TYPE_BULK, 1023, + otg.bulkout_max_pktsize * 1023); + } else { + s5p_usb_set_outep_xfersize(EP_TYPE_BULK, pkt_cnt, + otg.dn_filesize - 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); + } +} + +void s5p_usb_int_bulkout(u32 fifo_cnt_byte) +{ + s5p_usb_rx(fifo_cnt_byte); +} + +void s5p_usb_dma_in_done(void) +{ + s32 remain_cnt; + + otg.up_ptr = (u8 *)s5pc1xx_otg_read_reg(OTG_DIEPDMA_IN); + remain_cnt = otg.up_size - ((u32) otg.up_ptr - otg.up_addr); + + if (remain_cnt > 0) { + u32 pktcnt, remainder; + pktcnt = (u32)(remain_cnt / otg.bulkin_max_pktsize); + remainder = (u32)(remain_cnt % otg.bulkin_max_pktsize); + + if (remainder != 0) + pktcnt += 1; + + if (pktcnt > 1023) { + s5p_usb_set_inep_xfersize(EP_TYPE_BULK, 1023, + otg.bulkin_max_pktsize * 1023); + } else { + s5p_usb_set_inep_xfersize(EP_TYPE_BULK, pktcnt, + remain_cnt); + } + + /*ep1 enable, clear nak, bulk, usb active, next ep1, max pkt */ + s5pc1xx_otg_write_reg(1u << 31 | 1 << 26 | 2 << 18 | 1 << 15 | + BULK_IN_EP << 11 | otg.bulkin_max_pktsize << 0, + OTG_DIEPCTL_IN); + + s5p_receive_done = 1; + } +} + +void s5p_usb_dma_out_done(void) +{ + s32 remain_cnt; + + otg.dn_ptr = (u8 *)s5pc1xx_otg_read_reg(OTG_DOEPDMA_OUT); + + remain_cnt = otg.dn_filesize - ((u32) otg.dn_ptr - otg.dn_addr + 8); + + if (remain_cnt > 0) { + u32 pktcnt, remainder; + pktcnt = (u32)(remain_cnt / otg.bulkout_max_pktsize); + remainder = (u32)(remain_cnt % otg.bulkout_max_pktsize); + + if (remainder != 0) + pktcnt += 1; + + if (pktcnt > 1023) { + s5p_usb_set_outep_xfersize(EP_TYPE_BULK, 1023, + otg.bulkout_max_pktsize * 1023); + } else { + s5p_usb_set_outep_xfersize(EP_TYPE_BULK, pktcnt, + remain_cnt); + } + + /*ep3 enable, clear nak, bulk, usb active, next ep3, max pkt 64 */ + s5pc1xx_otg_write_reg(1u << 31 | 1 << 26 | 2 << 18 | 1 << 15 | + otg.bulkout_max_pktsize << 0, OTG_DOEPCTL_OUT); + } else { + udelay(500); /*for FPGA ??? */ + } +} + +void s5p_usb_set_all_outep_nak(void) +{ + u8 i; + u32 tmp; + + for (i = 0; i < 16; i++) { + tmp = s5pc1xx_otg_read_reg(OTG_DOEPCTL0 + 0x20 * i); + tmp |= DEPCTL_SNAK; + s5pc1xx_otg_write_reg(tmp, OTG_DOEPCTL0 + 0x20 * i); + } +} + +void s5p_usb_clear_all_outep_nak(void) +{ + u8 i; + u32 tmp; + + for (i = 0; i < 16; i++) { + tmp = s5pc1xx_otg_read_reg(OTG_DOEPCTL0 + 0x20 * i); + tmp |= (DEPCTL_EPENA | DEPCTL_CNAK); + s5pc1xx_otg_write_reg(tmp, OTG_DOEPCTL0 + 0x20 * i); + } +} + +void s5p_usb_set_max_pktsize(USB_SPEED speed) +{ + if (speed == USB_HIGH) { + 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; + } else { + otg.speed = USB_FULL; + otg.ctrl_max_pktsize = FS_CTRL_PKT_SIZE; + otg.bulkin_max_pktsize = FS_BULK_PKT_SIZE; + otg.bulkout_max_pktsize = FS_BULK_PKT_SIZE; + } +} + +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 */ + if (otg.speed == USB_HIGH) { + /*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); + } else { + /*MPS:8bytes */ + s5pc1xx_otg_write_reg(((1 << 26) | (CONTROL_EP << 11) | (3 << 0)), + OTG_DIEPCTL0); + /*ep0 enable, clear nak */ + s5pc1xx_otg_write_reg((1u << 31) | (1 << 26) | (3 << 0), + OTG_DOEPCTL0); + } +} + +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; + if (otg.speed == USB_FULL) { + otg.desc.dev.bcdUSBL = 0x10; + otg.desc.dev.bcdUSBH = 0x01; + } else { + 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; + if (otg.speed == USB_FULL) { + otg.desc.dev.bcdUSBL = 0x10; + otg.desc.dev.bcdUSBH = 0x01; + } else { + 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; +} + +void s5p_usb_check_speed(USB_SPEED *speed) +{ + u32 status; + + status = s5pc1xx_otg_read_reg(OTG_DSTS); + + *speed = (USB_SPEED)((status & 0x6) >> 1); +} + +int s5p_usb_check_setconf(void) +{ + return otg.set_config; +} + +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); +} + +void s5p_usb_reset(void) +{ + s5p_usb_set_all_outep_nak(); + + 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_clear_all_outep_nak(); + + /*clear device address */ + s5pc1xx_otg_write_reg(s5pc1xx_otg_read_reg(OTG_DCFG) & ~(0x7f << 4), + OTG_DCFG); + + if (SUSPEND_RESUME_ON) { + s5pc1xx_otg_write_reg(s5pc1xx_otg_read_reg(OTG_PCGCCTRL) & ~(1 << 0), + OTG_PCGCCTRL); + } +} + +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) { + s5p_usb_set_max_pktsize(USB_FULL); + } else { + printf("Error:Neither High_Speed nor Full_Speed\n"); + return 0; + } + + s5p_usb_set_endpoint(); + s5p_usb_set_descriptors(); + s5p_usb_set_opmode(op_mode); + + return 1; +} + +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; + } + + } else if ((rx_status & (0xf << 17)) == GLOBAL_OUT_NAK) { + /* nop */ + } else if ((rx_status & (0xf << 17)) == OUT_TRNASFER_COMPLETED) { + /* nop */ + } else if ((rx_status & (0xf << 17)) == SETUP_TRANSACTION_COMPLETED) { + /* nop */ + } else { + /* nop */ + } +} + +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 ((check_dma & MODE_DMA) && (ep_int_status & TRANSFER_DONE)) + s5p_usb_dma_in_done(); + } + + 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); + + if ((check_dma & MODE_DMA) && (ep_int_status & TRANSFER_DONE)) + s5p_usb_dma_out_done(); + } +} + +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 (SUSPEND_RESUME_ON) { + s5pc1xx_otg_write_reg(s5pc1xx_otg_read_reg(OTG_PCGCCTRL) & + ~(1 << 0), OTG_PCGCCTRL); + } + } + + if (int_status & INT_SUSPEND) { + s5pc1xx_otg_write_reg(INT_SUSPEND, OTG_GINTSTS); + + if (SUSPEND_RESUME_ON) { + s5pc1xx_otg_write_reg(s5pc1xx_otg_read_reg(OTG_PCGCCTRL) | + (1 << 0), OTG_PCGCCTRL); + } + } + + 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(); +} diff --git a/cpu/arm1176/s5p64xx/usb-hs-otg.h b/cpu/arm1176/s5p64xx/usb-hs-otg.h new file mode 100644 index 0000000..6d2e46e --- /dev/null +++ b/cpu/arm1176/s5p64xx/usb-hs-otg.h @@ -0,0 +1,277 @@ +/* + * (C) Copyright 2007 + * Byungjae Lee, Samsung Erectronics, bjlee@samsung.com. + * - only support for S3C6400 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __USBD_HS_OTG_H__ +#define __USBD_HS_OTG_H__ + +#include +#include +#include + +#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); +int s5p_usbc_activate(void); +void s5p_usb_stop(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 diff --git a/cpu/arm1176/s5p64xx/usb_downloader.c b/cpu/arm1176/s5p64xx/usb_downloader.c new file mode 100644 index 0000000..c641663 --- /dev/null +++ b/cpu/arm1176/s5p64xx/usb_downloader.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include +#include "usbd.h" +#include "usb-hs-otg.h" +#ifdef CONFIG_S5PC1XXFB +#include +#endif + +static char tx_data[8] = "MPL"; +static long tx_len = 4; + +static char rx_data[2048]; +static long rx_len = 64; + +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"))); + +/* clear download informations */ +static void s5p_usb_clear_dnfile_info(void) +{ + otg.dn_addr = 0; + otg.dn_filesize = 0; + otg.dn_ptr = 0; +} + +/* clear upload informations */ +static void s5p_usb_clear_upfile_info(void) +{ + otg.up_addr = 0; + otg.up_size = 0; + otg.up_ptr = 0; +} + +/* start the usb controller */ +static void usb_init(void) +{ + if (usb_board_init()) { + printf("Failed to usb_board_init\n"); + return; + } + +#ifdef CONFIG_S5PC1XXFB + init_font(); + set_font_color(FONT_WHITE); + fb_printf("Ready to USB Connection\n"); +#endif + + s5p_usbctl_init(); + s5p_usbc_activate(); + + printf("USB Start!! - %s Speed\n", + otg.speed ? "Full" : "High"); + + while (!s5p_usb_connected) { + if (s5p_usb_detect_irq()) { + s5p_udc_int_hndlr(); + s5p_usb_clear_irq(); + } + } + + s5p_usb_clear_dnfile_info(); + + printf("Connected!!\n"); + +#ifdef CONFIG_S5PC1XXFB + fb_printf("Download Start\n"); + draw_progress(40, 0, FONT_WHITE); +#endif +} + +static void usb_stop(void) +{ + s5p_usb_stop(); +#ifdef CONFIG_S5PC1XXFB + exit_font(); + + /* it uses fb3 as default window. */ + s5pc_fimd_lcd_off(3); + s5pc_fimd_window_off(3); +#endif +} + +/* + * 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; +} + +#ifdef CONFIG_GENERIC_MMC +#include + +static void usbd_set_mmc_dev(struct usbd_ops *usbd) +{ + struct mmc *mmc; + + usbd->mmc_dev = 0; + /* FIX 0x400 */ + usbd->mmc_max = 0x400; + /* get from mmc->capacity?? */ + usbd->mmc_total = 0xf50000; /* 8GB / 0x200 */ + + mmc = find_mmc_device(usbd->mmc_dev); + mmc_init(mmc); + + usbd->mmc_blk = mmc->read_bl_len; +} +#endif + +#ifdef CONFIG_S5PC1XXFB +static void set_progress(int progress) +{ + draw_progress(40, progress, FONT_WHITE); +} +#endif +/* + * 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_len; + usbd->rx_len = rx_len; + usbd->ram_addr = CONFIG_SYS_DOWN_ADDR; +#ifdef CONFIG_S5PC1XXFB + usbd->set_progress = set_progress; +#endif +#ifdef CONFIG_GENERIC_MMC + usbd_set_mmc_dev(usbd); +#endif + + return usbd; +} diff --git a/cpu/arm1176/start.S b/cpu/arm1176/start.S index 68a356d..e48999e 100644 --- a/cpu/arm1176/start.S +++ b/cpu/arm1176/start.S @@ -35,7 +35,9 @@ #ifdef CONFIG_ENABLE_MMU #include #endif +#ifdef CONFIG_S3C64XX #include +#endif #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE) #define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 3c77a7c..5f0eebb 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -34,6 +34,7 @@ COBJS-$(CONFIG_SYS_NS16550) += ns16550.o COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o COBJS-$(CONFIG_S3C64XX) += s3c64xx.o COBJS-$(CONFIG_S5PC1XX) += serial_s5pc1xx.o +COBJS-$(CONFIG_S5P64XX) += serial_s5pc1xx.o COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial.o COBJS-$(CONFIG_CLPS7111_SERIAL) += serial_clps7111.o COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o diff --git a/drivers/serial/serial_s5pc1xx.c b/drivers/serial/serial_s5pc1xx.c index 73669a9..6cd0c17 100644 --- a/drivers/serial/serial_s5pc1xx.c +++ b/drivers/serial/serial_s5pc1xx.c @@ -31,10 +31,15 @@ static inline struct s5pc1xx_uart *s5pc1xx_get_base_uart(int dev_index) { u32 offset = dev_index * sizeof(struct s5pc1xx_uart); +#ifdef CONFIG_S5PC1XX if (cpu_is_s5pc100()) return (struct s5pc1xx_uart *)(S5PC100_UART_BASE + offset); else return (struct s5pc1xx_uart *)(S5PC110_UART_BASE + offset); +#elif CONFIG_S5P64XX + if (cpu_is_s5p6442()) + return (struct s5pc1xx_uart *)(S5P6442_UART_BASE + offset); +#endif } /* diff --git a/include/asm-arm/arch-s5p64xx/clk.h b/include/asm-arm/arch-s5p64xx/clk.h new file mode 100644 index 0000000..9feb3e6 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/clk.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARM_ARCH_CLK_H_ +#define __ASM_ARM_ARCH_CLK_H_ + +void s5p64xx_clock_init(void); + +extern unsigned long (*get_pll_clk)(int pllreg); +extern unsigned long (*get_arm_clk)(void); +extern unsigned long (*get_pclk)(void); + +#endif diff --git a/include/asm-arm/arch-s5p64xx/clock.h b/include/asm-arm/arch-s5p64xx/clock.h new file mode 100644 index 0000000..e7df0b4 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/clock.h @@ -0,0 +1,83 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARM_ARCH_CLOCK_H_ +#define __ASM_ARM_ARCH_CLOCK_H_ + +#define APLL 0 +#define MPLL 1 +#define EPLL 2 +#define HPLL 3 +#define VPLL 4 + +#define S5P6442_APLL_LOCK 0xE0100000 +#define S5P6442_MPLL_LOCK 0xE0100008 +#define S5P6442_EPLL_LOCK 0xE0100010 +#define S5P6442_VPLL_LOCK 0xE0100020 +#define S5P6442_APLL_CON 0xE0100100 +#define S5P6442_MPLL_CON 0xE0100108 +#define S5P6442_EPLL_CON 0xE0100110 +#define S5P6442_VPLL_CON 0xE0100120 + +#ifndef __ASSEMBLY__ +struct s5p6442_clock { + unsigned int apll_lock; + unsigned char res1[0x4]; + unsigned int mpll_lock; + unsigned char res2[0x4]; + unsigned int epll_lock; + unsigned char res3[0xc]; + unsigned int vpll_lock; + unsigned char res4[0xdc]; + unsigned int apll_con; + unsigned char res5[0x4]; + unsigned int mpll_con; + unsigned char res6[0x4]; + unsigned int epll_con; + unsigned char res7[0xc]; + unsigned int vpll_con; + unsigned char res8[0xdc]; + unsigned int src0; + unsigned int src1; + unsigned int src2; + unsigned int src3; + unsigned int src4; + unsigned int src5; + unsigned int src6; + unsigned char res9[0xe4]; + unsigned int div0; + unsigned int div1; + unsigned int div2; + unsigned int div3; + unsigned int div4; + unsigned int div5; + unsigned int div6; + unsigned char res10[0x1e4]; + unsigned int gate_d00; + unsigned int gate_d01; + unsigned int gate_d02; + unsigned char res11[0x54]; + unsigned int gate_sclk0; + unsigned int gate_sclk1; +}; +#endif + +#endif diff --git a/include/asm-arm/arch-s5p64xx/cpu.h b/include/asm-arm/arch-s5p64xx/cpu.h new file mode 100644 index 0000000..cd84e5d --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/cpu.h @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef _S5P64XX_CPU_H +#define _S5P64XX_CPU_H + +#define S5P64XX_ADDR_BASE 0xE0000000 + +#define S5P64XX_CLOCK_BASE 0xE0100000 + +/* S5P6442 */ +#define S5P6442_GPIO_BASE 0xE0200000 +#define S5P6442_SROMC_BASE 0xE7000000 +#define S5P6442_DMC_BASE 0xE6000000 +#define S5P6442_VIC0_BASE 0xE4000000 +#define S5P6442_VIC1_BASE 0xE4100000 +#define S5P6442_VIC2_BASE 0xE4200000 +#define S5P6442_PWMTIMER_BASE 0xEA000000 +#define S5P6442_WATCHDOG_BASE 0xEA200000 +#define S5P6442_UART_BASE 0xEC000000 + +/* Chip ID */ +#define S5P64XX_PRO_ID 0xE0000000 + +#ifndef __ASSEMBLY__ +/* CPU detection macros */ +extern unsigned int s5p64xx_cpu_id; + +#define IS_SAMSUNG_TYPE(type, id) \ +static inline int cpu_is_##type(void) \ +{ \ + return s5p64xx_cpu_id == id ? 1 : 0; \ +} + +IS_SAMSUNG_TYPE(s5p6442, 0x6442) + +#endif + +#endif /* _S5P6442_CPU_H */ diff --git a/include/asm-arm/arch-s5p64xx/gpio.h b/include/asm-arm/arch-s5p64xx/gpio.h new file mode 100644 index 0000000..0bda7a3 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/gpio.h @@ -0,0 +1,110 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#ifndef __ASSEMBLY__ +struct s5p_gpio_bank { + unsigned int con; + unsigned int dat; + unsigned int pull; + unsigned int drv; + unsigned int pdn_con; + unsigned int pdn_pull; + unsigned char res1[8]; +}; + +struct s5p6442_gpio { + struct s5p_gpio_bank gpio_a0; + struct s5p_gpio_bank gpio_a1; + struct s5p_gpio_bank gpio_b; + struct s5p_gpio_bank gpio_c0; + struct s5p_gpio_bank gpio_c1; + struct s5p_gpio_bank gpio_d0; + struct s5p_gpio_bank gpio_d1; + struct s5p_gpio_bank gpio_e0; + struct s5p_gpio_bank gpio_e1; + struct s5p_gpio_bank gpio_f0; + struct s5p_gpio_bank gpio_f1; + struct s5p_gpio_bank gpio_f2; + struct s5p_gpio_bank gpio_f3; + struct s5p_gpio_bank gpio_g0; + struct s5p_gpio_bank gpio_g1; + struct s5p_gpio_bank gpio_g2; + struct s5p_gpio_bank gpio_j0; + struct s5p_gpio_bank gpio_j1; + struct s5p_gpio_bank gpio_j2; + struct s5p_gpio_bank gpio_j3; + struct s5p_gpio_bank gpio_j4; + struct s5p_gpio_bank gpio_mp0_1; + struct s5p_gpio_bank gpio_mp0_2; + struct s5p_gpio_bank gpio_mp0_3; + struct s5p_gpio_bank gpio_mp0_4; + struct s5p_gpio_bank gpio_mp0_5; + struct s5p_gpio_bank gpio_mp0_6; + struct s5p_gpio_bank gpio_mp0_7; + struct s5p_gpio_bank gpio_mp1_0; + struct s5p_gpio_bank gpio_mp1_1; + struct s5p_gpio_bank gpio_mp1_2; + struct s5p_gpio_bank gpio_mp1_3; + struct s5p_gpio_bank gpio_mp1_4; + struct s5p_gpio_bank gpio_mp1_5; + struct s5p_gpio_bank gpio_mp1_6; + struct s5p_gpio_bank gpio_mp1_7; + struct s5p_gpio_bank gpio_mp1_8; + struct s5p_gpio_bank res1[59]; + struct s5p_gpio_bank gpio_h0; + struct s5p_gpio_bank gpio_h1; + struct s5p_gpio_bank gpio_h2; + struct s5p_gpio_bank gpio_h3; +}; + +/* functions */ +void gpio_cfg_pin(struct s5p_gpio_bank *bank, int gpio, int cfg); +void gpio_direction_output(struct s5p_gpio_bank *bank, int gpio, int enable); +void gpio_direction_input(struct s5p_gpio_bank *bank, int gpio); +void gpio_set_value(struct s5p_gpio_bank *bank, int gpio, int enable); +unsigned int gpio_get_value(struct s5p_gpio_bank *bank, int gpio); +void gpio_set_pull(struct s5p_gpio_bank *bank, int gpio, int mode); +void gpio_set_drv(struct s5p_gpio_bank *bank, int gpio, int mode); +void gpio_set_rate(struct s5p_gpio_bank *bank, int gpio, int mode); +#endif + +/* Pin configurations */ +#define GPIO_INPUT 0x0 +#define GPIO_OUTPUT 0x1 +#define GPIO_IRQ 0xf +#define GPIO_FUNC(x) (x) + +/* Pull mode */ +#define GPIO_PULL_NONE 0x0 +#define GPIO_PULL_DOWN 0x1 +#define GPIO_PULL_UP 0x2 + +/* Drive Strength level */ +#define GPIO_DRV_1x 0x0 +#define GPIO_DRV_2x 0x1 +#define GPIO_DRV_3x 0x2 +#define GPIO_DRV_4x 0x3 +#define GPIO_DRV_FAST 0x0 +#define GPIO_DRV_SLOW 0x1 + +#endif diff --git a/include/asm-arm/arch-s5p64xx/i2c.h b/include/asm-arm/arch-s5p64xx/i2c.h new file mode 100644 index 0000000..35a904a --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/i2c.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * Kyungnin Park + * + * based on s3c24x0_i2c.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_I2C_H_ +#define __ASM_ARCH_I2C_H_ + +/* I2C */ +#define S5PC100_I2C0_BASE 0xEC100000 +#define S5PC100_I2C1_BASE 0xEC200000 +#define S5PC110_I2C0_BASE 0xE1800000 +#define S5PC110_I2C2_BASE 0xE1A00000 + +#ifndef __ASSEMBLY__ +typedef struct s5pc1xx_i2c { + volatile unsigned long IICCON; + volatile unsigned long IICSTAT; + volatile unsigned long IICADD; + volatile unsigned long IICDS; + volatile unsigned long IICLC; +} s5pc1xx_i2c_t; +#endif + +#endif diff --git a/include/asm-arm/arch-s5p64xx/keypad.h b/include/asm-arm/arch-s5p64xx/keypad.h new file mode 100644 index 0000000..97aafb0 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/keypad.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Kyungnin Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_KEYPAD_H_ +#define __ASM_ARCH_KEYPAD_H_ + +/* I2C */ +#define S5PC100_KEYPAD_BASE 0xF3100000 +#define S5PC110_KEYPAD_BASE 0xE1600000 + +#define S5PC1XX_KEYIFCON_OFFSET (0x00) +#define S5PC1XX_KEYIFSTSCLR_OFFSET (0x04) +#define S5PC1XX_KEYIFCOL_OFFSET (0x08) +#define S5PC1XX_KEYIFROW_OFFSET (0x0C) +#define S5PC1XX_KEYIFFC_OFFSET (0x10) + +#endif diff --git a/include/asm-arm/arch-s5p64xx/mem.h b/include/asm-arm/arch-s5p64xx/mem.h new file mode 100644 index 0000000..97c04a0 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/mem.h @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2009 + * Samsung Electronics, + * Heungjun Kim + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARM_ARCH_MEM_H_ +#define __ASM_ARM_ARCH_MEM_H_ + +/* DRAM Memory Controller */ +#define CONCONTROL_OFFSET 0x00 +#define MEMCONTROL_OFFSET 0x04 +#define MEMCONFIG0_OFFSET 0x08 +#define MEMCONFIG1_OFFSET 0x0c +#define DIRECTCMD_OFFSET 0x10 +#define PRECHCONFIG_OFFSET 0x14 +#define PHYCONTROL0_OFFSET 0x18 +#define PHYCONTROL1_OFFSET 0x1c +#define PHYCONTROL2_OFFSET 0x20 +#define PWRDNCONFIG_OFFSET 0x28 +#define TIMINGAREF_OFFSET 0x30 +#define TIMINGROW_OFFSET 0x34 +#define TIMINGDATA_OFFSET 0x38 +#define TIMINGPOWER_OFFSET 0x3c +#define PHYSTATUS0_OFFSET 0x40 +#define PHYSTATUS1_OFFSET 0x44 +#define CHIP0STATUS_OFFSET 0x48 +#define CHIP1STATUS_OFFSET 0x4c +#define AREFSTATUS_OFFSET 0x50 +#define MRSTATUS_OFFSET 0x54 +#define PHYTEST0_OFFSET 0x58 +#define PHYTEST1_OFFSET 0x5c + +#endif diff --git a/include/asm-arm/arch-s5p64xx/mmc.h b/include/asm-arm/arch-s5p64xx/mmc.h new file mode 100644 index 0000000..4efefba --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/mmc.h @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2009 SAMSUNG Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARCH_MMC_H_ +#define __ASM_ARCH_MMC_H_ + +#define S5PC100_MMC_BASE 0xED800000 +#define S5PC110_MMC_BASE 0xEB000000 + +#ifndef __ASSEMBLY__ +struct s5pc1xx_mmc { + unsigned long sysad; + unsigned short blksize; + unsigned short blkcnt; + unsigned long argument; + unsigned short trnmod; + unsigned short cmdreg; + unsigned long rspreg0; + unsigned long rspreg1; + unsigned long rspreg2; + unsigned long rspreg3; + unsigned long bdata; + unsigned long prnsts; + unsigned char hostctl; + unsigned char pwrcon; + unsigned char blkgap; + unsigned char wakcon; + unsigned short clkcon; + unsigned char timeoutcon; + unsigned char swrst; + unsigned short norintsts; + unsigned short errintsts; + unsigned short norintstsen; + unsigned short errintstsen; + unsigned short norintsigen; + unsigned short errintsigen; + unsigned short acmd12errsts; + unsigned char res1[2]; + unsigned long capareg; + unsigned char res2[4]; + unsigned long maxcurr; + unsigned char res3[0x34]; + unsigned long control2; + unsigned long control3; + unsigned long control4; + unsigned char res4[0x6e]; + unsigned short hcver; + unsigned char res5[0xFFF00]; +}; + +struct mmc_host { + struct s5pc1xx_mmc *reg; + unsigned int version; /* SDHCI spec. version */ + unsigned int clock; /* Current clock (MHz) */ +}; + +int s5pc1xx_mmc_init(int dev_index); + +#endif /* __ASSEMBLY__ */ +#endif diff --git a/include/asm-arm/arch-s5p64xx/power.h b/include/asm-arm/arch-s5p64xx/power.h new file mode 100644 index 0000000..6ade0f4 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/power.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2009 Samsung Electronics + * Kyungmin Park + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARM_ARCH_POWER_H_ +#define __ASM_ARM_ARCH_POWER_H_ + +/* + * Power control + */ +#define S5P6442_RST_STAT 0xE010A000 +#define S5P6442_SLEEP_WAKEUP (1 << 16) +#define S5P6442_OSC_CON 0xE0108000 +#define S5P6442_PWR_CFG 0xE010C000 +#define S5P6442_CFG_STANDBYWFI_MASK (0x3 << 8) +#define S5P6442_CFG_STANDBYWFI_IGNORE (0x0 << 8) +#define S5P6442_CFG_STANDBYWFI_IDLE (0x1 << 8) +#define S5P6442_CFG_STANDBYWFI_STOP (0x2 << 8) +#define S5P6442_CFG_STANDBYWFI_SLEEP (0x3 << 8) +#define S5P6442_EINT_WAKEUP_MASK 0xE010C004 +#define S5P6442_WAKEUP_MASK 0xE010C008 +#define S5P6442_PWR_MODE 0xE010C00C +#define S5P6442_PWR_MODE_SLEEP (1 << 2) +#define S5P6442_NORMAL_CFG 0xE010C010 +#define S5P6442_IDLE_CFG 0xE010C020 +#define S5P6442_STOP_CFG 0xE010C030 +#define S5P6442_STOP_MEM_CFG 0xE010C034 +#define S5P6442_SLEEP_CFG 0xE010C040 +#define S5P6442_OSC_FREQ 0xE010C100 +#define S5P6442_OSC_STABLE 0xE010C104 +#define S5P6442_PWR_STABLE 0xE010C108 +#define S5P6442_MTC_STABLE 0xE010C110 +#define S5P6442_CLAMP_STABLE 0xE010C114 +#define S5P6442_WAKEUP_STAT 0xE010C200 +#define S5P6442_OTHERS 0xE010E000 +#define S5P6442_OTHERS_SYSCON_INT_DISABLE (1 << 0) +#define S5P6442_MIE_CONTROL 0xE010E800 +#define S5P6442_HDMI_CONTROL 0xE010E804 +#define S5P6442_USB_PHY_CON 0xE010E80C +#define S5P6442_DAC_CONTROL 0xE010E810 +#define S5P6442_MIPI_DPHY_CONTROL 0xE010E814 +#define S5P6442_ADC_CONTROL 0xE010E818 +#define S5P6442_PS_HOLD_CONTROL 0xE010E81C +#define S5P6442_PS_HOLD_DIR_OUTPUT (1 << 9) +#define S5P6442_PS_HOLD_DIR_INPUT (0 << 9) +#define S5P6442_PS_HOLD_DATA_HIGH (1 << 8) +#define S5P6442_PS_HOLD_DATA_LOW (0 << 8) +#define S5P6442_PS_HOLD_OUT_EN (1 << 0) +#define S5P6442_INFORM0 0xE010F000 +#define S5P6442_INFORM1 0xE010F004 +#define S5P6442_INFORM2 0xE010F008 +#define S5P6442_INFORM3 0xE010F00C +#define S5P6442_INFORM4 0xE010F010 +#define S5P6442_INFORM5 0xE010F014 +#define S5P6442_INFORM6 0xE010F018 +#define S5P6442_INFORM7 0xE010F01C + +#endif diff --git a/include/asm-arm/arch-s5p64xx/pwm.h b/include/asm-arm/arch-s5p64xx/pwm.h new file mode 100644 index 0000000..13b1bb0 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/pwm.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_ARM_ARCH_PWM_H_ +#define __ASM_ARM_ARCH_PWM_H_ + +/* PWM timer addressing */ +#define S5P6442_TIMER_BASE S5P6442_PWMTIMER_BASE + +/* Interval mode(Auto Reload) of PWM Timer 4 */ +#define S5P64XX_TCON4_AUTO_RELOAD (1 << 22) +/* Update TCNTB4 */ +#define S5P64XX_TCON4_UPDATE (1 << 21) +/* start bit of PWM Timer 4 */ +#define S5P64XX_TCON4_START (1 << 20) + +#ifndef __ASSEMBLY__ +struct s5p64xx_timer { + unsigned int tcfg0; + unsigned int tcfg1; + unsigned int tcon; + unsigned int tcntb0; + unsigned int tcmpb0; + unsigned int tcnto0; + unsigned int tcntb1; + unsigned int tcmpb1; + unsigned int tcnto1; + unsigned int tcntb2; + unsigned int tcmpb2; + unsigned int tcnto2; + unsigned int tcntb3; + unsigned int res1; + unsigned int tcnto3; + unsigned int tcntb4; + unsigned int tcnto4; + unsigned int tintcstat; +}; +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/include/asm-arm/arch-s5p64xx/regs-fb.h b/include/asm-arm/arch-s5p64xx/regs-fb.h new file mode 100644 index 0000000..800bb50 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/regs-fb.h @@ -0,0 +1,388 @@ +/* linux/asm/arch/regs-fb.h + * + * Register definition file for Samsung Display Controller (FIMD) driver + * + * Jinsung Yang, Copyright (c) 2009 Samsung Electronics + * http://www.samsungsemi.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef _REGS_FB_H +#define _REGS_FB_H + +#define S5P_LCDREG(x) (x) +#define S5P_WINCON(x) S5P_LCDREG(0x0020 + (x * 0x04)) +#define S5P_VIDOSD_A(x) S5P_LCDREG(0x0040 + (x * 0x10)) +#define S5P_VIDOSD_B(x) S5P_LCDREG(0x0044 + (x * 0x10)) +#define S5P_VIDOSD_C(x) S5P_LCDREG(0x0048 + (x * 0x10)) +#define S5P_VIDOSD_D(x) S5P_LCDREG(0x004C + (x * 0x10)) +#define S5P_VIDADDR_START0(x) S5P_LCDREG(0x00A0 + (x * 0x08)) +#define S5P_VIDADDR_START1(x) S5P_LCDREG(0x00A4 + (x * 0x08)) +#define S5P_VIDADDR_END0(x) S5P_LCDREG(0x00D0 + (x * 0x08)) +#define S5P_VIDADDR_END1(x) S5P_LCDREG(0x00D4 + (x * 0x08)) +#define S5P_VIDADDR_SIZE(x) S5P_LCDREG(0x0100 + (x * 0x04)) +#define S5P_KEYCON(x) S5P_LCDREG(0x0140 + ((x - 1) * 0x08)) +#define S5P_KEYVAL(x) S5P_LCDREG(0x0144 + ((x - 1) * 0x08)) + +/* + * Register Map +*/ +#define S5P_VIDCON0 S5P_LCDREG(0x0000) /* Video control 0 */ +#define S5P_VIDCON1 S5P_LCDREG(0x0004) /* Video control 1 */ +#define S5P_VIDCON2 S5P_LCDREG(0x0008) /* Video control 2 */ +#define S5P_PRTCON S5P_LCDREG(0x000C) /* Protect control */ + +#define S5P_VIDTCON0 S5P_LCDREG(0x0010) /* Video time control 0 */ +#define S5P_VIDTCON1 S5P_LCDREG(0x0014) /* Video time control 1 */ +#define S5P_VIDTCON2 S5P_LCDREG(0x0018) /* Video time control 2 */ + +#define S5P_WINCON0 S5P_LCDREG(0x0020) /* Window control 0 */ +#define S5P_WINCON1 S5P_LCDREG(0x0024) /* Window control 1 */ +#define S5P_WINCON2 S5P_LCDREG(0x0028) /* Window control 2 */ +#define S5P_WINCON3 S5P_LCDREG(0x002C) /* Window control 3 */ +#define S5P_WINCON4 S5P_LCDREG(0x0030) /* Window control 4 */ +#define S5P_WINSHMAP S5P_LCDREG(0x0034) /* Window Shodow control */ +#define S5P_WINCHMAP2 S5P_LCDREG(0x003C) /* Channel mapping control register */ + +#define S5P_VIDOSD0A S5P_LCDREG(0x0040) /* Video Window 0 position control */ +#define S5P_VIDOSD0B S5P_LCDREG(0x0044) /* Video Window 0 position control1 */ +#define S5P_VIDOSD0C S5P_LCDREG(0x0048) /* Video Window 0 position control */ + +#define S5P_VIDOSD1A S5P_LCDREG(0x0050) /* Video Window 1 position control */ +#define S5P_VIDOSD1B S5P_LCDREG(0x0054) /* Video Window 1 position control */ +#define S5P_VIDOSD1C S5P_LCDREG(0x0058) /* Video Window 1 position control */ +#define S5P_VIDOSD1D S5P_LCDREG(0x005C) /* Video Window 1 position control */ + +#define S5P_VIDOSD2A S5P_LCDREG(0x0060) /* Video Window 2 position control */ +#define S5P_VIDOSD2B S5P_LCDREG(0x0064) /* Video Window 2 position control */ +#define S5P_VIDOSD2C S5P_LCDREG(0x0068) /* Video Window 2 position control */ +#define S5P_VIDOSD2D S5P_LCDREG(0x006C) /* Video Window 2 position control */ + +#define S5P_VIDOSD3A S5P_LCDREG(0x0070) /* Video Window 3 position control */ +#define S5P_VIDOSD3B S5P_LCDREG(0x0074) /* Video Window 3 position control */ +#define S5P_VIDOSD3C S5P_LCDREG(0x0078) /* Video Window 3 position control */ + +#define S5P_VIDOSD4A S5P_LCDREG(0x0080) /* Video Window 4 position control */ +#define S5P_VIDOSD4B S5P_LCDREG(0x0084) /* Video Window 4 position control */ +#define S5P_VIDOSD4C S5P_LCDREG(0x0088) /* Video Window 4 position control */ + +#define S5P_VIDW00ADD0B0 S5P_LCDREG(0x00A0) /* Window 0 buffer start address, buffer 0 */ +#define S5P_VIDW00ADD0B1 S5P_LCDREG(0x00A4) /* Window 0 buffer start address, buffer 1 */ +#define S5P_VIDW01ADD0B0 S5P_LCDREG(0x00A8) /* Window 1 buffer start address, buffer 0 */ +#define S5P_VIDW01ADD0B1 S5P_LCDREG(0x00AC) /* Window 1 buffer start address, buffer 1 */ +#define S5P_VIDW02ADD0 S5P_LCDREG(0x00B0) /* Window 2 buffer start address, buffer 0 */ +#define S5P_VIDW03ADD0 S5P_LCDREG(0x00B8) /* Window 3 buffer start address, buffer 0 */ +#define S5P_VIDW04ADD0 S5P_LCDREG(0x00C0) /* Window 4 buffer start address, buffer 0 */ +#define S5P_VIDW00ADD1B0 S5P_LCDREG(0x00D0) /* Window 0 buffer end address, buffer 0 */ +#define S5P_VIDW00ADD1B1 S5P_LCDREG(0x00D4) /* Window 0 buffer end address, buffer 1 */ +#define S5P_VIDW01ADD1B0 S5P_LCDREG(0x00D8) /* Window 1 buffer end address, buffer 0 */ +#define S5P_VIDW01ADD1B1 S5P_LCDREG(0x00DC) /* Window 1 buffer end address, buffer 1 */ +#define S5P_VIDW02ADD1 S5P_LCDREG(0x00E0) /* Window 2 buffer end address */ +#define S5P_VIDW03ADD1 S5P_LCDREG(0x00E8) /* Window 3 buffer end address */ +#define S5P_VIDW04ADD1 S5P_LCDREG(0x00F0) /* Window 4 buffer end address */ +#define S5P_VIDW00ADD2 S5P_LCDREG(0x0100) /* Window 0 buffer size */ +#define S5P_VIDW01ADD2 S5P_LCDREG(0x0104) /* Window 1 buffer size */ +#define S5P_VIDW02ADD2 S5P_LCDREG(0x0108) /* Window 2 buffer size */ +#define S5P_VIDW03ADD2 S5P_LCDREG(0x010C) /* Window 3 buffer size */ +#define S5P_VIDW04ADD2 S5P_LCDREG(0x0110) /* Window 4 buffer size */ + +#define S5P_VP1TCON0 S5P_LCDREG(0x0118) /* VP1 interface timing control 0 */ +#define S5P_VP1TCON1 S5P_LCDREG(0x011C) /* VP1 interface timing control 1 */ + +#define S5P_VIDINTCON0 S5P_LCDREG(0x0130) /* Indicate the Video interrupt control */ +#define S5P_VIDINTCON1 S5P_LCDREG(0x0134) /* Video Interrupt Pending */ + +#define S5P_W1KEYCON0 S5P_LCDREG(0x0140) /* Color key control */ +#define S5P_W1KEYCON1 S5P_LCDREG(0x0144) /* Color key value (transparent value) */ +#define S5P_W2KEYCON0 S5P_LCDREG(0x0148) /* Color key control */ +#define S5P_W2KEYCON1 S5P_LCDREG(0x014C) /* Color key value (transparent value) */ +#define S5P_W3KEYCON0 S5P_LCDREG(0x0150) /* Color key control */ +#define S5P_W3KEYCON1 S5P_LCDREG(0x0154) /* Color key value (transparent value) */ +#define S5P_W4KEYCON0 S5P_LCDREG(0x0158) /* Color key control */ +#define S5P_W4KEYCON1 S5P_LCDREG(0x015C) /* Color key value (transparent value) */ + +#define S5P_W1KEYALPHA S5P_LCDREG(0x0160) /* Color key alpha value */ +#define S5P_W2KEYALPHA S5P_LCDREG(0x0164) /* Color key alpha value */ +#define S5P_W3KEYALPHA S5P_LCDREG(0x0168) /* Color key alpha value */ +#define S5P_W4KEYALPHA S5P_LCDREG(0x016C) /* Color key alpha value */ + +#define S5P_DITHMODE S5P_LCDREG(0x0170) /* Dithering mode */ + +#define S5P_WIN0MAP S5P_LCDREG(0x0180) /* Window color control */ +#define S5P_WIN1MAP S5P_LCDREG(0x0184) /* Window color control */ +#define S5P_WIN2MAP S5P_LCDREG(0x0188) /* Window color control */ +#define S5P_WIN3MAP S5P_LCDREG(0x018C) /* Window color control */ +#define S5P_WIN4MAP S5P_LCDREG(0x0190) /* Window color control */ + +#define S5P_WPALCON_H S5P_LCDREG(0x019C) /* Window Palette control */ +#define S5P_WPALCON_L S5P_LCDREG(0x01A0) /* Window Palette control */ + +#define S5P_VIDW0ALPHA0 S5P_LCDREG(0x0200) /* Window 0 alpha value 0 */ +#define S5P_VIDW0ALPHA1 S5P_LCDREG(0x0204) /* Window 0 alpha value 1 */ +#define S5P_VIDW1ALPHA0 S5P_LCDREG(0x0208) /* Window 1 alpha value 0 */ +#define S5P_VIDW1ALPHA1 S5P_LCDREG(0x020C) /* Window 1 alpha value 1 */ +#define S5P_VIDW2ALPHA0 S5P_LCDREG(0x0210) /* Window 2 alpha value 0 */ +#define S5P_VIDW2ALPHA1 S5P_LCDREG(0x0214) /* Window 2 alpha value 1 */ +#define S5P_VIDW3ALPHA0 S5P_LCDREG(0x0218) /* Window 3 alpha value 0 */ +#define S5P_VIDW3ALPHA1 S5P_LCDREG(0x021C) /* Window 3 alpha value 1 */ +#define S5P_VIDW4ALPHA0 S5P_LCDREG(0x0220) /* Window 4 alpha value 0 */ +#define S5P_VIDW4ALPHA1 S5P_LCDREG(0x0224) /* Window 4 alpha value 1 */ + +#define S5P_BLENDEQ1 S5P_LCDREG(0x0244) /* Window 1 blending equation control */ +#define S5P_BLENDEQ2 S5P_LCDREG(0x0248) /* Window 2 blending equation control */ +#define S5P_BLENDEQ3 S5P_LCDREG(0x024C) /* Window 3 blending equation control */ +#define S5P_BLENDEQ4 S5P_LCDREG(0x0250) /* Window 4 blending equation control */ +#define S5P_BLENDCON S5P_LCDREG(0x0260) /* Blending control */ +#define S5P_DUALRGB S5P_LCDREG(0x027C) /* DUALRGB Interface Setting Register */ + +/* + * Bit Definitions +*/ + +/* VIDCON0 */ +#define S5P_VIDCON0_DSI_DISABLE (0 << 30) +#define S5P_VIDCON0_DSI_ENABLE (1 << 30) +#define S5P_VIDCON0_SCAN_PROGRESSIVE (0 << 29) +#define S5P_VIDCON0_SCAN_INTERLACE (1 << 29) +#define S5P_VIDCON0_SCAN_MASK (1 << 29) +#define S5P_VIDCON0_VIDOUT_RGB (0 << 26) +#define S5P_VIDCON0_VIDOUT_ITU (1 << 26) +#define S5P_VIDCON0_VIDOUT_I80LDI0 (2 << 26) +#define S5P_VIDCON0_VIDOUT_I80LDI1 (3 << 26) +#define S5P_VIDCON0_VIDOUT_MASK (3 << 26) +#define S5P_VIDCON0_PNRMODE_RGB_P (0 << 17) +#define S5P_VIDCON0_PNRMODE_BGR_P (1 << 17) +#define S5P_VIDCON0_PNRMODE_RGB_S (2 << 17) +#define S5P_VIDCON0_PNRMODE_BGR_S (3 << 17) +#define S5P_VIDCON0_PNRMODE_MASK (3 << 17) +#define S5P_VIDCON0_PNRMODE_SHIFT (17) +#define S5P_VIDCON0_CLKVALUP_ALWAYS (0 << 16) +#define S5P_VIDCON0_CLKVALUP_START_FRAME (1 << 16) +#define S5P_VIDCON0_CLKVALUP_MASK (1 << 16) +#define S5P_VIDCON0_CLKVAL_F(x) (((x) & 0xff) << 6) +#define S5P_VIDCON0_VCLKEN_NORMAL (0 << 5) +#define S5P_VIDCON0_VCLKEN_FREERUN (1 << 5) +#define S5P_VIDCON0_VCLKEN_MASK (1 << 5) +#define S5P_VIDCON0_CLKDIR_DIRECTED (0 << 4) +#define S5P_VIDCON0_CLKDIR_DIVIDED (1 << 4) +#define S5P_VIDCON0_CLKDIR_MASK (1 << 4) +#define S5P_VIDCON0_CLKSEL_HCLK (0 << 2) +#define S5P_VIDCON0_CLKSEL_SCLK (1 << 2) +#define S5P_VIDCON0_CLKSEL_MASK (1 << 2) +#define S5P_VIDCON0_ENVID_ENABLE (1 << 1) +#define S5P_VIDCON0_ENVID_DISABLE (0 << 1) +#define S5P_VIDCON0_ENVID_F_ENABLE (1 << 0) +#define S5P_VIDCON0_ENVID_F_DISABLE (0 << 0) + +/* VIDCON1 */ +#define S5P_VIDCON1_IVCLK_FALLING_EDGE (0 << 7) +#define S5P_VIDCON1_IVCLK_RISING_EDGE (1 << 7) +#define S5P_VIDCON1_IHSYNC_NORMAL (0 << 6) +#define S5P_VIDCON1_IHSYNC_INVERT (1 << 6) +#define S5P_VIDCON1_IVSYNC_NORMAL (0 << 5) +#define S5P_VIDCON1_IVSYNC_INVERT (1 << 5) +#define S5P_VIDCON1_IVDEN_NORMAL (0 << 4) +#define S5P_VIDCON1_IVDEN_INVERT (1 << 4) + +/* VIDCON2 */ +#define S5P_VIDCON2_EN601_DISABLE (0 << 23) +#define S5P_VIDCON2_EN601_ENABLE (1 << 23) +#define S5P_VIDCON2_EN601_MASK (1 << 23) +#define S5P_VIDCON2_ORGYUV_YCBCR (0 << 8) +#define S5P_VIDCON2_ORGYUV_CBCRY (1 << 8) +#define S5P_VIDCON2_ORGYUV_MASK (1 << 8) +#define S5P_VIDCON2_YUVORD_CBCR (0 << 7) +#define S5P_VIDCON2_YUVORD_CRCB (1 << 7) +#define S5P_VIDCON2_YUVORD_MASK (1 << 7) + +/* PRTCON */ +#define S5P_PRTCON_UPDATABLE (0 << 11) +#define S5P_PRTCON_PROTECT (1 << 11) + +/* VIDTCON0 */ +#define S5P_VIDTCON0_VBPDE(x) (((x) & 0xff) << 24) +#define S5P_VIDTCON0_VBPD(x) (((x) & 0xff) << 16) +#define S5P_VIDTCON0_VFPD(x) (((x) & 0xff) << 8) +#define S5P_VIDTCON0_VSPW(x) (((x) & 0xff) << 0) + +/* VIDTCON1 */ +#define S5P_VIDTCON1_VFPDE(x) (((x) & 0xff) << 24) +#define S5P_VIDTCON1_HBPD(x) (((x) & 0xff) << 16) +#define S5P_VIDTCON1_HFPD(x) (((x) & 0xff) << 8) +#define S5P_VIDTCON1_HSPW(x) (((x) & 0xff) << 0) + +/* VIDTCON2 */ +#define S5P_VIDTCON2_LINEVAL(x) (((x) & 0x7ff) << 11) +#define S5P_VIDTCON2_HOZVAL(x) (((x) & 0x7ff) << 0) + +/* Window 0~4 Control - WINCONx */ +#define S5P_WINCON_DATAPATH_DMA (0 << 22) +#define S5P_WINCON_DATAPATH_LOCAL (1 << 22) +#define S5P_WINCON_DATAPATH_MASK (1 << 22) +#define S5P_WINCON_BUFSEL_0 (0 << 20) +#define S5P_WINCON_BUFSEL_1 (1 << 20) +#define S5P_WINCON_BUFSEL_MASK (1 << 20) +#define S5P_WINCON_BUFSEL_SHIFT (20) +#define S5P_WINCON_BUFAUTO_DISABLE (0 << 19) +#define S5P_WINCON_BUFAUTO_ENABLE (1 << 19) +#define S5P_WINCON_BUFAUTO_MASK (1 << 19) +#define S5P_WINCON_BITSWP_DISABLE (0 << 18) +#define S5P_WINCON_BITSWP_ENABLE (1 << 18) +#define S5P_WINCON_BITSWP_SHIFT (18) +#define S5P_WINCON_BYTESWP_DISABLE (0 << 17) +#define S5P_WINCON_BYTESWP_ENABLE (1 << 17) +#define S5P_WINCON_BYTESWP_SHIFT (17) +#define S5P_WINCON_HAWSWP_DISABLE (0 << 16) +#define S5P_WINCON_HAWSWP_ENABLE (1 << 16) +#define S5P_WINCON_HAWSWP_SHIFT (16) +#define S5P_WINCON_WSWP_DISABLE (0 << 15) +#define S5P_WINCON_WSWP_ENABLE (1 << 15) +#define S5P_WINCON_WSWP_SHIFT (15) +#define S5P_WINCON_INRGB_RGB (0 << 13) +#define S5P_WINCON_INRGB_YUV (1 << 13) +#define S5P_WINCON_INRGB_MASK (1 << 13) +#define S5P_WINCON_BURSTLEN_16WORD (0 << 9) +#define S5P_WINCON_BURSTLEN_8WORD (1 << 9) +#define S5P_WINCON_BURSTLEN_4WORD (2 << 9) +#define S5P_WINCON_BURSTLEN_MASK (3 << 9) +#define S5P_WINCON_ALPHA_MULTI_DISABLE (0 << 7) +#define S5P_WINCON_ALPHA_MULTI_ENABLE (1 << 7) +#define S5P_WINCON_BLD_PLANE (0 << 6) +#define S5P_WINCON_BLD_PIXEL (1 << 6) +#define S5P_WINCON_BLD_MASK (1 << 6) +#define S5P_WINCON_BPPMODE_1BPP (0 << 2) +#define S5P_WINCON_BPPMODE_2BPP (1 << 2) +#define S5P_WINCON_BPPMODE_4BPP (2 << 2) +#define S5P_WINCON_BPPMODE_8BPP_PAL (3 << 2) +#define S5P_WINCON_BPPMODE_8BPP (4 << 2) +#define S5P_WINCON_BPPMODE_16BPP_565 (5 << 2) +#define S5P_WINCON_BPPMODE_16BPP_A555 (6 << 2) +#define S5P_WINCON_BPPMODE_18BPP_666 (8 << 2) +#define S5P_WINCON_BPPMODE_18BPP_A665 (9 << 2) +#define S5P_WINCON_BPPMODE_24BPP_888 (0xb << 2) +#define S5P_WINCON_BPPMODE_24BPP_A887 (0xc << 2) +#define S5P_WINCON_BPPMODE_32BPP (0xd << 2) +#define S5P_WINCON_BPPMODE_16BPP_A444 (0xe << 2) +#define S5P_WINCON_BPPMODE_15BPP_555 (0xf << 2) +#define S5P_WINCON_BPPMODE_MASK (0xf << 2) +#define S5P_WINCON_BPPMODE_SHIFT (2) +#define S5P_WINCON_ALPHA0_SEL (0 << 1) +#define S5P_WINCON_ALPHA1_SEL (1 << 1) +#define S5P_WINCON_ALPHA_SEL_MASK (1 << 1) +#define S5P_WINCON_ENWIN_DISABLE (0 << 0) +#define S5P_WINCON_ENWIN_ENABLE (1 << 0) + +/* WINSHMAP */ +#define S5P_WINSHMAP_CH_ENABLE(x) (1 << x) +#define S5P_WINSHMAP_CH_DISABLE(x) (0 << x) +#define S5P_WINSHMAP_CH_LOCAL_ENABLE(x) (1 << (x + 5)) +#define S5P_WINSHMAP_CH_LOCAL_DISABLE(x) (0 << (x + 5)) + +/* WINCON1 special */ +#define S5P_WINCON1_VP_DISABLE (0 << 24) +#define S5P_WINCON1_VP_ENABLE (1 << 24) +#define S5P_WINCON1_LOCALSEL_FIMC1 (0 << 23) +#define S5P_WINCON1_LOCALSEL_VP (1 << 23) +#define S5P_WINCON1_LOCALSEL_MASK (1 << 23) + +/* VIDOSDxA, VIDOSDxB */ +#define S5P_VIDOSD_LEFT_X(x) (((x) & 0x7ff) << 11) +#define S5P_VIDOSD_TOP_Y(x) (((x) & 0x7ff) << 0) +#define S5P_VIDOSD_RIGHT_X(x) (((x) & 0x7ff) << 11) +#define S5P_VIDOSD_BOTTOM_Y(x) (((x) & 0x7ff) << 0) + +/* VIDOSD0C, VIDOSDxD */ +#define S5P_VIDOSD_SIZE(x) (((x) & 0xffffff) << 0) + +/* VIDOSDxC (1~4) */ +#define S5P_VIDOSD_ALPHA0_R(x) (((x) & 0xf) << 20) +#define S5P_VIDOSD_ALPHA0_G(x) (((x) & 0xf) << 16) +#define S5P_VIDOSD_ALPHA0_B(x) (((x) & 0xf) << 12) +#define S5P_VIDOSD_ALPHA1_R(x) (((x) & 0xf) << 8) +#define S5P_VIDOSD_ALPHA1_G(x) (((x) & 0xf) << 4) +#define S5P_VIDOSD_ALPHA1_B(x) (((x) & 0xf) << 0) +#define S5P_VIDOSD_ALPHA0_SHIFT (12) +#define S5P_VIDOSD_ALPHA1_SHIFT (0) + +/* Start Address */ +#define S5P_VIDADDR_START_VBANK(x) (((x) & 0xff) << 24) +#define S5P_VIDADDR_START_VBASEU(x) (((x) & 0xffffff) << 0) + +/* End Address */ +#define S5P_VIDADDR_END_VBASEL(x) (((x) & 0xffffff) << 0) + +/* Buffer Size */ +#define S5P_VIDADDR_OFFSIZE(x) (((x) & 0x1fff) << 13) +#define S5P_VIDADDR_PAGEWIDTH(x) (((x) & 0x1fff) << 0) + +/* VIDINTCON0 */ +#define S5P_VIDINTCON0_SYSMAINCON_DISABLE (0 << 19) +#define S5P_VIDINTCON0_SYSMAINCON_ENABLE (1 << 19) +#define S5P_VIDINTCON0_SYSSUBCON_DISABLE (0 << 18) +#define S5P_VIDINTCON0_SYSSUBCON_ENABLE (1 << 18) +#define S5P_VIDINTCON0_SYSIFDONE_DISABLE (0 << 17) +#define S5P_VIDINTCON0_SYSIFDONE_ENABLE (1 << 17) +#define S5P_VIDINTCON0_FRAMESEL0_BACK (0 << 15) +#define S5P_VIDINTCON0_FRAMESEL0_VSYNC (1 << 15) +#define S5P_VIDINTCON0_FRAMESEL0_ACTIVE (2 << 15) +#define S5P_VIDINTCON0_FRAMESEL0_FRONT (3 << 15) +#define S5P_VIDINTCON0_FRAMESEL0_MASK (3 << 15) +#define S5P_VIDINTCON0_FRAMESEL1_NONE (0 << 13) +#define S5P_VIDINTCON0_FRAMESEL1_BACK (1 << 13) +#define S5P_VIDINTCON0_FRAMESEL1_VSYNC (2 << 13) +#define S5P_VIDINTCON0_FRAMESEL1_FRONT (3 << 13) +#define S5P_VIDINTCON0_INTFRMEN_DISABLE (0 << 12) +#define S5P_VIDINTCON0_INTFRMEN_ENABLE (1 << 12) +#define S5P_VIDINTCON0_FIFOSEL_WIN4 (1 << 11) +#define S5P_VIDINTCON0_FIFOSEL_WIN3 (1 << 10) +#define S5P_VIDINTCON0_FIFOSEL_WIN2 (1 << 9) +#define S5P_VIDINTCON0_FIFOSEL_WIN1 (1 << 6) +#define S5P_VIDINTCON0_FIFOSEL_WIN0 (1 << 5) +#define S5P_VIDINTCON0_FIFOSEL_ALL (0x73 << 5) +#define S5P_VIDINTCON0_FIFOSEL_MASK (0x73 << 5) +#define S5P_VIDINTCON0_FIFOLEVEL_25 (0 << 2) +#define S5P_VIDINTCON0_FIFOLEVEL_50 (1 << 2) +#define S5P_VIDINTCON0_FIFOLEVEL_75 (2 << 2) +#define S5P_VIDINTCON0_FIFOLEVEL_EMPTY (3 << 2) +#define S5P_VIDINTCON0_FIFOLEVEL_FULL (4 << 2) +#define S5P_VIDINTCON0_FIFOLEVEL_MASK (7 << 2) +#define S5P_VIDINTCON0_INTFIFO_DISABLE (0 << 1) +#define S5P_VIDINTCON0_INTFIFO_ENABLE (1 << 1) +#define S5P_VIDINTCON0_INT_DISABLE (0 << 0) +#define S5P_VIDINTCON0_INT_ENABLE (1 << 0) +#define S5P_VIDINTCON0_INT_MASK (1 << 0) + +/* VIDINTCON1 */ +#define S5P_VIDINTCON1_INTVPPEND (1 << 5) +#define S5P_VIDINTCON1_INTI80PEND (1 << 2) +#define S5P_VIDINTCON1_INTFRMPEND (1 << 1) +#define S5P_VIDINTCON1_INTFIFOPEND (1 << 0) + +/* WxKEYCON0 (1~4) */ +#define S5P_KEYCON0_KEYBLEN_DISABLE (0 << 26) +#define S5P_KEYCON0_KEYBLEN_ENABLE (1 << 26) +#define S5P_KEYCON0_KEY_DISABLE (0 << 25) +#define S5P_KEYCON0_KEY_ENABLE (1 << 25) +#define S5P_KEYCON0_DIRCON_MATCH_FG (0 << 24) +#define S5P_KEYCON0_DIRCON_MATCH_BG (1 << 24) +#define S5P_KEYCON0_COMPKEY(x) (((x) & 0xffffff) << 0) + +/* WxKEYCON1 (1~4) */ +#define S5P_KEYCON1_COLVAL(x) (((x) & 0xffffff) << 0) + +/* DUALRGB */ +#define S5P_DUALRGB_BYPASS_SINGLE (0x00 << 0) +#define S5P_DUALRGB_BYPASS_DUAL (0x01 << 0) +#define S5P_DUALRGB_MIE_DUAL (0x10 << 0) +#define S5P_DUALRGB_MIE_SINGLE (0x11 << 0) +#define S5P_DUALRGB_LINESPLIT (0x0 << 2) +#define S5P_DUALRGB_FRAMESPLIT (0x1 << 2) +#define S5P_DUALRGB_SUB_CNT(x) ((x & 0xfff) << 4) +#define S5P_DUALRGB_VDEN_EN_DISABLE (0x0 << 16) +#define S5P_DUALRGB_VDEN_EN_ENABLE (0x1 << 16) +#define S5P_DUALRGB_MAIN_CNT(x) ((x & 0xfff) << 18) + +#endif /* _REGS_FB_H */ diff --git a/include/asm-arm/arch-s5p64xx/sys_proto.h b/include/asm-arm/arch-s5p64xx/sys_proto.h new file mode 100644 index 0000000..3078aaf --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/sys_proto.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2009 Samsung Electrnoics + * Minkyu Kang + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _SYS_PROTO_H_ +#define _SYS_PROTO_H_ + +u32 get_device_type(void); +void invalidate_dcache(u32); +void l2_cache_disable(void); +void l2_cache_enable(void); + +#endif diff --git a/include/asm-arm/arch-s5p64xx/uart.h b/include/asm-arm/arch-s5p64xx/uart.h new file mode 100644 index 0000000..122bf0c --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/uart.h @@ -0,0 +1,46 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARCH_UART_H_ +#define __ASM_ARCH_UART_H_ + +#ifndef __ASSEMBLY__ +struct s5pc1xx_uart { + unsigned int ulcon; + unsigned int ucon; + unsigned int ufcon; + unsigned int umcon; + unsigned int utrstat; + unsigned int uerstat; + unsigned int ufstat; + unsigned int umstat; + unsigned char utxh; + unsigned char res1[3]; + unsigned char urxh; + unsigned char res2[3]; + unsigned int ubrdiv; + unsigned short udivslot; + unsigned char res3[2]; + unsigned char res4[0x3d0]; +}; +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/include/asm-arm/arch-s5p64xx/usb-hs-otg.h b/include/asm-arm/arch-s5p64xx/usb-hs-otg.h new file mode 100644 index 0000000..4df1081 --- /dev/null +++ b/include/asm-arm/arch-s5p64xx/usb-hs-otg.h @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#ifndef __ASM_ARCH_USB_HS_OTG_H_ +#define __ASM_ARCH_USB_HS_OTG_H_ + +/* + * USB2.0 HS OTG + */ +#define S5PC100_OTG_BASE 0xED200000 +#define S5PC100_PHY_BASE 0xED300000 + +#define S5PC110_OTG_BASE 0xEC000000 +#define S5PC110_PHY_BASE 0xEC100000 + +/* Core Global Registers */ +#define OTG_GOTGCTL 0x000 +#define OTG_GOTGINT 0x004 +#define OTG_GAHBCFG 0x008 +#define OTG_GUSBCFG 0x00C +#define OTG_GRSTCTL 0x010 +#define OTG_GINTSTS 0x014 +#define OTG_GINTMSK 0x018 +#define OTG_GRXSTSR 0x01C +#define OTG_GRXSTSP 0x020 +#define OTG_GRXFSIZ 0x024 +#define OTG_GNPTXFSIZ 0x028 +#define OTG_GNPTXSTS 0x02C + +#define OTG_HPTXFSIZ 0x100 +#define OTG_DPTXFSIZ1 0x104 +#define OTG_DPTXFSIZ2 0x108 +#define OTG_DPTXFSIZ3 0x10C +#define OTG_DPTXFSIZ4 0x110 +#define OTG_DPTXFSIZ5 0x114 +#define OTG_DPTXFSIZ6 0x118 +#define OTG_DPTXFSIZ7 0x11C +#define OTG_DPTXFSIZ8 0x120 +#define OTG_DPTXFSIZ9 0x124 +#define OTG_DPTXFSIZ10 0x128 +#define OTG_DPTXFSIZ11 0x12C +#define OTG_DPTXFSIZ12 0x130 +#define OTG_DPTXFSIZ13 0x134 +#define OTG_DPTXFSIZ14 0x138 +#define OTG_DPTXFSIZ15 0x13C + +/* Host Global Registers */ +#define OTG_HCFG 0x400 +#define OTG_HFIR 0x404 +#define OTG_HFNUM 0x408 +#define OTG_HPTXSTS 0x410 +#define OTG_HAINT 0x414 +#define OTG_HAINTMSK 0x418 + +/* Host Port Control & Status Registers */ +#define OTG_HPRT 0x440 + +/* Host Channel-Specific Registers */ +#define OTG_HCCHAR0 0x500 +#define OTG_HCSPLT0 0x504 +#define OTG_HCINT0 0x508 +#define OTG_HCINTMSK0 0x50C +#define OTG_HCTSIZ0 0x510 +#define OTG_HCDMA0 0x514 + +/* Device Global Registers */ +#define OTG_DCFG 0x800 +#define OTG_DCTL 0x804 +#define OTG_DSTS 0x808 +#define OTG_DIEPMSK 0x810 +#define OTG_DOEPMSK 0x814 +#define OTG_DAINT 0x818 +#define OTG_DAINTMSK 0x81C +#define OTG_DTKNQR1 0x820 +#define OTG_DTKNQR2 0x824 +#define OTG_DVBUSDIS 0x828 +#define OTG_DVBUSPULSE 0x82C +#define OTG_DTKNQR3 0x830 +#define OTG_DTKNQR4 0x834 + +/* Device Logical IN Endpoint-Specific Registers */ +#define OTG_DIEPCTL0 0x900 +#define OTG_DIEPINT0 0x908 +#define OTG_DIEPTSIZ0 0x910 +#define OTG_DIEPDMA0 0x914 + +/* Device Logical OUT Endpoint-Specific Registers */ +#define OTG_DOEPCTL0 0xB00 +#define OTG_DOEPINT0 0xB08 +#define OTG_DOEPTSIZ0 0xB10 +#define OTG_DOEPDMA0 0xB14 + +/* Power & clock gating registers */ +#define OTG_PCGCCTRL 0xE00 + +/* Endpoint FIFO address */ +#define OTG_EP0_FIFO 0x1000 + +/* OTG PHY CORE REGISTERS */ +#define OTG_PHYPWR 0x0 +#define OTG_PHYCTRL 0x4 +#define OTG_RSTCON 0x8 + +#endif diff --git a/include/configs/smdk6442.h b/include/configs/smdk6442.h new file mode 100644 index 0000000..4759983 --- /dev/null +++ b/include/configs/smdk6442.h @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2009 Samsung Electronics + * Minkyu Kang + * + * Configuation settings for the SAMSUNG board. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_SAMSUNG 1 /* in a SAMSUNG core */ +#define CONFIG_S5P64XX 1 /* which is in a S5P64XX Family */ +#define CONFIG_S5P6442 1 /* which is in a S5P6442 */ + +#include /* get chip and board defs */ + +#define CONFIG_ARCH_CPU_INIT + +#define CONFIG_SYS_SDRAM_BASE 0x20000000 + +/* input clock of PLL: Universal has 12MHz/24MHz input clock at S5PC100/C110 */ +#define CONFIG_SYS_CLK_FREQ_6442 12000000 + +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_CMDLINE_TAG +#define CONFIG_INITRD_TAG +//#define CONFIG_REVISION_TAG + +/* + * Architecture magic and machine type + */ +#define CONFIG_DISPLAY_CPUINFO + +#undef CONFIG_SKIP_RELOCATE_UBOOT + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 1024 * 1024) +#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes for initial data */ + +/* + * select serial console configuration + */ +#define CONFIG_SERIAL_MULTI 1 +#define CONFIG_SERIAL2 1 /* we use SERIAL 2 on S5PC100 */ + +#if 0 +/* MMC */ +#define CONFIG_GENERIC_MMC 1 +#define CONFIG_MMC 1 +#define CONFIG_S5PC1XX_MMC 1 +#define CONFIG_MMC_INDEX 0 +#endif + +#define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */ +#ifdef CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " +#endif + +#define CONFIG_CMDLINE_EDITING + +#define CONFIG_BAUDRATE 115200 + +/* It should define before config_cmd_default.h */ +#define CONFIG_SYS_NO_FLASH 1 +/*********************************************************** + * Command definition + ***********************************************************/ +#include + +#undef CONFIG_CMD_LOADB +#undef CONFIG_CMD_LOADS +#undef CONFIG_CMD_BOOTD +#undef CONFIG_CMD_FPGA +#undef CONFIG_CMD_XIMG +#undef CONFIG_CMD_NAND +#undef CONFIG_CMD_IMLS +#undef CONFIG_CMD_FLASH +#undef CONFIG_CMD_IMLS +#undef CONFIG_CMD_NET +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_REGINFO +#define CONFIG_CMD_ONENAND +#define CONFIG_CMD_MTDPARTS +#if 0 +#define CONFIG_CMD_I2C +#define CONFIG_CMD_MMC +#define CONFIG_CMD_SLEEP +#define CONFIG_CMD_GPIO +#define CONFIG_CMD_PMIC +#define CONFIG_CMD_DEVICE_POWER +#endif + +#define CONFIG_SYS_64BIT_VSPRINTF 1 + +#define CONFIG_BOOTDELAY 1 + +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_IPADDR 192.168.129.3 +#define CONFIG_SERVERIP 192.168.129.1 +#define CONFIG_GATEWAYIP 192.168.129.1 +#define CONFIG_ETHADDR 00:0E:99:34:10:00 + +#define CONFIG_MTD_DEVICE +#define CONFIG_MTD_PARTITIONS + +/* Actual modem binary size is 16MiB. Add 2MiB for bad block handling */ +#define MTDIDS_DEFAULT "onenand0=samsung-onenand" +#define MTDPARTS_DEFAULT "mtdparts=samsung-onenand:256k(bootloader)"\ + ",128k(params)"\ + ",3m(kernel)"\ + ",18m(modem)"\ + ",7m(fota)"\ + ",9m(log)"\ + ",-(UBI)\0" + +#define MTDPARTS_DEFAULT_4KB "mtdparts=samsung-onenand:256k(bootloader)"\ + ",256k(params)"\ + ",3m(kernel)"\ + ",18m(modem)"\ + ",7m(fota)"\ + ",9m(log)"\ + ",-(UBI)\0" + +#define NORMAL_MTDPARTS_DEFAULT MTDPARTS_DEFAULT + +#define CONFIG_BOOTCOMMAND "run ubifsboot" + +#define CONFIG_RAMDISK_BOOT "root=/dev/ram0 rw rootfstype=ext2" \ + " console=ttySAC2,115200n8" \ + " ${meminfo}" + +#define CONFIG_COMMON_BOOT "console=ttySAC2,115200n8" \ + " ${meminfo}" \ + " ${mtdparts}" + +#define CONFIG_BOOTARGS "root=/dev/mtdblock7 ubi.mtd=6" \ + " rootfstype=cramfs " CONFIG_COMMON_BOOT + +#define CONFIG_UPDATEB "updateb=onenand erase 0x0 0x40000;" \ + " onenand write 0x32008000 0x0 0x40000\0" + +#define CONFIG_ENV_OVERWRITE +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_UPDATEB \ + "updatek=onenand erase 0x80000 0x300000;" \ + " onenand write 0x31008000 0x80000 0x300000\0" \ + "updateu=onenand erase 0x01560000 0x1eaa0000;" \ + " onenand write 0x32000000 0x1260000 0x8C0000\0" \ + "bootk=onenand read 0x30007FC0 0x80000 0x300000;" \ + " bootm 0x30007FC0\0" \ + "flashboot=set bootargs root=/dev/mtdblock${bootblock}" \ + " rootfstype=${rootfstype}" \ + " ubi.mtd=${ubiblock} ${opts} ${lcdinfo} " CONFIG_COMMON_BOOT "; run bootk\0" \ + "ubifsboot=set bootargs root=ubi0!rootfs rootfstype=ubifs" \ + " ubi.mtd=${ubiblock} ${opts} ${lcdinfo} " CONFIG_COMMON_BOOT "; run bootk\0" \ + "boottrace=setenv opts initcall_debug; run bootcmd\0" \ + "android=set bootargs root=ubi0!ramdisk ubi.mtd=${ubiblock}" \ + " rootfstype=ubifs init=/init.sh " CONFIG_COMMON_BOOT "; run bootk\0" \ + "nfsboot=set bootargs root=/dev/nfs rw ubi.mtd=${ubiblock}" \ + " nfsroot=${nfsroot},nolock,tcp ip=${ipaddr}:${serverip}:${gatewayip}:" \ + "${netmask}:generic:usb0:off " CONFIG_COMMON_BOOT "; run bootk\0" \ + "ramboot=set bootargs " CONFIG_RAMDISK_BOOT \ + " initrd=0x33000000,8M ramdisk=8192\0" \ + "mmcboot=set bootargs root=${mmcblk} rootfstype=${rootfstype}" \ + " ubi.mtd=${ubiblock} ${opts} ${lcdinfo} " CONFIG_COMMON_BOOT "; run bootk\0" \ + "verify=n\0" \ + "rootfstype=cramfs\0" \ + "mtdparts=" MTDPARTS_DEFAULT \ + "meminfo=mem=80M mem=128M@0x40000000\0" \ + "nfsroot=/nfsroot/arm\0" \ + "mmcblk=/dev/mmcblk1p1\0" \ + "bootblock=7\0" \ + "ubiblock=6\0" \ + "ubi=enabled" + +/* + * Miscellaneous configurable options + */ +#define CONFIG_SYS_LONGHELP /* undef to save memory */ +#define CONFIG_SYS_PROMPT "6442 # " /* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PBSIZE 384 /* Print Buffer Size */ +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ + +#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE /* memtest works on */ +#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x5000000) + +#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x4800000) + +#define CONFIG_SYS_HZ 1000 + +/* valid baudrates */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* base address for uboot */ +#define CONFIG_SYS_PHY_UBOOT_BASE (CONFIG_SYS_SDRAM_BASE + 0x04800000) + +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (256 << 10) /* regular stack 256KB */ + +/******************************* + Support Clock Settings(APLL) + ******************************* + ARMCLK HCLKD0 PCLKD0 + ------------------------------- + 667 166 83 + 600 150 75 + 533 133 66 + 500 166 66 + 467 117 59 + 400 100 50 + *******************************/ + +#define CONFIG_CLK_667_166_83 +/*#define CONFIG_CLK_666_166_66*/ +/*#define CONFIG_CLK_600_150_75*/ +/*#define CONFIG_CLK_533_133_66*/ +/*#define CONFIG_CLK_500_166_66*/ +/*#define CONFIG_CLK_467_117_59*/ +/*#define CONFIG_CLK_400_100_50*/ + +/* Universal has 2 banks of DRAM, but swap the bank */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE /* OneDRAM Bank #0 */ +#define PHYS_SDRAM_1_SIZE (80 << 20) /* 80 MB in Bank #0 */ + +#define CONFIG_SYS_MONITOR_BASE 0x00000000 + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ + +#define CONFIG_SYS_MONITOR_LEN (256 << 10) /* Reserve 2 sectors */ + +/* OneNAND IPL uses 8KiB */ +#define CONFIG_ONENAND_START_PAGE 4 + +#define CONFIG_ENV_IS_IN_ONENAND 1 +#define CONFIG_ENV_SIZE (256 << 10) /* 256 KiB, 0x40000 */ +#define CONFIG_ENV_ADDR (256 << 10) /* 256 KiB, 0x40000 */ +#define CONFIG_ENV_OFFSET (256 << 10) /* 256 KiB, 0x40000 */ + +#define CONFIG_USE_ONENAND_BOARD_INIT +#define CONFIG_SAMSUNG_ONENAND 1 +#define CONFIG_SYS_ONENAND_BASE 0xB0000000 + +#define CONFIG_DOS_PARTITION 1 + +//#define CONFIG_MISC_INIT_R + +#if 0 +/* I2C */ +#if 0 +#define CONFIG_DRIVER_S5PC1XX_I2C +#define CONFIG_HARD_I2C 1 +#define CONFIG_SYS_I2C_SPEED 50000 +#define CONFIG_SYS_I2C_SLAVE 0xFE +#define CONFIG_SYS_I2C_0 1 +#else +#include +#define CONFIG_SOFT_I2C 1 +#define CONFIG_SYS_I2C_INIT_BOARD +#define CONFIG_SYS_I2C_SPEED 50000 +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_SYS_MAX_I2C_BUS 6 +#endif + +/* USB Downloader */ +#define CONFIG_CMD_USBDOWN +#define CONFIG_SAMSUNG_USB +#define CONFIG_OTG_CLK_OSCC +#define CONFIG_SYS_DOWN_ADDR CONFIG_SYS_SDRAM_BASE +#define CONFIG_RAMDISK_ADDR (CONFIG_SYS_SDRAM_BASE + 0x03000000) + +/* LCD */ +#if 1 /* For LCD test */ +#define CONFIG_LCD 1 +#define CONFIG_S5PC1XXFB 1 +#endif + +#if 0 +#define CONFIG_CMD_EXT2 1 +#define CONFIG_CMD_ONENAND_EXT2 1 +#endif +#endif + +#endif /* __CONFIG_H */ diff --git a/include/serial.h b/include/serial.h index f2638ec..eadcc68 100644 --- a/include/serial.h +++ b/include/serial.h @@ -43,7 +43,7 @@ extern struct serial_device s3c24xx_serial1_device; extern struct serial_device s3c24xx_serial2_device; #endif -#if defined(CONFIG_S5PC1XX) +#if defined(CONFIG_S5PC1XX) || defined(CONFIG_S5P64XX) extern struct serial_device s5pc1xx_serial0_device; extern struct serial_device s5pc1xx_serial1_device; extern struct serial_device s5pc1xx_serial2_device; -- 2.7.4