From a08ab63761730634bbbf8f361d1a058c1f4af9c5 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:06:39 +0100 Subject: [ARM] S3C64XX: Initial arch directory Add the initial PLAT_S3C64XX support files and directory structure. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/Makefile (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile new file mode 100644 index 00000000000..900c86367e1 --- /dev/null +++ b/arch/arm/plat-s3c64xx/Makefile @@ -0,0 +1,13 @@ +# arch/arm/plat-s3c64xx/Makefile +# +# Copyright 2008 Openmoko, Inc. +# Copyright 2008 Simtec Electronics +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := dummy.o +obj- := + +# Core files -- cgit v1.2.3-70-g09d2 From 0241cbb9d62613f6952d023a04d565901a3ca1ad Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:06:46 +0100 Subject: [ARM] S3C64XX: Add UARTdevice definitions Add resources and information for the UART deviecs on the S3C64XX CPUs. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c/include/plat/devs.h | 1 + arch/arm/plat-s3c64xx/Makefile | 2 + arch/arm/plat-s3c64xx/dev-uart.c | 176 ++++++++++++++++++++++++++++++ arch/arm/plat-s3c64xx/include/plat/irqs.h | 35 +++++- 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 arch/arm/plat-s3c64xx/dev-uart.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h index badaac9d64a..a689c7c5ac2 100644 --- a/arch/arm/plat-s3c/include/plat/devs.h +++ b/arch/arm/plat-s3c/include/plat/devs.h @@ -17,6 +17,7 @@ struct s3c24xx_uart_resources { }; extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; +extern struct s3c24xx_uart_resources s3c64xx_uart_resources[]; extern struct platform_device *s3c24xx_uart_devs[]; extern struct platform_device *s3c24xx_uart_src[]; diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 900c86367e1..178c968bb8d 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -11,3 +11,5 @@ obj-n := dummy.o obj- := # Core files + +obj-y += dev-uart.o diff --git a/arch/arm/plat-s3c64xx/dev-uart.c b/arch/arm/plat-s3c64xx/dev-uart.c new file mode 100644 index 00000000000..62c11a6fc7b --- /dev/null +++ b/arch/arm/plat-s3c64xx/dev-uart.c @@ -0,0 +1,176 @@ +/* linux/arch/arm/plat-s3c64xx/dev-uart.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX UART resource and device definitions + * + * 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 + +/* Serial port registrations */ + +/* 64xx uarts are closer together */ + +static struct resource s3c64xx_uart0_resource[] = { + [0] = { + .start = S3C_PA_UART0, + .end = S3C_PA_UART0 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX0, + .end = IRQ_S3CUART_RX0, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX0, + .end = IRQ_S3CUART_TX0, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR0, + .end = IRQ_S3CUART_ERR0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource s3c64xx_uart1_resource[] = { + [0] = { + .start = S3C_PA_UART1, + .end = S3C_PA_UART1 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX1, + .end = IRQ_S3CUART_RX1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX1, + .end = IRQ_S3CUART_TX1, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR1, + .end = IRQ_S3CUART_ERR1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s3c6xx_uart2_resource[] = { + [0] = { + .start = S3C_PA_UART2, + .end = S3C_PA_UART2 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX2, + .end = IRQ_S3CUART_RX2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX2, + .end = IRQ_S3CUART_TX2, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR2, + .end = IRQ_S3CUART_ERR2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s3c64xx_uart3_resource[] = { + [0] = { + .start = S3C_PA_UART3, + .end = S3C_PA_UART3 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX3, + .end = IRQ_S3CUART_RX3, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX3, + .end = IRQ_S3CUART_TX3, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR3, + .end = IRQ_S3CUART_ERR3, + .flags = IORESOURCE_IRQ, + }, +}; + + +struct s3c24xx_uart_resources s3c64xx_uart_resources[] __initdata = { + [0] = { + .resources = s3c64xx_uart0_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart0_resource), + }, + [1] = { + .resources = s3c64xx_uart1_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart1_resource), + }, + [2] = { + .resources = s3c6xx_uart2_resource, + .nr_resources = ARRAY_SIZE(s3c6xx_uart2_resource), + }, + [3] = { + .resources = s3c64xx_uart3_resource, + .nr_resources = ARRAY_SIZE(s3c64xx_uart3_resource), + }, +}; + +/* uart devices */ + +static struct platform_device s3c24xx_uart_device0 = { + .id = 0, +}; + +static struct platform_device s3c24xx_uart_device1 = { + .id = 1, +}; + +static struct platform_device s3c24xx_uart_device2 = { + .id = 2, +}; + +static struct platform_device s3c24xx_uart_device3 = { + .id = 3, +}; + +struct platform_device *s3c24xx_uart_src[4] = { + &s3c24xx_uart_device0, + &s3c24xx_uart_device1, + &s3c24xx_uart_device2, + &s3c24xx_uart_device3, +}; + +struct platform_device *s3c24xx_uart_devs[4] = { +}; + diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h index 592a5635455..0f207ab2df2 100644 --- a/arch/arm/plat-s3c64xx/include/plat/irqs.h +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h @@ -15,12 +15,45 @@ * the ISA space, so that the PC104 has them to itself * and we don't end up having to do horrible things to the * standard ISA drivers.... + * + * note, since we're using the VICs, our start must be a + * mulitple of 32 to allow the common code to work */ -#define S3C_IRQ_OFFSET (16) +#define S3C_IRQ_OFFSET (32) #define S3C_IRQ(x) ((x) + S3C_IRQ_OFFSET) +/* UART interrupts, each UART has 4 intterupts per channel so + * use the space between the ISA and S3C main interrupts. Note, these + * are not in the same order as the S3C24XX series! */ + +#define IRQ_S3CUART_BASE0 (16) +#define IRQ_S3CUART_BASE1 (20) +#define IRQ_S3CUART_BASE2 (24) +#define IRQ_S3CUART_BASE3 (28) + +#define UART_IRQ_RXD (0) +#define UART_IRQ_ERR (1) +#define UART_IRQ_TXD (2) +#define UART_IRQ_MODEM (3) + +#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) + /* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE * which we place after the pair of VICs. */ -- cgit v1.2.3-70-g09d2 From beda30f6a9c5f8e1eebd195019a537057cc556fd Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:06:49 +0100 Subject: [ARM] S3C64XX: Basic CPU detection and map initialisation Initialise the basic physical to virtual mappings and then detect the CPU that the system is being run on so that the cpu code code can call the correct initialisation code. Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6400/include/mach/map.h | 1 + arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/cpu.c | 106 +++++++++++++++++++++++++++ arch/arm/plat-s3c64xx/include/plat/s3c6400.h | 33 +++++++++ arch/arm/plat-s3c64xx/include/plat/s3c6410.h | 28 +++++++ 5 files changed, 169 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/cpu.c create mode 100644 arch/arm/plat-s3c64xx/include/plat/s3c6400.h create mode 100644 arch/arm/plat-s3c64xx/include/plat/s3c6410.h (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h index 0ee6be08e74..de6cdd518ce 100644 --- a/arch/arm/mach-s3c6400/include/mach/map.h +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -24,6 +24,7 @@ #define S3C_PA_UART3 (S3C_PA_UART + 0xC00) #define S3C_UART_OFFSET (0x400) +#define S3C64XX_PA_SYSCON (0x7E00F000) #define S3C64XX_PA_TIMER (0x7F006000) #define S3C64XX_PA_SDRAM (0x50000000) diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 178c968bb8d..5d9a1d86ab8 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -13,3 +13,4 @@ obj- := # Core files obj-y += dev-uart.o +obj-y += cpu.o diff --git a/arch/arm/plat-s3c64xx/cpu.c b/arch/arm/plat-s3c64xx/cpu.c new file mode 100644 index 00000000000..dc7bf112ec0 --- /dev/null +++ b/arch/arm/plat-s3c64xx/cpu.c @@ -0,0 +1,106 @@ +/* linux/arch/arm/plat-s3c64xx/cpu.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX CPU Support + * + * 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 + +#include + +#include +#include +#include + +#include +#include + +/* table of supported CPUs */ + +static const char name_s3c6400[] = "S3C6400"; +static const char name_s3c6410[] = "S3C6410"; + +static struct cpu_table cpu_ids[] __initdata = { + { + .idcode = 0x36400000, + .idmask = 0xfffff000, + .map_io = s3c6400_map_io, + .init_clocks = s3c6400_init_clocks, + .init_uarts = s3c6400_init_uarts, + .init = s3c6400_init, + .name = name_s3c6400, + }, { + .idcode = 0x36410100, + .idmask = 0xffffff00, + .map_io = s3c6410_map_io, + .init_clocks = s3c6410_init_clocks, + .init_uarts = s3c6410_init_uarts, + .init = s3c6410_init, + .name = name_s3c6410, + }, +}; + +/* minimal IO mapping */ + +/* see notes on uart map in arch/arm/mach-s3c6400/include/mach/debug-macro.S */ +#define UART_OFFS (S3C_PA_UART & 0xfffff) + +static struct map_desc s3c_iodesc[] __initdata = { + { + .virtual = S3C_VA_SYS, + .pfn = __phys_to_pfn(S3C64XX_PA_SYSCON), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)(S3C_VA_UART + UART_OFFS), + .pfn = __phys_to_pfn(S3C_PA_UART), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = S3C_VA_VIC0, + .pfn = __phys_to_pfn(S3C64XX_PA_VIC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = S3C_VA_VIC1, + .pfn = __phys_to_pfn(S3C64XX_PA_VIC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, +}; + +/* read cpu identification code */ + + +void __init s3c64xx_init_io(struct map_desc *mach_desc, int size) +{ + unsigned long idcode; + + /* initialise the io descriptors we need for initialisation */ + iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); + iotable_init(mach_desc, size); + + idcode = __raw_readl(S3C_VA_SYS + 0x118); + s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); +} diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h new file mode 100644 index 00000000000..142bb3d18cd --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h @@ -0,0 +1,33 @@ +/* arch/arm/plat-s3c64xx/include/plat/s3c6400.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Header file for s3c6400 cpu support + * + * 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. +*/ + +/* Common init code for S3C6400 related SoCs */ + +extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +#ifdef CONFIG_CPU_S3C6400 + +extern int s3c6400_init(void); +extern void s3c6400_map_io(void); +extern void s3c6400_init_clocks(int xtal); + +#define s3c6400_init_uarts s3c6400_common_init_uarts + +#else +#define s3c6400_init_clocks NULL +#define s3c6400_init_uarts NULL +#define s3c6400_map_io NULL +#define s3c6400_init NULL +#endif + diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h new file mode 100644 index 00000000000..56f14b5d454 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h @@ -0,0 +1,28 @@ +/* arch/arm/plat-s3c64xx/include/plat/s3c6410.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Header file for s3c6410 cpu support + * + * 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. +*/ + +#ifdef CONFIG_CPU_S3C6410 + +extern int s3c6410_init(void); +extern void s3c6410_map_io(void); +extern void s3c6410_init_clocks(int xtal); + +#define s3c6410_init_uarts s3c6400_common_init_uarts + +#else +#define s3c6410_init_clocks NULL +#define s3c6410_init_uarts NULL +#define s3c6410_map_io NULL +#define s3c6410_init NULL +#endif -- cgit v1.2.3-70-g09d2 From d9b79fb56829de34eaddb01b405216eddd0d3b10 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:06:51 +0100 Subject: [ARM] S3C64XX: Add VIC0 and VIC1 sourced interripts Add and initialise the two VIC (PL192) found on the S3C64XX series CPUs. Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6410/cpu.c | 6 +++++ arch/arm/plat-s3c/include/plat/cpu.h | 1 + arch/arm/plat-s3c64xx/Kconfig | 1 + arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/include/plat/irqs.h | 3 +++ arch/arm/plat-s3c64xx/include/plat/s3c6410.h | 1 + arch/arm/plat-s3c64xx/irq.c | 34 ++++++++++++++++++++++++++++ 7 files changed, 47 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/irq.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c index fbca763fa48..c3e317c1650 100644 --- a/arch/arm/mach-s3c6410/cpu.c +++ b/arch/arm/mach-s3c6410/cpu.c @@ -58,6 +58,12 @@ void __init s3c6410_init_clocks(int xtal) s3c24xx_register_baseclocks(xtal); } +void __init s3c6410_init_irq(void) +{ + /* VIC0 is missing IRQ7, VIC1 is fully populated. */ + s3c64xx_init_irq(~0 & ~(1 << 7), ~0); +} + struct sysdev_class s3c6410_sysclass = { .name = "s3c6410-core", }; diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h index 011157ea871..6d89a4637f3 100644 --- a/arch/arm/plat-s3c/include/plat/cpu.h +++ b/arch/arm/plat-s3c/include/plat/cpu.h @@ -44,6 +44,7 @@ extern void s3c_init_cpu(unsigned long idcode, /* core initialisation functions */ extern void s3c24xx_init_irq(void); +extern void s3c64xx_init_irq(u32 vic0, u32 vic1); extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 756c166051b..14d6343b54e 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -10,6 +10,7 @@ config PLAT_S3C64XX bool depends on ARCH_S3C64XX select PLAT_S3C + select ARM_VIC default y select NO_IOPORT select ARCH_REQUIRE_GPIOLIB diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 5d9a1d86ab8..9be8ed59977 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -14,3 +14,4 @@ obj- := obj-y += dev-uart.o obj-y += cpu.o +obj-y += irq.o diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h index 0092b5cba4a..3564dfbec85 100644 --- a/arch/arm/plat-s3c64xx/include/plat/irqs.h +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h @@ -24,6 +24,9 @@ #define S3C_IRQ(x) ((x) + S3C_IRQ_OFFSET) +#define S3C_VIC0_BASE S3C_IRQ(0) +#define S3C_VIC1_BASE S3C_IRQ(32) + /* UART interrupts, each UART has 4 intterupts per channel so * use the space between the ISA and S3C main interrupts. Note, these * are not in the same order as the S3C24XX series! */ diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h index 56f14b5d454..50dcdd6f680 100644 --- a/arch/arm/plat-s3c64xx/include/plat/s3c6410.h +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6410.h @@ -15,6 +15,7 @@ #ifdef CONFIG_CPU_S3C6410 extern int s3c6410_init(void); +extern void s3c6410_init_irq(void); extern void s3c6410_map_io(void); extern void s3c6410_init_clocks(int xtal); diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c new file mode 100644 index 00000000000..308dc4198a1 --- /dev/null +++ b/arch/arm/plat-s3c64xx/irq.c @@ -0,0 +1,34 @@ +/* arch/arm/plat-s3c64xx/irq.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Interrupt handling + * + * 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 + +void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) +{ + printk(KERN_INFO "%s: initialising interrupts\n", __func__); + + /* initialise the pair of VICs */ + vic_init(S3C_VA_VIC0, S3C_VIC0_BASE, vic0_valid); + vic_init(S3C_VA_VIC1, S3C_VIC1_BASE, vic1_valid); +} + + -- cgit v1.2.3-70-g09d2 From aa64ea3f78496bcd7d72d5caffa3d0bf43e84e54 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:06:58 +0100 Subject: [ARM] S3C64XX: Common init code for S3C6400 and S3C6410 Add the common initialisation code for both the S3C6400 and S3C6410, the UART registration. Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6410/Kconfig | 1 + arch/arm/plat-s3c64xx/Kconfig | 6 ++++++ arch/arm/plat-s3c64xx/Makefile | 4 ++++ arch/arm/plat-s3c64xx/s3c6400-init.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/s3c6400-init.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig index c473ba998b3..eff8248439a 100644 --- a/arch/arm/mach-s3c6410/Kconfig +++ b/arch/arm/mach-s3c6410/Kconfig @@ -9,6 +9,7 @@ config CPU_S3C6410 bool + select CPU_S3C6400_INIT help Enable S3C6410 CPU support diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 14d6343b54e..8ed2f7b8611 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -21,4 +21,10 @@ if PLAT_S3C64XX # Configuration options shared by all S3C64XX implementations +config CPU_S3C6400_INIT + bool + help + Common initialisation code for the S3C6400 that is shared + by other CPUs in the series, such as the S3C6410. + endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 9be8ed59977..26b5714ee73 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -15,3 +15,7 @@ obj- := obj-y += dev-uart.o obj-y += cpu.o obj-y += irq.o + +# CPU support + +obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o diff --git a/arch/arm/plat-s3c64xx/s3c6400-init.c b/arch/arm/plat-s3c64xx/s3c6400-init.c new file mode 100644 index 00000000000..6c28f39df09 --- /dev/null +++ b/arch/arm/plat-s3c64xx/s3c6400-init.c @@ -0,0 +1,29 @@ +/* linux/arch/arm/plat-s3c64xx/s3c6400-init.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C6400 - CPU initialisation (common with other S3C64XX chips) + * + * 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 + +/* uart registration process */ + +void __init s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c6400-uart", s3c64xx_uart_resources, cfg, no); +} -- cgit v1.2.3-70-g09d2 From 4b31d8b2256db3ed825a63603f223f84d927ca39 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:07:00 +0100 Subject: [ARM] S3C64XX: Add initial clock framework Add the initial clocks definitions for the s3c6400 and s3c6410. Move the epll and ext clock from the s3c2443 support into the common code. Signed-off-by: Ben Dooks --- arch/arm/mach-s3c2412/clock.c | 6 - arch/arm/mach-s3c2443/clock.c | 15 +- arch/arm/mach-s3c6410/cpu.c | 1 + arch/arm/plat-s3c/clock.c | 10 ++ arch/arm/plat-s3c/include/plat/clock.h | 8 + arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/clock.c | 258 +++++++++++++++++++++++++++++++++ 7 files changed, 279 insertions(+), 20 deletions(-) create mode 100644 arch/arm/plat-s3c64xx/clock.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c index 96d9eb15424..3ce15e082e7 100644 --- a/arch/arm/mach-s3c2412/clock.c +++ b/arch/arm/mach-s3c2412/clock.c @@ -93,12 +93,6 @@ static int s3c2412_upll_enable(struct clk *clk, int enable) /* clock selections */ -/* CPU EXTCLK input */ -static struct clk clk_ext = { - .name = "extclk", - .id = -1, -}; - static struct clk clk_erefclk = { .name = "erefclk", .id = -1, diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 1df8429242b..363f3960878 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c @@ -147,12 +147,6 @@ static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk, /* clock selections */ -/* CPU EXTCLK input */ -static struct clk clk_ext = { - .name = "ext", - .id = -1, -}; - static struct clk clk_mpllref = { .name = "mpllref", .parent = &clk_xtal, @@ -167,14 +161,6 @@ static struct clk clk_mpll = { }; #endif -static struct clk clk_epllref; - -static struct clk clk_epll = { - .name = "epll", - .parent = &clk_epllref, - .id = -1, -}; - static struct clk clk_i2s_ext = { .name = "i2s-ext", .id = -1, @@ -1072,6 +1058,7 @@ void __init s3c2443_init_clocks(int xtal) } clk_epll.rate = s3c2443_get_epll(epllcon, xtal); + clk_epll.parent = &clk_epllref; clk_usb_bus.parent = &clk_usb_bus_host; /* ensure usb bus clock is within correct rate of 48MHz */ diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c index c3e317c1650..94a6204ee55 100644 --- a/arch/arm/mach-s3c6410/cpu.c +++ b/arch/arm/mach-s3c6410/cpu.c @@ -56,6 +56,7 @@ void __init s3c6410_init_clocks(int xtal) { printk(KERN_INFO "%s: initialising clocks\n", __func__); s3c24xx_register_baseclocks(xtal); + s3c64xx_register_clocks(); } void __init s3c6410_init_irq(void) diff --git a/arch/arm/plat-s3c/clock.c b/arch/arm/plat-s3c/clock.c index da7ac07c7a0..1054d18828f 100644 --- a/arch/arm/plat-s3c/clock.c +++ b/arch/arm/plat-s3c/clock.c @@ -239,6 +239,16 @@ struct clk clk_xtal = { .ctrlbit = 0, }; +struct clk clk_ext = { + .name = "ext", + .id = -1, +}; + +struct clk clk_epll = { + .name = "epll", + .id = -1, +}; + struct clk clk_mpll = { .name = "mpll", .id = -1, diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h index d871609738f..6a2c5af1000 100644 --- a/arch/arm/plat-s3c/include/plat/clock.h +++ b/arch/arm/plat-s3c/include/plat/clock.h @@ -45,7 +45,13 @@ extern struct clk clk_h; extern struct clk clk_p; extern struct clk clk_mpll; extern struct clk clk_upll; +extern struct clk clk_epll; extern struct clk clk_xtal; +extern struct clk clk_ext; + +/* S3C64XX specific clocks */ +extern struct clk clk_27m; +extern struct clk clk_48m; /* exports for arch/arm/mach-s3c2410 * @@ -61,6 +67,8 @@ extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks); extern int s3c24xx_register_baseclocks(unsigned long xtal); +extern void s3c64xx_register_clocks(void); + extern void s3c24xx_setup_clocks(unsigned long fclk, unsigned long hclk, unsigned long pclk); diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 26b5714ee73..15f717fd148 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -15,6 +15,7 @@ obj- := obj-y += dev-uart.o obj-y += cpu.o obj-y += irq.o +obj-y += clock.o # CPU support diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c new file mode 100644 index 00000000000..e7c2994e2d3 --- /dev/null +++ b/arch/arm/plat-s3c64xx/clock.c @@ -0,0 +1,258 @@ +/* linux/arch/arm/plat-s3c64xx/clock.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX Base clock support + * + * 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 + +struct clk clk_27m = { + .name = "clk_27m", + .id = -1, + .rate = 27000000, +}; + +struct clk clk_48m = { + .name = "clk_48m", + .id = -1, + .rate = 48000000, +}; + +static int inline s3c64xx_gate(void __iomem *reg, + struct clk *clk, + int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + u32 con; + + con = __raw_readl(reg); + + if (enable) + con |= ctrlbit; + else + con &= ~ctrlbit; + + __raw_writel(con, reg); + return 0; +} + +static int s3c64xx_pclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_PCLK_GATE, clk, enable); +} + +static int s3c64xx_hclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_HCLK_GATE, clk, enable); +} + +static int s3c6xx_sclk_ctrl(struct clk *clk, int enable) +{ + return s3c64xx_gate(S3C_SCLK_GATE, clk, enable); +} + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_TSADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIC, + }, { + .name = "iis", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIS0, + }, { + .name = "iis", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_IIS1, + }, { + .name = "spi", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_SPI0, + }, { + .name = "spi", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_SPI1, + }, { + .name = "48m", + .id = 0, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC0_48, + }, { + .name = "48m", + .id = 1, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC1_48, + }, { + .name = "48m", + .id = 2, + .parent = &clk_48m, + .enable = s3c64xx_sclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_MMC2_48, + }, +}; + +static struct clk init_clocks[] = { + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_LCD, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_SCLK_UHOST, + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC0, + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC1, + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_h, + .enable = s3c64xx_hclk_ctrl, + .ctrlbit = S3C_CLKCON_HCLK_HSMMC2, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_PWM, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART2, + }, { + .name = "uart", + .id = 3, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_UART3, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C_CLKCON_PCLK_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C_CLKCON_PCLK_WDT, + }, { + .name = "ac97", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C_CLKCON_PCLK_AC97, + } +}; + +static struct clk *clks[] __initdata = { + &clk_ext, + &clk_epll, + &clk_27m, + &clk_48m, +}; + +void s3c64xx_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + (clkp->enable)(clkp, 0); + } +} -- cgit v1.2.3-70-g09d2 From cf18acf0e04260ff8ffa46dc245d3d2324ed41b0 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:07:02 +0100 Subject: [ARM] S3C64XX: Clock support for S3C6400/S3C6410 Add the PLL clock initialisation and clock registration and include the clocks sourced via CLKDIVx for most of the on-chip peripherals. Signed-off-by: Ben Dooks --- arch/arm/mach-s3c6410/Kconfig | 1 + arch/arm/mach-s3c6410/cpu.c | 3 + arch/arm/plat-s3c/include/plat/clock.h | 3 + arch/arm/plat-s3c64xx/Kconfig | 6 + arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/clock.c | 2 +- arch/arm/plat-s3c64xx/include/plat/regs-clock.h | 95 +++- arch/arm/plat-s3c64xx/include/plat/s3c6400.h | 2 + arch/arm/plat-s3c64xx/s3c6400-clock.c | 654 ++++++++++++++++++++++++ 9 files changed, 765 insertions(+), 2 deletions(-) create mode 100644 arch/arm/plat-s3c64xx/s3c6400-clock.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig index eff8248439a..d8377f737c4 100644 --- a/arch/arm/mach-s3c6410/Kconfig +++ b/arch/arm/mach-s3c6410/Kconfig @@ -10,6 +10,7 @@ config CPU_S3C6410 bool select CPU_S3C6400_INIT + select CPU_S3C6400_CLOCK help Enable S3C6410 CPU support diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c index 94a6204ee55..846f464c767 100644 --- a/arch/arm/mach-s3c6410/cpu.c +++ b/arch/arm/mach-s3c6410/cpu.c @@ -35,6 +35,7 @@ #include #include #include +#include #include /* Initial IO mappings */ @@ -57,6 +58,8 @@ void __init s3c6410_init_clocks(int xtal) printk(KERN_INFO "%s: initialising clocks\n", __func__); s3c24xx_register_baseclocks(xtal); s3c64xx_register_clocks(); + s3c6400_register_clocks(); + s3c6400_setup_clocks(); } void __init s3c6410_init_irq(void) diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h index 6a2c5af1000..ea1f3ffa971 100644 --- a/arch/arm/plat-s3c/include/plat/clock.h +++ b/arch/arm/plat-s3c/include/plat/clock.h @@ -78,3 +78,6 @@ extern void s3c2412_setup_clocks(void); extern void s3c244x_setup_clocks(void); extern void s3c2443_setup_clocks(void); +/* S3C64XX specific functions and clocks */ + +extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 8ed2f7b8611..bd832ba0cf7 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -27,4 +27,10 @@ config CPU_S3C6400_INIT Common initialisation code for the S3C6400 that is shared by other CPUs in the series, such as the S3C6410. +config CPU_S3C6400_CLOCK + bool + help + Common clock support code for the S3C6400 that is shared + by other CPUs in the series, such as the S3C6410. + endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 15f717fd148..9e055d48661 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -20,3 +20,4 @@ obj-y += clock.o # CPU support obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o +obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c index e7c2994e2d3..2d2e83a036c 100644 --- a/arch/arm/plat-s3c64xx/clock.c +++ b/arch/arm/plat-s3c64xx/clock.c @@ -67,7 +67,7 @@ static int s3c64xx_hclk_ctrl(struct clk *clk, int enable) return s3c64xx_gate(S3C_HCLK_GATE, clk, enable); } -static int s3c6xx_sclk_ctrl(struct clk *clk, int enable) +int s3c64xx_sclk_ctrl(struct clk *clk, int enable) { return s3c64xx_gate(S3C_SCLK_GATE, clk, enable); } diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h index 462558ec1af..78938a5e1d2 100644 --- a/arch/arm/plat-s3c64xx/include/plat/regs-clock.h +++ b/arch/arm/plat-s3c64xx/include/plat/regs-clock.h @@ -33,6 +33,59 @@ #define S3C_PCLK_GATE S3C_CLKREG(0x34) #define S3C_SCLK_GATE S3C_CLKREG(0x38) +/* CLKDIV0 */ +#define S3C6400_CLKDIV0_MFC_MASK (0xf << 28) +#define S3C6400_CLKDIV0_MFC_SHIFT (28) +#define S3C6400_CLKDIV0_JPEG_MASK (0xf << 24) +#define S3C6400_CLKDIV0_JPEG_SHIFT (24) +#define S3C6400_CLKDIV0_CAM_MASK (0xf << 20) +#define S3C6400_CLKDIV0_CAM_SHIFT (20) +#define S3C6400_CLKDIV0_SECURITY_MASK (0x3 << 18) +#define S3C6400_CLKDIV0_SECURITY_SHIFT (18) +#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12) +#define S3C6400_CLKDIV0_PCLK_SHIFT (12) +#define S3C6400_CLKDIV0_HCLK2_MASK (0x7 << 9) +#define S3C6400_CLKDIV0_HCLK2_SHIFT (9) +#define S3C6400_CLKDIV0_HCLK_MASK (0x1 << 8) +#define S3C6400_CLKDIV0_HCLK_SHIFT (8) +#define S3C6400_CLKDIV0_MPLL_MASK (0x1 << 4) +#define S3C6400_CLKDIV0_MPLL_SHIFT (4) +#define S3C6400_CLKDIV0_ARM_MASK (0x3 << 0) +#define S3C6410_CLKDIV0_ARM_MASK (0x7 << 0) +#define S3C6400_CLKDIV0_ARM_SHIFT (0) + +/* CLKDIV1 */ +#define S3C6410_CLKDIV1_FIMC_MASK (0xf << 24) +#define S3C6410_CLKDIV1_FIMC_SHIFT (24) +#define S3C6400_CLKDIV1_UHOST_MASK (0xf << 20) +#define S3C6400_CLKDIV1_UHOST_SHIFT (20) +#define S3C6400_CLKDIV1_SCALER_MASK (0xf << 16) +#define S3C6400_CLKDIV1_SCALER_SHIFT (16) +#define S3C6400_CLKDIV1_LCD_MASK (0xf << 12) +#define S3C6400_CLKDIV1_LCD_SHIFT (12) +#define S3C6400_CLKDIV1_MMC2_MASK (0xf << 8) +#define S3C6400_CLKDIV1_MMC2_SHIFT (8) +#define S3C6400_CLKDIV1_MMC1_MASK (0xf << 4) +#define S3C6400_CLKDIV1_MMC1_SHIFT (4) +#define S3C6400_CLKDIV1_MMC0_MASK (0xf << 0) +#define S3C6400_CLKDIV1_MMC0_SHIFT (0) + +/* CLKDIV2 */ +#define S3C6410_CLKDIV2_AUDIO2_MASK (0xf << 24) +#define S3C6410_CLKDIV2_AUDIO2_SHIFT (24) +#define S3C6400_CLKDIV2_IRDA_MASK (0xf << 20) +#define S3C6400_CLKDIV2_IRDA_SHIFT (20) +#define S3C6400_CLKDIV2_UART_MASK (0xf << 16) +#define S3C6400_CLKDIV2_UART_SHIFT (16) +#define S3C6400_CLKDIV2_AUDIO1_MASK (0xf << 12) +#define S3C6400_CLKDIV2_AUDIO1_SHIFT (12) +#define S3C6400_CLKDIV2_AUDIO0_MASK (0xf << 8) +#define S3C6400_CLKDIV2_AUDIO0_SHIFT (8) +#define S3C6400_CLKDIV2_SPI1_MASK (0xf << 4) +#define S3C6400_CLKDIV2_SPI1_SHIFT (4) +#define S3C6400_CLKDIV2_SPI0_MASK (0xf << 0) +#define S3C6400_CLKDIV2_SPI0_SHIFT (0) + /* HCLK GATE Registers */ #define S3C_CLKCON_HCLK_BUS (1<<30) #define S3C_CLKCON_HCLK_SECUR (1<<29) @@ -128,4 +181,44 @@ #define S3C_CLKCON_SCLK_CAM (1<<2) #define S3C_CLKCON_SCLK_JPEG (1<<1) -#endif /* __PLAT_REGS_CLOCK_H */ +/* CLKSRC */ + +#define S3C6400_CLKSRC_APLL_MOUT (1 << 0) +#define S3C6400_CLKSRC_MPLL_MOUT (1 << 1) +#define S3C6400_CLKSRC_EPLL_MOUT (1 << 2) +#define S3C6400_CLKSRC_APLL_MOUT_SHIFT (0) +#define S3C6400_CLKSRC_MPLL_MOUT_SHIFT (1) +#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2) +#define S3C6400_CLKSRC_MFC (1 << 4) + +#define S3C6410_CLKSRC_TV27_MASK (0x1 << 31) +#define S3C6410_CLKSRC_TV27_SHIFT (31) +#define S3C6410_CLKSRC_DAC27_MASK (0x1 << 30) +#define S3C6410_CLKSRC_DAC27_SHIFT (30) +#define S3C6400_CLKSRC_SCALER_MASK (0x3 << 28) +#define S3C6400_CLKSRC_SCALER_SHIFT (28) +#define S3C6400_CLKSRC_LCD_MASK (0x3 << 26) +#define S3C6400_CLKSRC_LCD_SHIFT (26) +#define S3C6400_CLKSRC_IRDA_MASK (0x3 << 24) +#define S3C6400_CLKSRC_IRDA_SHIFT (24) +#define S3C6400_CLKSRC_MMC2_MASK (0x3 << 22) +#define S3C6400_CLKSRC_MMC2_SHIFT (22) +#define S3C6400_CLKSRC_MMC1_MASK (0x3 << 20) +#define S3C6400_CLKSRC_MMC1_SHIFT (20) +#define S3C6400_CLKSRC_MMC0_MASK (0xf << 1) +#define S3C6400_CLKSRC_MMC0_SHIFT (1) +#define S3C6400_CLKSRC_SPI1_MASK (0x3 << 16) +#define S3C6400_CLKSRC_SPI1_SHIFT (16) +#define S3C6400_CLKSRC_SPI0_MASK (0x3 << 14) +#define S3C6400_CLKSRC_SPI0_SHIFT (14) +#define S3C6400_CLKSRC_UART_MASK (0x1 << 13) +#define S3C6400_CLKSRC_UART_SHIFT (13) +#define S3C6400_CLKSRC_AUDIO1_MASK (0x7 << 10) +#define S3C6400_CLKSRC_AUDIO1_SHIFT (10) +#define S3C6400_CLKSRC_AUDIO0_MASK (0x7 << 7) +#define S3C6400_CLKSRC_AUDIO0_SHIFT (7) +#define S3C6400_CLKSRC_UHOST_MASK (0x3 << 5) +#define S3C6400_CLKSRC_UHOST_SHIFT (5) + + +#endif /* _PLAT_REGS_CLOCK_H */ diff --git a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h index 142bb3d18cd..571eaa2e54f 100644 --- a/arch/arm/plat-s3c64xx/include/plat/s3c6400.h +++ b/arch/arm/plat-s3c64xx/include/plat/s3c6400.h @@ -15,6 +15,8 @@ /* Common init code for S3C6400 related SoCs */ extern void s3c6400_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); +extern void s3c6400_register_clocks(void); +extern void s3c6400_setup_clocks(void); #ifdef CONFIG_CPU_S3C6400 diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c new file mode 100644 index 00000000000..ff5d907f2fc --- /dev/null +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -0,0 +1,654 @@ +/* linux/arch/arm/plat-s3c64xx/s3c6400-clock.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C6400 based common clock support + * + * 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 + +#include +#include +#include +#include + +/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call + * ext_xtal_mux for want of an actual name from the manual. +*/ + +struct clk clk_ext_xtal_mux = { + .name = "ext_xtal", + .id = -1, +}; + +#define clk_fin_apll clk_ext_xtal_mux +#define clk_fin_mpll clk_ext_xtal_mux +#define clk_fin_epll clk_ext_xtal_mux + +#define clk_fout_mpll clk_mpll + +struct clk_sources { + unsigned int nr_sources; + struct clk **sources; +}; + +struct clksrc_clk { + struct clk clk; + unsigned int mask; + unsigned int shift; + + struct clk_sources *sources; + + unsigned int divider_shift; + void __iomem *reg_divider; +}; + +struct clk clk_fout_apll = { + .name = "fout_apll", + .id = -1, +}; + +static struct clk *clk_src_apll_list[] = { + [0] = &clk_fin_apll, + [1] = &clk_fout_apll, +}; + +static struct clk_sources clk_src_apll = { + .sources = clk_src_apll_list, + .nr_sources = ARRAY_SIZE(clk_src_apll_list), +}; + +struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_APLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_APLL_MOUT, + .sources = &clk_src_apll, +}; + +struct clk clk_fout_epll = { + .name = "fout_epll", + .id = -1, +}; + +static struct clk *clk_src_epll_list[] = { + [0] = &clk_fin_epll, + [1] = &clk_fout_epll, +}; + +static struct clk_sources clk_src_epll = { + .sources = clk_src_epll_list, + .nr_sources = ARRAY_SIZE(clk_src_epll_list), +}; + +struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_EPLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_EPLL_MOUT, + .sources = &clk_src_epll, +}; + +static struct clk *clk_src_mpll_list[] = { + [0] = &clk_fin_mpll, + [1] = &clk_fout_mpll, +}; + +static struct clk_sources clk_src_mpll = { + .sources = clk_src_mpll_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_list), +}; + +struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .shift = S3C6400_CLKSRC_MPLL_MOUT_SHIFT, + .mask = S3C6400_CLKSRC_MPLL_MOUT, + .sources = &clk_src_mpll, +}; + +static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + + printk(KERN_INFO "%s: parent is %ld\n", __func__, rate); + + if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK) + rate /= 2; + + return rate; +} + +struct clk clk_dout_mpll = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, + .get_rate = s3c64xx_clk_doutmpll_get_rate, +}; + +static struct clk *clkset_spi_mmc_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + &clk_fin_epll, + &clk_27m, +}; + +static struct clk_sources clkset_spi_mmc = { + .sources = clkset_spi_mmc_list, + .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list), +}; + +static struct clk *clkset_irda_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + &clk_27m, +}; + +static struct clk_sources clkset_irda = { + .sources = clkset_irda_list, + .nr_sources = ARRAY_SIZE(clkset_irda_list), +}; + +static struct clk *clkset_uart_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + NULL +}; + +static struct clk_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static struct clk *clkset_uhost_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + &clk_fin_epll, + &clk_48m, +}; + +static struct clk_sources clkset_uhost = { + .sources = clkset_uhost_list, + .nr_sources = ARRAY_SIZE(clkset_uhost_list), +}; + + +/* The peripheral clocks are all controlled via clocksource followed + * by an optional divider and gate stage. We currently roll this into + * one clock which hides the intermediate clock from the mux. + * + * Note, the JPEG clock can only be an even divider... + * + * The scaler and LCD clocks depend on the S3C64XX version, and also + * have a common parent divisor so are not included here. + */ + +static inline struct clksrc_clk *to_clksrc(struct clk *clk) +{ + return container_of(clk, struct clksrc_clk, clk); +} + +static unsigned long s3c64xx_getrate_clksrc(struct clk *clk) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + unsigned long rate = clk_get_rate(clk->parent); + u32 clkdiv = __raw_readl(sclk->reg_divider); + + clkdiv >>= sclk->divider_shift; + clkdiv &= 0xf; + clkdiv++; + + rate /= clkdiv; + return rate; +} + +static int s3c64xx_setrate_clksrc(struct clk *clk, unsigned long rate) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + void __iomem *reg = sclk->reg_divider; + unsigned int div; + u32 val; + + rate = clk_round_rate(clk, rate); + div = clk_get_rate(clk->parent) / rate; + + val = __raw_readl(reg); + val &= ~sclk->mask; + val |= (rate - 1) << sclk->shift; + __raw_writel(val, reg); + + return 0; +} + +static int s3c64xx_setparent_clksrc(struct clk *clk, struct clk *parent) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + struct clk_sources *srcs = sclk->sources; + u32 clksrc = __raw_readl(S3C_CLK_SRC); + int src_nr = -1; + int ptr; + + for (ptr = 0; ptr < srcs->nr_sources; ptr++) + if (srcs->sources[ptr] == parent) { + src_nr = ptr; + break; + } + + if (src_nr >= 0) { + clksrc &= ~sclk->mask; + clksrc |= src_nr << sclk->shift; + + __raw_writel(clksrc, S3C_CLK_SRC); + return 0; + } + + return -EINVAL; +} + +static unsigned long s3c64xx_roundrate_clksrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + rate = parent_rate; + else { + div = rate / parent_rate; + + if (div == 0) + div = 1; + if (div > 16) + div = 16; + + rate = parent_rate / div; + } + + return rate; +} + +static struct clksrc_clk clk_mmc0 = { + .clk = { + .name = "mmc_bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_MMC0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC0_SHIFT, + .mask = S3C6400_CLKSRC_MMC0_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC0_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_mmc1 = { + .clk = { + .name = "mmc_bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_MMC1, + .enable = s3c64xx_sclk_ctrl, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .set_parent = s3c64xx_setparent_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC1_SHIFT, + .mask = S3C6400_CLKSRC_MMC1_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC1_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_mmc2 = { + .clk = { + .name = "mmc_bus", + .id = 2, + .ctrlbit = S3C_CLKCON_SCLK_MMC2, + .enable = s3c64xx_sclk_ctrl, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .set_parent = s3c64xx_setparent_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_MMC2_SHIFT, + .mask = S3C6400_CLKSRC_MMC2_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV1_MMC2_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_usbhost = { + .clk = { + .name = "usb-host-bus", + .id = -1, + .ctrlbit = S3C_CLKCON_SCLK_UHOST, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_UHOST_SHIFT, + .mask = S3C6400_CLKSRC_UHOST_MASK, + .sources = &clkset_uhost, + .divider_shift = S3C6400_CLKDIV1_UHOST_SHIFT, + .reg_divider = S3C_CLK_DIV1, +}; + +static struct clksrc_clk clk_uart_uclk1 = { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = S3C_CLKCON_SCLK_UART, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_UART_SHIFT, + .mask = S3C6400_CLKSRC_UART_MASK, + .sources = &clkset_uart, + .divider_shift = S3C6400_CLKDIV2_UART_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +/* Where does UCLK0 come from? */ + +static struct clksrc_clk clk_spi0 = { + .clk = { + .name = "spi-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_SPI0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_SPI0_SHIFT, + .mask = S3C6400_CLKSRC_SPI0_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV2_SPI0_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clksrc_clk clk_spi1 = { + .clk = { + .name = "spi-bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_SPI1, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_SPI1_SHIFT, + .mask = S3C6400_CLKSRC_SPI1_MASK, + .sources = &clkset_spi_mmc, + .divider_shift = S3C6400_CLKDIV2_SPI1_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clk clk_iis_cd0 = { + .name = "iis_cdclk0", + .id = -1, +}; + +static struct clk clk_iis_cd1 = { + .name = "iis_cdclk1", + .id = -1, +}; + +static struct clk clk_pcm_cd = { + .name = "pcm_cdclk", + .id = -1, +}; + +static struct clk *clkset_audio0_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iis_cd0, + [4] = &clk_pcm_cd, +}; + +static struct clk_sources clkset_audio0 = { + .sources = clkset_audio0_list, + .nr_sources = ARRAY_SIZE(clkset_audio0_list), +}; + +static struct clksrc_clk clk_audio0 = { + .clk = { + .name = "audio-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_AUDIO0, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_AUDIO0_SHIFT, + .mask = S3C6400_CLKSRC_AUDIO0_MASK, + .sources = &clkset_audio0, + .divider_shift = S3C6400_CLKDIV2_AUDIO0_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clk *clkset_audio1_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iis_cd1, + [4] = &clk_pcm_cd, +}; + +static struct clk_sources clkset_audio1 = { + .sources = clkset_audio1_list, + .nr_sources = ARRAY_SIZE(clkset_audio1_list), +}; + +static struct clksrc_clk clk_audio1 = { + .clk = { + .name = "audio-bus", + .id = 1, + .ctrlbit = S3C_CLKCON_SCLK_AUDIO1, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_AUDIO1_SHIFT, + .mask = S3C6400_CLKSRC_AUDIO1_MASK, + .sources = &clkset_audio1, + .divider_shift = S3C6400_CLKDIV2_AUDIO1_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +static struct clksrc_clk clk_irda = { + .clk = { + .name = "irda-bus", + .id = 0, + .ctrlbit = S3C_CLKCON_SCLK_IRDA, + .enable = s3c64xx_sclk_ctrl, + .set_parent = s3c64xx_setparent_clksrc, + .get_rate = s3c64xx_getrate_clksrc, + .set_rate = s3c64xx_setrate_clksrc, + .round_rate = s3c64xx_roundrate_clksrc, + }, + .shift = S3C6400_CLKSRC_IRDA_SHIFT, + .mask = S3C6400_CLKSRC_IRDA_MASK, + .sources = &clkset_irda, + .divider_shift = S3C6400_CLKDIV2_IRDA_SHIFT, + .reg_divider = S3C_CLK_DIV2, +}; + +/* Clock initialisation code */ + +static struct clksrc_clk *init_parents[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_mmc0, + &clk_mmc1, + &clk_mmc2, + &clk_usbhost, + &clk_uart_uclk1, + &clk_spi0, + &clk_spi1, + &clk_audio0, + &clk_audio1, + &clk_irda, +}; + +static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk) +{ + struct clk_sources *srcs = clk->sources; + u32 clksrc = __raw_readl(S3C_CLK_SRC); + + clksrc &= clk->mask; + clksrc >>= clk->shift; + + if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) { + printk(KERN_ERR "%s: bad source %d\n", + clk->clk.name, clksrc); + return; + } + + clk->clk.parent = srcs->sources[clksrc]; + + printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n", + clk->clk.name, clk->clk.parent->name, clksrc, + clk_get_rate(&clk->clk)); +} + +#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) + +void __init_or_cpufreq s3c6400_setup_clocks(void) +{ + struct clk *xtal_clk; + unsigned long xtal; + unsigned long fclk; + unsigned long hclk; + unsigned long hclk2; + unsigned long pclk; + unsigned long epll; + unsigned long apll; + unsigned long mpll; + unsigned int ptr; + u32 clkdiv0; + + printk(KERN_INFO "%s: registering clocks\n", __func__); + + clkdiv0 = __raw_readl(S3C_CLK_DIV0); + printk(KERN_INFO "%s: clkdiv0 = %08x\n", __func__, clkdiv0); + + xtal_clk = clk_get(NULL, "xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + printk(KERN_INFO "%s: xtal is %ld\n", __func__, xtal); + + epll = s3c6400_get_epll(xtal); + mpll = s3c6400_get_pll(xtal, __raw_readl(S3C_MPLL_CON)); + apll = s3c6400_get_pll(xtal, __raw_readl(S3C_APLL_CON)); + + fclk = mpll; + + printk(KERN_INFO "S3C64XX: PLL settings, A=%ld, M=%ld, E=%ld\n", + apll, mpll, epll); + + hclk2 = mpll / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK2); + hclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_HCLK); + pclk = hclk2 / GET_DIV(clkdiv0, S3C6400_CLKDIV0_PCLK); + + printk(KERN_INFO "S3C64XX: HCLK2=%ld, HCLK=%ld, PCLK=%ld\n", + hclk2, hclk, pclk); + + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_apll.rate = apll; + + clk_h.rate = hclk; + clk_p.rate = pclk; + clk_f.rate = fclk; + + for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) + s3c6400_set_clksrc(init_parents[ptr]); +} + +static struct clk *clks[] __initdata = { + &clk_ext_xtal_mux, + &clk_iis_cd0, + &clk_iis_cd1, + &clk_pcm_cd, + &clk_mout_epll.clk, + &clk_mout_mpll.clk, + &clk_dout_mpll, + &clk_mmc0.clk, + &clk_mmc1.clk, + &clk_mmc2.clk, + &clk_usbhost.clk, + &clk_uart_uclk1.clk, + &clk_spi0.clk, + &clk_spi1.clk, + &clk_audio0.clk, + &clk_audio1.clk, + &clk_irda.clk, +}; + +void __init s3c6400_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { + clkp = clks[ptr]; + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clk_mpll.parent = &clk_mout_mpll.clk; + clk_epll.parent = &clk_mout_epll.clk; +} -- cgit v1.2.3-70-g09d2 From 80789e79150b34e45a630e2f4f1b04d82c449c19 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 21 Oct 2008 14:07:08 +0100 Subject: [ARM] S3C64XX: Add IRQ_EINT support Add the necessary code to support IRQ_EINT(x) on the S3C64XX series of CPUs. Note, since there is no GPIO configuration support in the kernel, the irq set_type method does not configure the relevant pin to interrupt. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/include/plat/irqs.h | 3 +- arch/arm/plat-s3c64xx/irq-eint.c | 202 ++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 arch/arm/plat-s3c64xx/irq-eint.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 9e055d48661..9c09b081980 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -15,6 +15,7 @@ obj- := obj-y += dev-uart.o obj-y += cpu.o obj-y += irq.o +obj-y += irq-eint.o obj-y += clock.o # CPU support diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h index 8bdfb27425e..5ab41ad143b 100644 --- a/arch/arm/plat-s3c64xx/include/plat/irqs.h +++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h @@ -150,7 +150,8 @@ #define S3C_IRQ_EINT_BASE S3C_IRQ(64+5) -#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) +#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) +#define IRQ_EINT(x) S3C_EINT(x) /* Define NR_IRQs here, machine specific can always re-define. * Currently the IRQ_EINT27 is the last one we can have. */ diff --git a/arch/arm/plat-s3c64xx/irq-eint.c b/arch/arm/plat-s3c64xx/irq-eint.c new file mode 100644 index 00000000000..8c01f9cd94b --- /dev/null +++ b/arch/arm/plat-s3c64xx/irq-eint.c @@ -0,0 +1,202 @@ +/* arch/arm/plat-s3c64xx/irq-eint.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - Interrupt handling for IRQ_EINT(x) + * + * 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 + +/* GPIO is 0x7F008xxx, */ +#define S3C64XX_GPIOREG(x) (S3C64XX_VA_GPIO + (x)) + +#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900) +#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904) +#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910) +#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914) +#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918) +#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C) + +#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920) +#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924) + + +#define eint_offset(irq) ((irq) - IRQ_EINT(0)) +#define eint_irq_to_bit(irq) (1 << eint_offset(irq)) + +static inline void s3c_irq_eint_mask(unsigned int irq) +{ + u32 mask; + + mask = __raw_readl(S3C64XX_EINT0MASK); + mask |= eint_irq_to_bit(irq); + __raw_writel(mask, S3C64XX_EINT0MASK); +} + +static void s3c_irq_eint_unmask(unsigned int irq) +{ + u32 mask; + + mask = __raw_readl(S3C64XX_EINT0MASK); + mask |= eint_irq_to_bit(irq); + __raw_writel(mask, S3C64XX_EINT0MASK); +} + +static inline void s3c_irq_eint_ack(unsigned int irq) +{ + __raw_writel(eint_irq_to_bit(irq), S3C64XX_EINT0PEND); +} + +static void s3c_irq_eint_maskack(unsigned int irq) +{ + /* compiler should in-line these */ + s3c_irq_eint_mask(irq); + s3c_irq_eint_ack(irq); +} + +static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type) +{ + int offs = eint_offset(irq); + int shift; + u32 ctrl, mask; + u32 newvalue = 0; + void __iomem *reg; + + if (offs > 27) + return -EINVAL; + + if (offs > 15) + reg = S3C64XX_EINT0CON0; + else + reg = S3C64XX_EINT0CON1; + + switch (type) { + case IRQ_TYPE_NONE: + printk(KERN_WARNING "No edge setting!\n"); + break; + + case IRQ_TYPE_EDGE_RISING: + newvalue = S3C2410_EXTINT_RISEEDGE; + break; + + case IRQ_TYPE_EDGE_FALLING: + newvalue = S3C2410_EXTINT_FALLEDGE; + break; + + case IRQ_TYPE_EDGE_BOTH: + newvalue = S3C2410_EXTINT_BOTHEDGE; + break; + + case IRQ_TYPE_LEVEL_LOW: + newvalue = S3C2410_EXTINT_LOWLEV; + break; + + case IRQ_TYPE_LEVEL_HIGH: + newvalue = S3C2410_EXTINT_HILEV; + break; + + default: + printk(KERN_ERR "No such irq type %d", type); + return -1; + } + + shift = (offs / 2) * 4; + mask = 0x7 << shift; + + ctrl = __raw_readl(reg); + ctrl &= ~mask; + ctrl |= newvalue << shift; + __raw_writel(ctrl, reg); + + return 0; +} + +static struct irq_chip s3c_irq_eint = { + .name = "s3c-eint", + .mask = s3c_irq_eint_mask, + .unmask = s3c_irq_eint_unmask, + .mask_ack = s3c_irq_eint_maskack, + .ack = s3c_irq_eint_ack, + .set_type = s3c_irq_eint_set_type, +}; + +/* s3c_irq_demux_eint + * + * This function demuxes the IRQ from the group0 external interrupts, + * from IRQ_EINT(0) to IRQ_EINT(27). It is designed to be inlined into + * the specific handlers s3c_irq_demux_eintX_Y. + */ +static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end) +{ + u32 status = __raw_readl(S3C64XX_EINT0PEND); + u32 mask = __raw_readl(S3C64XX_EINT0MASK); + unsigned int irq; + + status &= ~mask; + status >>= start; + status &= (1 << (end - start + 1)) - 1; + + for (irq = IRQ_EINT(start); irq <= IRQ_EINT(end); irq++) { + if (status & 1) + generic_handle_irq(irq); + + status >>= 1; + } +} + +static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(0, 3); +} + +static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(4, 11); +} + +static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(12, 19); +} + +static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_eint(20, 27); +} + +int __init s3c64xx_init_irq_eint(void) +{ + int irq; + + for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) { + set_irq_chip(irq, &s3c_irq_eint); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3); + set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11); + set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19); + set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27); + + return 0; +} + +arch_initcall(s3c64xx_init_irq_eint); -- cgit v1.2.3-70-g09d2 From 89d043c3db22c37523165905708d2fa8062fda86 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 31 Oct 2008 16:14:33 +0000 Subject: [ARM] S3C64XX: GPIO library support Add gpiolib registration for the GPIOs available on the S3C64XX platform Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/gpiolib.c | 347 +++++++++++++++++++++++++ arch/arm/plat-s3c64xx/include/plat/regs-gpio.h | 35 +++ 3 files changed, 383 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/gpiolib.c create mode 100644 arch/arm/plat-s3c64xx/include/plat/regs-gpio.h (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 9c09b081980..a5b7c388351 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -17,6 +17,7 @@ obj-y += cpu.o obj-y += irq.o obj-y += irq-eint.o obj-y += clock.o +obj-y += gpiolib.o # CPU support diff --git a/arch/arm/plat-s3c64xx/gpiolib.c b/arch/arm/plat-s3c64xx/gpiolib.c new file mode 100644 index 00000000000..28ba23502bc --- /dev/null +++ b/arch/arm/plat-s3c64xx/gpiolib.c @@ -0,0 +1,347 @@ +/* arch/arm/plat-s3c64xx/gpiolib.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - GPIOlib support + * + * 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 + +/* GPIO bank summary: + * + * Bank GPIOs Style SlpCon ExtInt Group + * A 8 4Bit Yes 1 + * B 7 4Bit Yes 1 + * C 8 4Bit Yes 2 + * D 5 4Bit Yes 3 + * E 5 4Bit Yes None + * F 16 2Bit Yes 4 [1] + * G 7 4Bit Yes 5 + * H 10 4Bit[2] Yes 6 + * I 16 2Bit Yes None + * J 12 2Bit Yes None + * K 16 4Bit[2] No None + * L 15 4Bit[2] No None + * M 6 4Bit No IRQ_EINT + * N 16 2Bit No IRQ_EINT + * O 16 2Bit Yes 7 + * P 15 2Bit Yes 8 + * Q 9 2Bit Yes 9 + * + * [1] BANKF pins 14,15 do not form part of the external interrupt sources + * [2] BANK has two control registers, GPxCON0 and GPxCON1 + */ + +#define OFF_GPCON (0x00) +#define OFF_GPDAT (0x04) + +#define con_4bit_shift(__off) ((__off) * 4) + +/* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where + * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the + * following example: + * + * base + 0x00: Control register, 4 bits per gpio + * gpio n: 4 bits starting at (4*n) + * 0000 = input, 0001 = output, others mean special-function + * base + 0x04: Data register, 1 bit per gpio + * bit n: data bit n + * + * Note, since the data register is one bit per gpio and is at base + 0x4 + * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of + * the output. +*/ + +static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long con; + + con = __raw_readl(base + OFF_GPCON); + con &= ~(0xf << con_4bit_shift(offset)); + __raw_writel(con, base + OFF_GPCON); + + return 0; +} + +static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + unsigned long con; + unsigned long dat; + + con = __raw_readl(base + OFF_GPCON); + con &= ~(0xf << con_4bit_shift(offset)); + con |= 0x1 << con_4bit_shift(offset); + + dat = __raw_readl(base + OFF_GPDAT); + if (value) + dat |= 1 << offset; + else + dat &= ~(1 << offset); + + __raw_writel(dat, base + OFF_GPDAT); + __raw_writel(con, base + OFF_GPCON); + __raw_writel(dat, base + OFF_GPDAT); + + return 0; +} + +/* The next set of routines are for the case where the GPIO configuration + * registers are 4 bits per GPIO but there is more than one register (the + * bank has more than 8 GPIOs. + * + * This case is the similar to the 4 bit case, but the registers are as + * follows: + * + * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs) + * gpio n: 4 bits starting at (4*n) + * 0000 = input, 0001 = output, others mean special-function + * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs) + * gpio n: 4 bits starting at (4*n) + * 0000 = input, 0001 = output, others mean special-function + * base + 0x08: Data register, 1 bit per gpio + * bit n: data bit n + * + * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we + * store the 'base + 0x4' address so that these routines see the data + * register at ourchip->base + 0x04. +*/ + +static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + void __iomem *regcon = base; + unsigned long con; + + if (offset > 7) + offset -= 8; + else + regcon -= 4; + + con = __raw_readl(regcon); + con &= ~(0xf << con_4bit_shift(offset)); + __raw_writel(con, regcon); + + return 0; + +} + +static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); + void __iomem *base = ourchip->base; + void __iomem *regcon = base; + unsigned long con; + unsigned long dat; + + if (offset > 7) + offset -= 8; + else + regcon -= 4; + + con = __raw_readl(regcon); + con &= ~(0xf << con_4bit_shift(offset)); + con |= 0x1 << con_4bit_shift(offset); + + dat = __raw_readl(base + OFF_GPDAT); + if (value) + dat |= 1 << offset; + else + dat &= ~(1 << offset); + + __raw_writel(dat, base + OFF_GPDAT); + __raw_writel(con, regcon); + __raw_writel(dat, base + OFF_GPDAT); + + return 0; +} + +static struct s3c_gpio_chip gpio_4bit[] = { + { + .base = S3C64XX_GPA_BASE, + .chip = { + .base = S3C64XX_GPA(0), + .ngpio = S3C64XX_GPIO_A_NR, + .label = "GPA", + }, + }, { + .base = S3C64XX_GPB_BASE, + .chip = { + .base = S3C64XX_GPB(0), + .ngpio = S3C64XX_GPIO_B_NR, + .label = "GPB", + }, + }, { + .base = S3C64XX_GPC_BASE, + .chip = { + .base = S3C64XX_GPC(0), + .ngpio = S3C64XX_GPIO_C_NR, + .label = "GPC", + }, + }, { + .base = S3C64XX_GPD_BASE, + .chip = { + .base = S3C64XX_GPD(0), + .ngpio = S3C64XX_GPIO_D_NR, + .label = "GPD", + }, + }, { + .base = S3C64XX_GPE_BASE, + .chip = { + .base = S3C64XX_GPE(0), + .ngpio = S3C64XX_GPIO_E_NR, + .label = "GPE", + }, + }, { + .base = S3C64XX_GPG_BASE, + .chip = { + .base = S3C64XX_GPG(0), + .ngpio = S3C64XX_GPIO_G_NR, + .label = "GPG", + }, + }, { + .base = S3C64XX_GPM_BASE, + .chip = { + .base = S3C64XX_GPM(0), + .ngpio = S3C64XX_GPIO_M_NR, + .label = "GPM", + }, + }, +}; + +static struct s3c_gpio_chip gpio_4bit2[] = { + { + .base = S3C64XX_GPH_BASE + 0x4, + .chip = { + .base = S3C64XX_GPH(0), + .ngpio = S3C64XX_GPIO_H_NR, + .label = "GPH", + }, + }, { + .base = S3C64XX_GPK_BASE + 0x4, + .chip = { + .base = S3C64XX_GPK(0), + .ngpio = S3C64XX_GPIO_K_NR, + .label = "GPK", + }, + }, { + .base = S3C64XX_GPL_BASE + 0x4, + .chip = { + .base = S3C64XX_GPL(0), + .ngpio = S3C64XX_GPIO_L_NR, + .label = "GPL", + }, + }, +}; + +static struct s3c_gpio_chip gpio_2bit[] = { + { + .base = S3C64XX_GPF_BASE, + .chip = { + .base = S3C64XX_GPF(0), + .ngpio = S3C64XX_GPIO_F_NR, + .label = "GPF", + }, + }, { + .base = S3C64XX_GPI_BASE, + .chip = { + .base = S3C64XX_GPI(0), + .ngpio = S3C64XX_GPIO_I_NR, + .label = "GPI", + }, + }, { + .base = S3C64XX_GPJ_BASE, + .chip = { + .base = S3C64XX_GPJ(0), + .ngpio = S3C64XX_GPIO_J_NR, + .label = "GPJ", + }, + }, { + .base = S3C64XX_GPN_BASE, + .chip = { + .base = S3C64XX_GPN(0), + .ngpio = S3C64XX_GPIO_N_NR, + .label = "GPN", + }, + }, { + .base = S3C64XX_GPO_BASE, + .chip = { + .base = S3C64XX_GPO(0), + .ngpio = S3C64XX_GPIO_O_NR, + .label = "GPO", + }, + }, { + .base = S3C64XX_GPP_BASE, + .chip = { + .base = S3C64XX_GPP(0), + .ngpio = S3C64XX_GPIO_P_NR, + .label = "GPP", + }, + }, { + .base = S3C64XX_GPQ_BASE, + .chip = { + .base = S3C64XX_GPQ(0), + .ngpio = S3C64XX_GPIO_Q_NR, + .label = "GPQ", + }, + }, +}; + +static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip) +{ + chip->chip.direction_input = s3c64xx_gpiolib_4bit_input; + chip->chip.direction_output = s3c64xx_gpiolib_4bit_output; +} + +static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip) +{ + chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input; + chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output; +} + +static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips, + int nr_chips, + void (*fn)(struct s3c_gpio_chip *)) +{ + for (; nr_chips > 0; nr_chips--, chips++) { + if (fn) + (fn)(chips); + s3c_gpiolib_add(chips); + } +} + +static __init int s3c64xx_gpiolib_init(void) +{ + s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit), + s3c64xx_gpiolib_add_4bit); + + s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2), + s3c64xx_gpiolib_add_4bit2); + + s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL); + + return 0; +} + +arch_initcall(s3c64xx_gpiolib_init); diff --git a/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h new file mode 100644 index 00000000000..75b873d8280 --- /dev/null +++ b/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h @@ -0,0 +1,35 @@ +/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * S3C64XX - GPIO register definitions + */ + +#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_H +#define __ASM_PLAT_S3C64XX_REGS_GPIO_H __FILE__ + +/* Base addresses for each of the banks */ + +#define S3C64XX_GPA_BASE (S3C64XX_VA_GPIO + 0x0000) +#define S3C64XX_GPB_BASE (S3C64XX_VA_GPIO + 0x0020) +#define S3C64XX_GPC_BASE (S3C64XX_VA_GPIO + 0x0040) +#define S3C64XX_GPD_BASE (S3C64XX_VA_GPIO + 0x0060) +#define S3C64XX_GPE_BASE (S3C64XX_VA_GPIO + 0x0080) +#define S3C64XX_GPF_BASE (S3C64XX_VA_GPIO + 0x00A0) +#define S3C64XX_GPG_BASE (S3C64XX_VA_GPIO + 0x00C0) +#define S3C64XX_GPH_BASE (S3C64XX_VA_GPIO + 0x00E0) +#define S3C64XX_GPI_BASE (S3C64XX_VA_GPIO + 0x0100) +#define S3C64XX_GPJ_BASE (S3C64XX_VA_GPIO + 0x0120) +#define S3C64XX_GPK_BASE (S3C64XX_VA_GPIO + 0x0800) +#define S3C64XX_GPL_BASE (S3C64XX_VA_GPIO + 0x0810) +#define S3C64XX_GPM_BASE (S3C64XX_VA_GPIO + 0x0820) +#define S3C64XX_GPN_BASE (S3C64XX_VA_GPIO + 0x0830) +#define S3C64XX_GPO_BASE (S3C64XX_VA_GPIO + 0x0140) +#define S3C64XX_GPP_BASE (S3C64XX_VA_GPIO + 0x0160) +#define S3C64XX_GPQ_BASE (S3C64XX_VA_GPIO + 0x0180) + +#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */ + -- cgit v1.2.3-70-g09d2 From 55132b8b4630a4b03d5c5556808c8d3866381536 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 31 Oct 2008 16:14:51 +0000 Subject: [ARM] S3C64XX: Add i2c device setup for I2C device 0 Add the necessary device initialisation information for I2C device 0. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/Kconfig | 11 +++++++++++ arch/arm/plat-s3c64xx/Makefile | 4 ++++ arch/arm/plat-s3c64xx/setup-i2c0.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/setup-i2c0.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 842200abeb3..0bcbe663e2f 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -37,4 +37,15 @@ config CPU_S3C6400_CLOCK Common clock support code for the S3C6400 that is shared by other CPUs in the series, such as the S3C6410. +# platform specific device setup + +config S3C64XX_SETUP_I2C0 + bool + default y + help + Common setup code for i2c bus 0. + + Note, currently since i2c0 is always compiled, this setup helper + is always compiled with it. + endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index a5b7c388351..469f066daab 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -23,3 +23,7 @@ obj-y += gpiolib.o obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o + +# Device setup + +obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o diff --git a/arch/arm/plat-s3c64xx/setup-i2c0.c b/arch/arm/plat-s3c64xx/setup-i2c0.c new file mode 100644 index 00000000000..36448076372 --- /dev/null +++ b/arch/arm/plat-s3c64xx/setup-i2c0.c @@ -0,0 +1,31 @@ +/* linux/arch/arm/plat-s3c64xx/setup-i2c0.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX I2C bus 0 gpio configuration + * + * 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 + +struct platform_device; /* don't need the contents */ + +#include +#include +#include +#include + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S3C64XX_GPB(5), S3C64XX_GPB5_I2C_SCL0); + s3c_gpio_cfgpin(S3C64XX_GPB(6), S3C64XX_GPB6_I2C_SDA0); + s3c_gpio_setpull(S3C64XX_GPB(5), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPB(6), S3C_GPIO_PULL_UP); +} -- cgit v1.2.3-70-g09d2 From f9e2f3453c2357b56870b483fbc4bfd950456625 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 31 Oct 2008 16:14:56 +0000 Subject: [ARM] S3C64XX: Setup functions for i2c bus 1. Add common gpio setup for i2c bus 1 on all current S3C64XX architectures. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/Kconfig | 5 +++++ arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/setup-i2c1.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/setup-i2c1.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 0bcbe663e2f..9037eb47076 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -48,4 +48,9 @@ config S3C64XX_SETUP_I2C0 Note, currently since i2c0 is always compiled, this setup helper is always compiled with it. +config S3C64XX_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. + endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 469f066daab..0a0b8c48a3e 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -27,3 +27,4 @@ obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o # Device setup obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o +obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/plat-s3c64xx/setup-i2c1.c b/arch/arm/plat-s3c64xx/setup-i2c1.c new file mode 100644 index 00000000000..bbe229bd90c --- /dev/null +++ b/arch/arm/plat-s3c64xx/setup-i2c1.c @@ -0,0 +1,31 @@ +/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX I2C bus 1 gpio configuration + * + * 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 + +struct platform_device; /* don't need the contents */ + +#include +#include +#include +#include + +void s3c_i2c1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S3C64XX_GPB(2), S3C64XX_GPB2_I2C_SCL1); + s3c_gpio_cfgpin(S3C64XX_GPB(3), S3C64XX_GPB3_I2C_SDA1); + s3c_gpio_setpull(S3C64XX_GPB(2), S3C_GPIO_PULL_UP); + s3c_gpio_setpull(S3C64XX_GPB(3), S3C_GPIO_PULL_UP); +} -- cgit v1.2.3-70-g09d2 From c7a0401e61447ebc2b7a8923c78875a2c300e548 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 19 Nov 2008 15:41:33 +0000 Subject: [ARM] S3C64XX: Add standard S3C64XX 24BPP LCD GPIO setup Add a standard helper to configure the LCD output pins for a 24BPP display with VSYNC/HSYNC/VDEN. Signed-off-by: Ben Dooks --- arch/arm/plat-s3c64xx/Kconfig | 5 +++++ arch/arm/plat-s3c64xx/Makefile | 1 + arch/arm/plat-s3c64xx/setup-fb-24bpp.c | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 arch/arm/plat-s3c64xx/setup-fb-24bpp.c (limited to 'arch/arm/plat-s3c64xx/Makefile') diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 9037eb47076..203dd730d1c 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -53,4 +53,9 @@ config S3C64XX_SETUP_I2C1 help Common setup code for i2c bus 1. +config S3C64XX_SETUP_FB_24BPP + bool + help + Common setup code for S3C64XX with an 24bpp RGB display helper. + endif diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 0a0b8c48a3e..2e6d79bf8f3 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -28,3 +28,4 @@ obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o +obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o diff --git a/arch/arm/plat-s3c64xx/setup-fb-24bpp.c b/arch/arm/plat-s3c64xx/setup-fb-24bpp.c new file mode 100644 index 00000000000..8e28e448dd2 --- /dev/null +++ b/arch/arm/plat-s3c64xx/setup-fb-24bpp.c @@ -0,0 +1,37 @@ +/* linux/arch/arm/plat-s3c64xx/setup-fb-24bpp.c + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Base S3C64XX setup information for 24bpp LCD framebuffer + * + * 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 + +extern void s3c64xx_fb_gpio_setup_24bpp(void) +{ + unsigned int gpio; + + for (gpio = S3C64XX_GPI(0); gpio <= S3C64XX_GPI(15); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S3C64XX_GPJ(0); gpio <= S3C64XX_GPJ(11); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } +} -- cgit v1.2.3-70-g09d2