summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2011-12-27 23:15:53 +0000
committerArnd Bergmann <arnd@arndb.de>2011-12-27 23:15:53 +0000
commit4eb821999086417ab42a15174b51497122fc406e (patch)
tree3ef7a628f82286f018df7d9d5f48da475d09c349
parent384703b8e6cd4c8ef08512e596024e028c91c339 (diff)
parent0561ceabd0f13871900d116278fe9268aeb714d1 (diff)
Merge branch 'next-samsung-devel-dt1' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into samsung/dt
-rw-r--r--Documentation/devicetree/bindings/arm/insignal-boards.txt8
-rw-r--r--Documentation/devicetree/bindings/arm/samsung-boards.txt8
-rw-r--r--Documentation/devicetree/bindings/dma/arm-pl330.txt30
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-samsung.txt40
-rw-r--r--Documentation/devicetree/bindings/input/samsung-keypad.txt88
-rw-r--r--Documentation/devicetree/bindings/rtc/s3c-rtc.txt20
-rw-r--r--Documentation/devicetree/bindings/serial/samsung_uart.txt14
-rw-r--r--arch/arm/boot/dts/exynos4210-origen.dts137
-rw-r--r--arch/arm/boot/dts/exynos4210-smdkv310.dts182
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi397
-rw-r--r--arch/arm/mach-exynos/Kconfig24
-rw-r--r--arch/arm/mach-exynos/Makefile5
-rw-r--r--arch/arm/mach-exynos/clock.c141
-rw-r--r--arch/arm/mach-exynos/cpu.c17
-rw-r--r--arch/arm/mach-exynos/dma.c229
-rw-r--r--arch/arm/mach-exynos/include/mach/entry-macro.S1
-rw-r--r--arch/arm/mach-exynos/include/mach/irqs.h8
-rw-r--r--arch/arm/mach-exynos/init.c21
-rw-r--r--arch/arm/mach-exynos/mach-exynos4-dt.c85
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c22
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c24
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c6
-rw-r--r--arch/arm/mach-s3c2412/clock.c7
-rw-r--r--arch/arm/mach-s3c2440/clock.c44
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c22
-rw-r--r--arch/arm/mach-s3c2440/mach-at2440evb.c22
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c24
-rw-r--r--arch/arm/mach-s3c2440/mach-rx1950.c18
-rw-r--r--arch/arm/mach-s3c2440/mach-rx3715.c19
-rw-r--r--arch/arm/mach-s3c64xx/clock.c37
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6440.c32
-rw-r--r--arch/arm/mach-s5p64x0/clock-s5p6450.c32
-rw-r--r--arch/arm/mach-s5p64x0/dma.c227
-rw-r--r--arch/arm/mach-s5p64x0/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-s5p64x0/init.c31
-rw-r--r--arch/arm/mach-s5pc100/clock.c33
-rw-r--r--arch/arm/mach-s5pc100/dma.c247
-rw-r--r--arch/arm/mach-s5pc100/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-s5pv210/clock.c107
-rw-r--r--arch/arm/mach-s5pv210/dma.c241
-rw-r--r--arch/arm/mach-s5pv210/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-s5pv210/init.c19
-rw-r--r--arch/arm/plat-s3c24xx/s3c2443-clock.c23
-rw-r--r--arch/arm/plat-samsung/dma-ops.c15
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-ops.h1
-rw-r--r--arch/arm/plat-samsung/include/plat/dma-pl330.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/irqs.h3
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-serial.h45
-rw-r--r--drivers/dma/pl330.c99
-rw-r--r--drivers/gpio/gpio-samsung.c72
-rw-r--r--drivers/input/keyboard/samsung-keypad.c174
-rw-r--r--drivers/rtc/rtc-s3c.c21
-rw-r--r--drivers/tty/serial/Kconfig45
-rw-r--r--drivers/tty/serial/Makefile5
-rw-r--r--drivers/tty/serial/s3c2410.c115
-rw-r--r--drivers/tty/serial/s3c2412.c149
-rw-r--r--drivers/tty/serial/s3c2440.c178
-rw-r--r--drivers/tty/serial/s3c6400.c149
-rw-r--r--drivers/tty/serial/s5pv210.c158
-rw-r--r--drivers/tty/serial/samsung.c639
-rw-r--r--drivers/tty/serial/samsung.h32
-rw-r--r--include/linux/amba/pl330.h15
62 files changed, 2423 insertions, 2193 deletions
diff --git a/Documentation/devicetree/bindings/arm/insignal-boards.txt b/Documentation/devicetree/bindings/arm/insignal-boards.txt
new file mode 100644
index 00000000000..524c3dc5d80
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/insignal-boards.txt
@@ -0,0 +1,8 @@
+* Insignal's Exynos4210 based Origen evaluation board
+
+Origen low-cost evaluation board is based on Samsung's Exynos4210 SoC.
+
+Required root node properties:
+ - compatible = should be one or more of the following.
+ (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
+ (b) "samsung,exynos4210" - for boards based on Exynos4210 SoC.
diff --git a/Documentation/devicetree/bindings/arm/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung-boards.txt
new file mode 100644
index 00000000000..0bf68be56fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung-boards.txt
@@ -0,0 +1,8 @@
+* Samsung's Exynos4210 based SMDKV310 evaluation board
+
+SMDKV310 evaluation board is based on Samsung's Exynos4210 SoC.
+
+Required root node properties:
+ - compatible = should be one or more of the following.
+ (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
+ (b) "samsung,exynos4210" - for boards based on Exynos4210 SoC.
diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt b/Documentation/devicetree/bindings/dma/arm-pl330.txt
new file mode 100644
index 00000000000..a4cd273b2a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt
@@ -0,0 +1,30 @@
+* ARM PrimeCell PL330 DMA Controller
+
+The ARM PrimeCell PL330 DMA controller can move blocks of memory contents
+between memory and peripherals or memory to memory.
+
+Required properties:
+ - compatible: should include both "arm,pl330" and "arm,primecell".
+ - reg: physical base address of the controller and length of memory mapped
+ region.
+ - interrupts: interrupt number to the cpu.
+
+Example:
+
+ pdma0: pdma@12680000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x12680000 0x1000>;
+ interrupts = <99>;
+ };
+
+Client drivers (device nodes requiring dma transfers from dev-to-mem or
+mem-to-dev) should specify the DMA channel numbers using a two-value pair
+as shown below.
+
+ [property name] = <[phandle of the dma controller] [dma request id]>;
+
+ where 'dma request id' is the dma request number which is connected
+ to the client controller. The 'property name' is recommended to be
+ of the form <name>-dma-channel.
+
+ Example: tx-dma-channel = <&pdma0 12>;
diff --git a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
new file mode 100644
index 00000000000..8f50fe5e6c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
@@ -0,0 +1,40 @@
+Samsung Exynos4 GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "samsung,exynos4-gpio>".
+
+- reg: Physical base address of the controller and length of memory mapped
+ region.
+
+- #gpio-cells: Should be 4. The syntax of the gpio specifier used by client nodes
+ should be the following with values derived from the SoC user manual.
+ <[phandle of the gpio controller node]
+ [pin number within the gpio controller]
+ [mux function]
+ [pull up/down]
+ [drive strength]>
+
+ Values for gpio specifier:
+ - Pin number: is a value between 0 to 7.
+ - Pull Up/Down: 0 - Pull Up/Down Disabled.
+ 1 - Pull Down Enabled.
+ 3 - Pull Up Enabled.
+ - Drive Strength: 0 - 1x,
+ 1 - 3x,
+ 2 - 2x,
+ 3 - 4x
+
+- gpio-controller: Specifies that the node is a gpio controller.
+- #address-cells: should be 1.
+- #size-cells: should be 1.
+
+Example:
+
+ gpa0: gpio-controller@11400000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400000 0x20>;
+ #gpio-cells = <4>;
+ gpio-controller;
+ };
diff --git a/Documentation/devicetree/bindings/input/samsung-keypad.txt b/Documentation/devicetree/bindings/input/samsung-keypad.txt
new file mode 100644
index 00000000000..ce3e394c0e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/samsung-keypad.txt
@@ -0,0 +1,88 @@
+* Samsung's Keypad Controller device tree bindings
+
+Samsung's Keypad controller is used to interface a SoC with a matrix-type
+keypad device. The keypad controller supports multiple row and column lines.
+A key can be placed at each intersection of a unique row and a unique column.
+The keypad controller can sense a key-press and key-release and report the
+event using a interrupt to the cpu.
+
+Required SoC Specific Properties:
+- compatible: should be one of the following
+ - "samsung,s3c6410-keypad": For controllers compatible with s3c6410 keypad
+ controller.
+ - "samsung,s5pv210-keypad": For controllers compatible with s5pv210 keypad
+ controller.
+
+- reg: physical base address of the controller and length of memory mapped
+ region.
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:
+- samsung,keypad-num-rows: Number of row lines connected to the keypad
+ controller.
+
+- samsung,keypad-num-columns: Number of column lines connected to the
+ keypad controller.
+
+- row-gpios: List of gpios used as row lines. The gpio specifier for
+ this property depends on the gpio controller to which these row lines
+ are connected.
+
+- col-gpios: List of gpios used as column lines. The gpio specifier for
+ this property depends on the gpio controller to which these column
+ lines are connected.
+
+- Keys represented as child nodes: Each key connected to the keypad
+ controller is represented as a child node to the keypad controller
+ device node and should include the following properties.
+ - keypad,row: the row number to which the key is connected.
+ - keypad,column: the column number to which the key is connected.
+ - linux,code: the key-code to be reported when the key is pressed
+ and released.
+
+Optional Properties specific to linux:
+- linux,keypad-no-autorepeat: do no enable autorepeat feature.
+- linux,keypad-wakeup: use any event on keypad as wakeup event.
+
+
+Example:
+ keypad@100A0000 {
+ compatible = "samsung,s5pv210-keypad";
+ reg = <0x100A0000 0x100>;
+ interrupts = <173>;
+ samsung,keypad-num-rows = <2>;
+ samsung,keypad-num-columns = <8>;
+ linux,input-no-autorepeat;
+ linux,input-wakeup;
+
+ row-gpios = <&gpx2 0 3 3 0
+ &gpx2 1 3 3 0>;
+
+ col-gpios = <&gpx1 0 3 0 0
+ &gpx1 1 3 0 0
+ &gpx1 2 3 0 0
+ &gpx1 3 3 0 0
+ &gpx1 4 3 0 0
+ &gpx1 5 3 0 0
+ &gpx1 6 3 0 0
+ &gpx1 7 3 0 0>;
+
+ key_1 {
+ keypad,row = <0>;
+ keypad,column = <3>;
+ linux,code = <2>;
+ };
+
+ key_2 {
+ keypad,row = <0>;
+ keypad,column = <4>;
+ linux,code = <3>;
+ };
+
+ key_3 {
+ keypad,row = <0>;
+ keypad,column = <5>;
+ linux,code = <4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
new file mode 100644
index 00000000000..90ec45fd33e
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt
@@ -0,0 +1,20 @@
+* Samsung's S3C Real Time Clock controller
+
+Required properties:
+- compatible: should be one of the following.
+ * "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc.
+ * "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc.
+- reg: physical base address of the controller and length of memory mapped
+ region.
+- interrupts: Two interrupt numbers to the cpu should be specified. First
+ interrupt number is the rtc alarm interupt and second interrupt number
+ is the rtc tick interrupt. The number of cells representing a interrupt
+ depends on the parent interrupt controller.
+
+Example:
+
+ rtc@10070000 {
+ compatible = "samsung,s3c6410-rtc";
+ reg = <0x10070000 0x100>;
+ interrupts = <44 0 45 0>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.txt b/Documentation/devicetree/bindings/serial/samsung_uart.txt
new file mode 100644
index 00000000000..2c8a17cf5cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/samsung_uart.txt
@@ -0,0 +1,14 @@
+* Samsung's UART Controller
+
+The Samsung's UART controller is used for interfacing SoC with serial communicaion
+devices.
+
+Required properties:
+- compatible: should be
+ - "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports.
+
+- reg: base physical address of the controller and length of memory mapped
+ region.
+
+- interrupts: interrupt number to the cpu. The interrupt specifier format depends
+ on the interrupt controller parent.
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
new file mode 100644
index 00000000000..b8c476384ee
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -0,0 +1,137 @@
+/*
+ * Samsung's Exynos4210 based Origen board device tree source
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2010-2011 Linaro Ltd.
+ * www.linaro.org
+ *
+ * Device tree source file for Insignal's Origen board which is based on
+ * Samsung's Exynos4210 SoC.
+ *
+ * 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.
+*/
+
+/dts-v1/;
+/include/ "exynos4210.dtsi"
+
+/ {
+ model = "Insignal Origen evaluation board based on Exynos4210";
+ compatible = "insignal,origen", "samsung,exynos4210";
+
+ memory {
+ reg = <0x40000000 0x40000000>;
+ };
+
+ chosen {
+ bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
+ };
+
+ sdhci@12530000 {
+ samsung,sdhci-bus-width = <4>;
+ linux,mmc_cap_4_bit_data;
+ samsung,sdhci-cd-internal;
+ gpio-cd = <&gpk2 2 2 3 3>;
+ gpios = <&gpk2 0 2 0 3>,
+ <&gpk2 1 2 0 3>,
+ <&gpk2 3 2 3 3>,
+ <&gpk2 4 2 3 3>,
+ <&gpk2 5 2 3 3>,
+ <&gpk2 6 2 3 3>;
+ };
+
+ sdhci@12510000 {
+ samsung,sdhci-bus-width = <4>;
+ linux,mmc_cap_4_bit_data;
+ samsung,sdhci-cd-internal;
+ gpio-cd = <&gpk0 2 2 3 3>;
+ gpios = <&gpk0 0 2 0 3>,
+ <&gpk0 1 2 0 3>,
+ <&gpk0 3 2 3 3>,
+ <&gpk0 4 2 3 3>,
+ <&gpk0 5 2 3 3>,
+ <&gpk0 6 2 3 3>;
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ up {
+ label = "Up";
+ gpios = <&gpx2 0 0 0 2>;
+ linux,code = <103>;
+ };
+
+ down {
+ label = "Down";
+ gpios = <&gpx2 1 0 0 2>;
+ linux,code = <108>;
+ };
+
+ back {
+ label = "Back";
+ gpios = <&gpx1 7 0 0 2>;
+ linux,code = <158>;
+ };
+
+ home {
+ label = "Home";
+ gpios = <&gpx1 6 0 0 2>;
+ linux,code = <102>;
+ };
+
+ menu {
+ label = "Menu";
+ gpios = <&gpx1 5 0 0 2>;
+ linux,code = <139>;
+ };
+ };
+
+ keypad@100A0000 {
+ status = "disabled";
+ };
+
+ sdhci@12520000 {
+ status = "disabled";
+ };
+
+ sdhci@12540000 {
+ status = "disabled";
+ };
+
+ i2c@13860000 {
+ status = "disabled";
+ };
+
+ i2c@13870000 {
+ status = "disabled";
+ };
+
+ i2c@13880000 {
+ status = "disabled";
+ };
+
+ i2c@13890000 {
+ status = "disabled";
+ };
+
+ i2c@138A0000 {
+ status = "disabled";
+ };
+
+ i2c@138B0000 {
+ status = "disabled";
+ };
+
+ i2c@138C0000 {
+ status = "disabled";
+ };
+
+ i2c@138D0000 {
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts
new file mode 100644
index 00000000000..27afc8e535c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -0,0 +1,182 @@
+/*
+ * Samsung's Exynos4210 based SMDKV310 board device tree source
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2010-2011 Linaro Ltd.
+ * www.linaro.org
+ *
+ * Device tree source file for Samsung's SMDKV310 board which is based on
+ * Samsung's Exynos4210 SoC.
+ *
+ * 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.
+*/
+
+/dts-v1/;
+/include/ "exynos4210.dtsi"
+
+/ {
+ model = "Samsung smdkv310 evaluation board based on Exynos4210";
+ compatible = "samsung,smdkv310", "samsung,exynos4210";
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ chosen {
+ bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
+ };
+
+ sdhci@12530000 {
+ samsung,sdhci-bus-width = <4>;
+ linux,mmc_cap_4_bit_data;
+ samsung,sdhci-cd-internal;
+ gpio-cd = <&gpk2 2 2 3 3>;
+ gpios = <&gpk2 0 2 0 3>,
+ <&gpk2 1 2 0 3>,
+ <&gpk2 3 2 3 3>,
+ <&gpk2 4 2 3 3>,
+ <&gpk2 5 2 3 3>,
+ <&gpk2 6 2 3 3>;
+ };
+
+ keypad@100A0000 {
+ samsung,keypad-num-rows = <2>;
+ samsung,keypad-num-columns = <8>;
+ linux,keypad-no-autorepeat;
+ linux,keypad-wakeup;
+
+ row-gpios = <&gpx2 0 3 3 0>,
+ <&gpx2 1 3 3 0>;
+
+ col-gpios = <&gpx1 0 3 0 0>,
+ <&gpx1 1 3 0 0>,
+ <&gpx1 2 3 0 0>,
+ <&gpx1 3 3 0 0>,
+ <&gpx1 4 3 0 0>,
+ <&gpx1 5 3 0 0>,
+ <&gpx1 6 3 0 0>,
+ <&gpx1 7 3 0 0>;
+
+ key_1 {
+ keypad,row = <0>;
+ keypad,column = <3>;
+ linux,code = <2>;
+ };
+
+ key_2 {
+ keypad,row = <0>;
+ keypad,column = <4>;
+ linux,code = <3>;
+ };
+
+ key_3 {
+ keypad,row = <0>;
+ keypad,column = <5>;
+ linux,code = <4>;
+ };
+
+ key_4 {
+ keypad,row = <0>;
+ keypad,column = <6>;
+ linux,code = <5>;
+ };
+
+ key_5 {
+ keypad,row = <0>;
+ keypad,column = <7>;
+ linux,code = <6>;
+ };
+
+ key_a {
+ keypad,row = <1>;
+ keypad,column = <3>;
+ linux,code = <30>;
+ };
+
+ key_b {
+ keypad,row = <1>;
+ keypad,column = <4>;
+ linux,code = <48>;
+ };
+
+ key_c {
+ keypad,row = <1>;
+ keypad,column = <5>;
+ linux,code = <46>;
+ };
+
+ key_d {
+ keypad,row = <1>;
+ keypad,column = <6>;
+ linux,code = <32>;
+ };
+
+ key_e {
+ keypad,row = <1>;
+ keypad,column = <7>;
+ linux,code = <18>;
+ };
+ };
+
+ i2c@13860000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ samsung,i2c-sda-delay = <100>;
+ samsung,i2c-max-bus-freq = <20000>;
+ gpios = <&gpd1 0 2 3 0>,
+ <&gpd1 1 2 3 0>;
+
+ eeprom@50 {
+ compatible = "samsung,24ad0xd1";
+ reg = <0x50>;
+ };
+
+ eeprom@52 {
+ compatible = "samsung,24ad0xd1";
+ reg = <0x52>;
+ };
+ };
+
+ sdhci@12510000 {
+ status = "disabled";
+ };
+
+ sdhci@12520000 {
+ status = "disabled";
+ };
+
+ sdhci@12540000 {
+ status = "disabled";
+ };
+
+ i2c@13870000 {
+ status = "disabled";
+ };
+
+ i2c@13880000 {
+ status = "disabled";
+ };
+
+ i2c@13890000 {
+ status = "disabled";
+ };
+
+ i2c@138A0000 {
+ status = "disabled";
+ };
+
+ i2c@138B0000 {
+ status = "disabled";
+ };
+
+ i2c@138C0000 {
+ status = "disabled";
+ };
+
+ i2c@138D0000 {
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
new file mode 100644
index 00000000000..63d7578856c
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -0,0 +1,397 @@
+/*
+ * Samsung's Exynos4210 SoC device tree source
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2010-2011 Linaro Ltd.
+ * www.linaro.org
+ *
+ * Samsung's Exynos4210 SoC device nodes are listed in this file. Exynos4210
+ * based board files can include this file and provide values for board specfic
+ * bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4210 SoC. As device tree coverage for Exynos4210 increases, additional
+ * nodes can be added to this file.
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+ compatible = "samsung,exynos4210";
+ interrupt-parent = <&gic>;
+
+ gic:interrupt-controller@10490000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x10490000 0x1000>, <0x10480000 0x100>;
+ };
+
+ watchdog@10060000 {
+ compatible = "samsung,s3c2410-wdt";
+ reg = <0x10060000 0x100>;
+ interrupts = <0 43 0>;
+ };
+
+ rtc@10070000 {
+ compatible = "samsung,s3c6410-rtc";
+ reg = <0x10070000 0x100>;
+ interrupts = <0 44 0>, <0 45 0>;
+ };
+
+ keypad@100A0000 {
+ compatible = "samsung,s5pv210-keypad";
+ reg = <0x100A0000 0x100>;
+ interrupts = <0 109 0>;
+ };
+
+ sdhci@12510000 {
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12510000 0x100>;
+ interrupts = <0 73 0>;
+ };
+
+ sdhci@12520000 {
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12520000 0x100>;
+ interrupts = <0 74 0>;
+ };
+
+ sdhci@12530000 {
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12530000 0x100>;
+ interrupts = <0 75 0>;
+ };
+
+ sdhci@12540000 {
+ compatible = "samsung,exynos4210-sdhci";
+ reg = <0x12540000 0x100>;
+ interrupts = <0 76 0>;
+ };
+
+ serial@13800000 {
+ compatible = "samsung,exynos4210-uart";
+ reg = <0x13800000 0x100>;
+ interrupts = <0 52 0>;
+ };
+
+ serial@13810000 {
+ compatible = "samsung,exynos4210-uart";
+ reg = <0x13810000 0x100>;
+ interrupts = <0 53 0>;
+ };
+
+ serial@13820000 {
+ compatible = "samsung,exynos4210-uart";
+ reg = <0x13820000 0x100>;
+ interrupts = <0 54 0>;
+ };
+
+ serial@13830000 {
+ compatible = "samsung,exynos4210-uart";
+ reg = <0x13830000 0x100>;
+ interrupts = <0 55 0>;
+ };
+
+ i2c@13860000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x13860000 0x100>;
+ interrupts = <0 58 0>;
+ };
+
+ i2c@13870000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x13870000 0x100>;
+ interrupts = <0 59 0>;
+ };
+
+ i2c@13880000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x13880000 0x100>;
+ interrupts = <0 60 0>;
+ };
+
+ i2c@13890000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x13890000 0x100>;
+ interrupts = <0 61 0>;
+ };
+
+ i2c@138A0000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x138A0000 0x100>;
+ interrupts = <0 62 0>;
+ };
+
+ i2c@138B0000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x138B0000 0x100>;
+ interrupts = <0 63 0>;
+ };
+
+ i2c@138C0000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x138C0000 0x100>;
+ interrupts = <0 64 0>;
+ };
+
+ i2c@138D0000 {
+ compatible = "samsung,s3c2440-i2c";
+ reg = <0x138D0000 0x100>;
+ interrupts = <0 65 0>;
+ };
+
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ pdma0: pdma@12680000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x12680000 0x1000>;
+ interrupts = <0 35 0>;
+ };
+
+ pdma1: pdma@12690000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x12690000 0x1000>;
+ interrupts = <0 36 0>;
+ };
+ };
+
+ gpio-controllers {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ gpio-controller;
+ ranges;
+
+ gpa0: gpio-controller@11400000 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400000 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpa1: gpio-controller@11400020 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400020 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpb: gpio-controller@11400040 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400040 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpc0: gpio-controller@11400060 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400060 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpc1: gpio-controller@11400080 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400080 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpd0: gpio-controller@114000A0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114000A0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpd1: gpio-controller@114000C0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114000C0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpe0: gpio-controller@114000E0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114000E0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpe1: gpio-controller@11400100 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400100 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpe2: gpio-controller@11400120 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400120 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpe3: gpio-controller@11400140 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400140 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpe4: gpio-controller@11400160 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400160 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpf0: gpio-controller@11400180 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11400180 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpf1: gpio-controller@114001A0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114001A0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpf2: gpio-controller@114001C0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114001C0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpf3: gpio-controller@114001E0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x114001E0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpj0: gpio-controller@11000000 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000000 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpj1: gpio-controller@11000020 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000020 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpk0: gpio-controller@11000040 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000040 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpk1: gpio-controller@11000060 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000060 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpk2: gpio-controller@11000080 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000080 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpk3: gpio-controller@110000A0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x110000A0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpl0: gpio-controller@110000C0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x110000C0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpl1: gpio-controller@110000E0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x110000E0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpl2: gpio-controller@11000100 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000100 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy0: gpio-controller@11000120 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000120 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy1: gpio-controller@11000140 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000140 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy2: gpio-controller@11000160 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000160 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy3: gpio-controller@11000180 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000180 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy4: gpio-controller@110001A0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x110001A0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy5: gpio-controller@110001C0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x110001C0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpy6: gpio-controller@110001E0 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x110001E0 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpx0: gpio-controller@11000C00 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000C00 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpx1: gpio-controller@11000C20 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000C20 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpx2: gpio-controller@11000C40 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000C40 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpx3: gpio-controller@11000C60 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x11000C60 0x20>;
+ #gpio-cells = <4>;
+ };
+
+ gpz: gpio-controller@03860000 {
+ compatible = "samsung,exynos4-gpio";
+ reg = <0x03860000 0x20>;
+ #gpio-cells = <4>;
+ };
+ };
+};
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 724ec0f3560..0afcc3b0f87 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -57,6 +57,11 @@ config EXYNOS4_MCT
help
Use MCT (Multi Core Timer) as kernel timers
+config EXYNOS4_DEV_DMA
+ bool
+ help
+ Compile in amba device definitions for DMA controller
+
config EXYNOS4_DEV_AHCI
bool
help
@@ -177,6 +182,7 @@ config MACH_SMDKV310
select SAMSUNG_DEV_BACKLIGHT
select EXYNOS4_DEV_AHCI
select SAMSUNG_DEV_KEYPAD
+ select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_PD
select SAMSUNG_DEV_PWM
select EXYNOS4_DEV_SYSMMU
@@ -197,6 +203,7 @@ config MACH_ARMLEX4210
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select EXYNOS4_DEV_AHCI
+ select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_SYSMMU
select EXYNOS4_SETUP_SDHCI
help
@@ -222,6 +229,7 @@ config MACH_UNIVERSAL_C210
select S5P_DEV_MFC
select S5P_DEV_ONENAND
select S5P_DEV_TV
+ select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
@@ -255,6 +263,7 @@ config MACH_NURI
select S5P_DEV_MFC
select S5P_DEV_USB_EHCI
select S5P_SETUP_MIPIPHY
+ select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_FIMC
select EXYNOS4_SETUP_FIMD0
@@ -287,6 +296,7 @@ config MACH_ORIGEN
select S5P_DEV_USB_EHCI
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
+ select EXYNOS4_DEV_DMA
select EXYNOS4_DEV_PD
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_SDHCI
@@ -327,6 +337,20 @@ config MACH_SMDK4412
Machine support for Samsung SMDK4412
endif
+comment "Flattened Device Tree based board for Exynos4 based SoC"
+
+config MACH_EXYNOS4_DT
+ bool "Samsung Exynos4 Machine using device tree"
+ select CPU_EXYNOS4210
+ select USE_OF
+ select ARM_AMBA
+ select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
+ help
+ Machine support for Samsung Exynos4 machine with device tree enabled.
+ Select this if a fdt blob is available for the Exynos4 SoC based board.
+ Note: This is under development and not all peripherals can be supported
+ with this machine file.
+
if ARCH_EXYNOS4
comment "Configuration for HSMMC 8-bit bus width"
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 59069a35e40..8d85ae635ac 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,7 +13,7 @@ obj- :=
# Core support for EXYNOS4 system
obj-$(CONFIG_ARCH_EXYNOS4) += cpu.o init.o clock.o irq-combiner.o setup-i2c0.o
-obj-$(CONFIG_ARCH_EXYNOS4) += irq-eint.o dma.o pmu.o
+obj-$(CONFIG_ARCH_EXYNOS4) += irq-eint.o pmu.o
obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o
obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o
obj-$(CONFIG_PM) += pm.o
@@ -37,6 +37,8 @@ obj-$(CONFIG_MACH_ORIGEN) += mach-origen.o
obj-$(CONFIG_MACH_SMDK4212) += mach-smdk4x12.o
obj-$(CONFIG_MACH_SMDK4412) += mach-smdk4x12.o
+obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o
+
# device support
obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o
@@ -44,6 +46,7 @@ obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
+obj-$(CONFIG_EXYNOS4_DEV_DMA) += dma.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
index 2894f0adef5..7dee8694486 100644
--- a/arch/arm/mach-exynos/clock.c
+++ b/arch/arm/mach-exynos/clock.c
@@ -553,16 +553,6 @@ static struct clk init_clocks_off[] = {
.enable = exynos4_clk_dac_ctrl,
.ctrlbit = (1 << 0),
}, {
- .name = "dma",
- .devname = "dma-pl330.0",
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 0),
- }, {
- .name = "dma",
- .devname = "dma-pl330.1",
- .enable = exynos4_clk_ip_fsys_ctrl,
- .ctrlbit = (1 << 1),
- }, {
.name = "adc",
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 15),
@@ -778,6 +768,20 @@ static struct clk init_clocks[] = {
}
};
+static struct clk clk_pdma0 = {
+ .name = "dma",
+ .devname = "dma-pl330.0",
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 0),
+};
+
+static struct clk clk_pdma1 = {
+ .name = "dma",
+ .devname = "dma-pl330.1",
+ .enable = exynos4_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 1),
+};
+
struct clk *clkset_group_list[] = {
[0] = &clk_ext_xtal_mux,
[1] = &clk_xusbxti,
@@ -1009,46 +1013,6 @@ static struct clksrc_clk clk_dout_mmc4 = {
static struct clksrc_clk clksrcs[] = {
{
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.0",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 0),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.1",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 4),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.2",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 8),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.3",
- .enable = exynos4_clksrc_mask_peril0_ctrl,
- .ctrlbit = (1 << 12),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
- }, {
.clk = {
.name = "sclk_pwm",
.enable = exynos4_clksrc_mask_peril0_ctrl,
@@ -1237,6 +1201,54 @@ static struct clksrc_clk clksrcs[] = {
}
};
+static struct clksrc_clk clk_sclk_uart0 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "exynos4210-uart.0",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 0),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_sclk_uart1 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "exynos4210-uart.1",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 4),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk clk_sclk_uart2 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "exynos4210-uart.2",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 8),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_sclk_uart3 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "exynos4210-uart.3",
+ .enable = exynos4_clksrc_mask_peril0_ctrl,
+ .ctrlbit = (1 << 12),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
+};
+
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -1271,6 +1283,27 @@ static struct clksrc_clk *sysclks[] = {
&clk_mout_mfc1,
};
+static struct clk *clk_cdev[] = {
+ &clk_pdma0,
+ &clk_pdma1,
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &clk_sclk_uart0,
+ &clk_sclk_uart1,
+ &clk_sclk_uart2,
+ &clk_sclk_uart3,
+};
+
+static struct clk_lookup exynos4_clk_lookup[] = {
+ CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &clk_sclk_uart0.clk),
+ CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &clk_sclk_uart1.clk),
+ CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &clk_sclk_uart2.clk),
+ CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &clk_sclk_uart3.clk),
+ CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0),
+ CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1),
+};
+
static int xtal_rate;
static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
@@ -1478,11 +1511,19 @@ void __init exynos4_register_clocks(void)
for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
s3c_register_clksrc(sclk_tv[ptr], 1);
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+ s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
+ for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
+ s3c_disable_clocks(clk_cdev[ptr], 1);
+
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
register_syscore_ops(&exynos4_clock_syscore_ops);
s3c24xx_register_clock(&dummy_apb_pclk);
diff --git a/arch/arm/mach-exynos/cpu.c b/arch/arm/mach-exynos/cpu.c
index 90ec247f3b3..0eb7b6a6903 100644
--- a/arch/arm/mach-exynos/cpu.c
+++ b/arch/arm/mach-exynos/cpu.c
@@ -10,6 +10,8 @@
#include <linux/sched.h>
#include <linux/sysdev.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -218,13 +220,26 @@ static void exynos4_gic_irq_fix_base(struct irq_data *d)
(gic_bank_offset * smp_processor_id());
}
+#ifdef CONFIG_OF
+static const struct of_device_id exynos4_dt_irq_match[] = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ {},
+};
+#endif
+
void __init exynos4_init_irq(void)
{
int irq;
gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
- gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+ if (!of_have_populated_dt())
+ gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+ else
+ of_irq_init(exynos4_dt_irq_match);
+#endif
+
gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
index 9667c61e64f..b10fcd270f0 100644
--- a/arch/arm/mach-exynos/dma.c
+++ b/arch/arm/mach-exynos/dma.c
@@ -24,6 +24,7 @@
#include <linux/dma-mapping.h>
#include <linux/amba/bus.h>
#include <linux/amba/pl330.h>
+#include <linux/of.h>
#include <asm/irq.h>
#include <plat/devs.h>
@@ -35,95 +36,42 @@
static u64 dma_dmamask = DMA_BIT_MASK(32);
-struct dma_pl330_peri pdma0_peri[28] = {
- {
- .peri_id = (u8)DMACH_PCM0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ0,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ2,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0S_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART4_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART4_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS4_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS4_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_AC97_MICIN,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_AC97_PCMIN,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_AC97_PCMOUT,
- .rqtype = MEMTODEV,
- },
+u8 pdma0_peri[] = {
+ DMACH_PCM0_RX,
+ DMACH_PCM0_TX,
+ DMACH_PCM2_RX,
+ DMACH_PCM2_TX,
+ DMACH_MSM_REQ0,
+ DMACH_MSM_REQ2,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI2_RX,
+ DMACH_SPI2_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S2_RX,
+ DMACH_I2S2_TX,
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART4_RX,
+ DMACH_UART4_TX,
+ DMACH_SLIMBUS0_RX,
+ DMACH_SLIMBUS0_TX,
+ DMACH_SLIMBUS2_RX,
+ DMACH_SLIMBUS2_TX,
+ DMACH_SLIMBUS4_RX,
+ DMACH_SLIMBUS4_TX,
+ DMACH_AC97_MICIN,
+ DMACH_AC97_PCMIN,
+ DMACH_AC97_PCMOUT,
};
struct dma_pl330_platdata exynos4_pdma0_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
- .peri = pdma0_peri,
+ .peri_id = pdma0_peri,
};
struct amba_device exynos4_device_pdma0 = {
@@ -142,86 +90,37 @@ struct amba_device exynos4_device_pdma0 = {
.periphid = 0x00041330,
};
-struct dma_pl330_peri pdma1_peri[25] = {
- {
- .peri_id = (u8)DMACH_PCM0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ1,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ3,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0S_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS5_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SLIMBUS5_TX,
- .rqtype = MEMTODEV,
- },
+u8 pdma1_peri[] = {
+ DMACH_PCM0_RX,
+ DMACH_PCM0_TX,
+ DMACH_PCM1_RX,
+ DMACH_PCM1_TX,
+ DMACH_MSM_REQ1,
+ DMACH_MSM_REQ3,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_SLIMBUS1_RX,
+ DMACH_SLIMBUS1_TX,
+ DMACH_SLIMBUS3_RX,
+ DMACH_SLIMBUS3_TX,
+ DMACH_SLIMBUS5_RX,
+ DMACH_SLIMBUS5_TX,
};
struct dma_pl330_platdata exynos4_pdma1_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
- .peri = pdma1_peri,
+ .peri_id = pdma1_peri,
};
struct amba_device exynos4_device_pdma1 = {
@@ -242,7 +141,15 @@ struct amba_device exynos4_device_pdma1 = {
static int __init exynos4_dma_init(void)
{
+ if (of_have_populated_dt())
+ return 0;
+
+ dma_cap_set(DMA_SLAVE, exynos4_pdma0_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, exynos4_pdma0_pdata.cap_mask);
amba_device_register(&exynos4_device_pdma0, &iomem_resource);
+
+ dma_cap_set(DMA_SLAVE, exynos4_pdma1_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, exynos4_pdma1_pdata.cap_mask);
amba_device_register(&exynos4_device_pdma1, &iomem_resource);
return 0;
diff --git a/arch/arm/mach-exynos/include/mach/entry-macro.S b/arch/arm/mach-exynos/include/mach/entry-macro.S
index f5e9fd8e37b..d7dfcd7eb92 100644
--- a/arch/arm/mach-exynos/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos/include/mach/entry-macro.S
@@ -72,7 +72,6 @@
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
- addne \irqnr, \irqnr, #32
.endm
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index dfd4b7eecb9..713dd5251c6 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -17,13 +17,13 @@
/* PPI: Private Peripheral Interrupt */
-#define IRQ_PPI(x) S5P_IRQ(x+16)
+#define IRQ_PPI(x) (x+16)
#define IRQ_MCT_LOCALTIMER IRQ_PPI(12)
/* SPI: Shared Peripheral Interrupt */
-#define IRQ_SPI(x) S5P_IRQ(x+32)
+#define IRQ_SPI(x) (x+32)
#define IRQ_EINT0 IRQ_SPI(16)
#define IRQ_EINT1 IRQ_SPI(17)
@@ -163,7 +163,9 @@
#define IRQ_GPIO2_NR_GROUPS 9
#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
+#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64)
+
/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_GPIO_END + 64)
+#define NR_IRQS (IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-exynos/init.c b/arch/arm/mach-exynos/init.c
index a8a83e3881a..5b35978029b 100644
--- a/arch/arm/mach-exynos/init.c
+++ b/arch/arm/mach-exynos/init.c
@@ -14,29 +14,14 @@
#include <plat/devs.h>
#include <plat/regs-serial.h>
-static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = {
- [0] = {
- .name = "uclk1",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
-};
-
/* uart registration process */
void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
struct s3c2410_uartcfg *tcfg = cfg;
u32 ucnt;
- for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
- if (!tcfg->clocks) {
- tcfg->has_fracval = 1;
- tcfg->clocks = exynos4_serial_clocks;
- tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
- }
- tcfg->flags |= NO_NEED_CHECK_CLKSRC;
- }
+ for (ucnt = 0; ucnt < no; ucnt++, tcfg++)
+ tcfg->has_fracval = 1;
- s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+ s3c24xx_init_uartdevs("exynos4210-uart", s5p_uart_resources, cfg, no);
}
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
new file mode 100644
index 00000000000..85fa02767d6
--- /dev/null
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -0,0 +1,85 @@
+/*
+ * Samsung's Exynos4210 flattened device tree enabled machine
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Copyright (c) 2010-2011 Linaro Ltd.
+ * www.linaro.org
+ *
+ * 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 <linux/of_platform.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/arch.h>
+#include <mach/map.h>
+
+#include <plat/cpu.h>
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+
+/*
+ * The following lookup table is used to override device names when devices
+ * are registered from device tree. This is temporarily added to enable
+ * device tree support addition for the Exynos4 architecture.
+ *
+ * For drivers that require platform data to be provided from the machine
+ * file, a platform data pointer can also be supplied along with the
+ * devices names. Usually, the platform data elements that cannot be parsed
+ * from the device tree by the drivers (example: function pointers) are
+ * supplied. But it should be noted that this is a temporary mechanism and
+ * at some point, the drivers should be capable of parsing all the platform
+ * data from the device tree.
+ */
+static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
+ OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART0,
+ "exynos4210-uart.0", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART1,
+ "exynos4210-uart.1", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART2,
+ "exynos4210-uart.2", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART3,
+ "exynos4210-uart.3", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(0),
+ "exynos4-sdhci.0", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(1),
+ "exynos4-sdhci.1", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(2),
+ "exynos4-sdhci.2", NULL),
+ OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(3),
+ "exynos4-sdhci.3", NULL),
+ OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
+ "s3c2440-i2c.0", NULL),
+ OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
+ OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
+ {},
+};
+
+static void __init exynos4210_dt_map_io(void)
+{
+ s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+ s3c24xx_init_clocks(24000000);
+}
+
+static void __init exynos4210_dt_machine_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ exynos4210_auxdata_lookup, NULL);
+}
+
+static char const *exynos4210_dt_compat[] __initdata = {
+ "samsung,exynos4210",
+ NULL
+};
+
+DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
+ /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
+ .init_irq = exynos4_init_irq,
+ .map_io = exynos4210_dt_map_io,
+ .init_machine = exynos4210_dt_machine_init,
+ .timer = &exynos4_timer,
+ .dt_compat = exynos4210_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index a20ae1ad406..71b95587779 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -164,22 +164,6 @@ static struct map_desc bast_iodesc[] __initdata = {
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-static struct s3c24xx_uart_clksrc bast_serial_clocks[] = {
- [0] = {
- .name = "uclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "pclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- }
-};
-
-
static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -187,8 +171,6 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = bast_serial_clocks,
- .clocks_size = ARRAY_SIZE(bast_serial_clocks),
},
[1] = {
.hwport = 1,
@@ -196,8 +178,6 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = bast_serial_clocks,
- .clocks_size = ARRAY_SIZE(bast_serial_clocks),
},
/* port 2 is not actually used */
[2] = {
@@ -206,8 +186,6 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = bast_serial_clocks,
- .clocks_size = ARRAY_SIZE(bast_serial_clocks),
}
};
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index df47e8e9006..0f0a9a1795e 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -109,23 +109,6 @@ static struct map_desc vr1000_iodesc[] __initdata = {
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-/* uart clock source(s) */
-
-static struct s3c24xx_uart_clksrc vr1000_serial_clocks[] = {
- [0] = {
- .name = "uclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "pclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0.
- }
-};
-
static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -133,8 +116,6 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = vr1000_serial_clocks,
- .clocks_size = ARRAY_SIZE(vr1000_serial_clocks),
},
[1] = {
.hwport = 1,
@@ -142,8 +123,6 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = vr1000_serial_clocks,
- .clocks_size = ARRAY_SIZE(vr1000_serial_clocks),
},
/* port 2 is not actually used */
[2] = {
@@ -152,9 +131,6 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = vr1000_serial_clocks,
- .clocks_size = ARRAY_SIZE(vr1000_serial_clocks),
-
}
};
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 3d7ebc557a7..af74927bca1 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -123,12 +123,18 @@ static struct clk s3c2410_armclk = {
.id = -1,
};
+static struct clk_lookup s3c2410_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p),
+ CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
+};
+
void __init s3c2410_init_clocks(int xtal)
{
s3c24xx_register_baseclocks(xtal);
s3c2410_setup_clocks();
s3c2410_baseclk_add();
s3c24xx_register_clock(&s3c2410_armclk);
+ clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup));
}
struct sysdev_class s3c2410_sysclass = {
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
index 140711db6c8..cd50291931f 100644
--- a/arch/arm/mach-s3c2412/clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -659,6 +659,12 @@ static struct clk *clks[] __initdata = {
&clk_armclk,
};
+static struct clk_lookup s3c2412_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_usysclk),
+};
+
int __init s3c2412_baseclk_add(void)
{
unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
@@ -751,6 +757,7 @@ int __init s3c2412_baseclk_add(void)
s3c2412_clkcon_enable(clkp, 0);
}
+ clkdev_add_table(s3c2412_clk_lookup, ARRAY_SIZE(s3c2412_clk_lookup));
s3c_pwmclk_init();
return 0;
}
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
index f9e6bdaf41d..c9879af42b0 100644
--- a/arch/arm/mach-s3c2440/clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -34,6 +34,7 @@
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/serial_core.h>
#include <mach/hardware.h>
#include <linux/atomic.h>
@@ -43,6 +44,7 @@
#include <plat/clock.h>
#include <plat/cpu.h>
+#include <plat/regs-serial.h>
/* S3C2440 extended clock support */
@@ -108,6 +110,46 @@ static struct clk s3c2440_clk_ac97 = {
.ctrlbit = S3C2440_CLKCON_CAMERA,
};
+static unsigned long s3c2440_fclk_n_getrate(struct clk *clk)
+{
+ unsigned long ucon0, ucon1, ucon2, divisor;
+
+ /* the fun of calculating the uart divisors on the s3c2440 */
+ ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
+ ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
+ ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
+
+ ucon0 &= S3C2440_UCON0_DIVMASK;
+ ucon1 &= S3C2440_UCON1_DIVMASK;
+ ucon2 &= S3C2440_UCON2_DIVMASK;
+
+ if (ucon0 != 0)
+ divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6;
+ else if (ucon1 != 0)
+ divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21;
+ else if (ucon2 != 0)
+ divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36;
+ else
+ /* manual calims 44, seems to be 9 */
+ divisor = 9;
+
+ return clk_get_rate(clk->parent) / divisor;
+}
+
+static struct clk s3c2440_clk_fclk_n = {
+ .name = "fclk_n",
+ .parent = &clk_f,
+ .ops = &(struct clk_ops) {
+ .get_rate = s3c2440_fclk_n_getrate,
+ },
+};
+
+static struct clk_lookup s3c2440_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
+};
+
static int s3c2440_clk_add(struct sys_device *sysdev)
{
struct clk *clock_upll;
@@ -126,10 +168,12 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
s3c2440_clk_cam.parent = clock_h;
s3c2440_clk_ac97.parent = clock_p;
s3c2440_clk_cam_upll.parent = clock_upll;
+ s3c24xx_register_clock(&s3c2440_clk_fclk_n);
s3c24xx_register_clock(&s3c2440_clk_ac97);
s3c24xx_register_clock(&s3c2440_clk_cam);
s3c24xx_register_clock(&s3c2440_clk_cam_upll);
+ clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup));
clk_disable(&s3c2440_clk_ac97);
clk_disable(&s3c2440_clk_cam);
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index 74f92fc3fd0..d8f36c0a16a 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -96,22 +96,6 @@ static struct map_desc anubis_iodesc[] __initdata = {
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = {
- [0] = {
- .name = "uclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "pclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- }
-};
-
-
static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -119,8 +103,7 @@ static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = anubis_serial_clocks,
- .clocks_size = ARRAY_SIZE(anubis_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
},
[1] = {
.hwport = 2,
@@ -128,8 +111,7 @@ static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = anubis_serial_clocks,
- .clocks_size = ARRAY_SIZE(anubis_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
},
};
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c
index 38887ee0c78..aa86ca8fa1e 100644
--- a/arch/arm/mach-s3c2440/mach-at2440evb.c
+++ b/arch/arm/mach-s3c2440/mach-at2440evb.c
@@ -57,22 +57,6 @@ static struct map_desc at2440evb_iodesc[] __initdata = {
#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE)
#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
-static struct s3c24xx_uart_clksrc at2440evb_serial_clocks[] = {
- [0] = {
- .name = "uclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "pclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- }
-};
-
-
static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -80,8 +64,7 @@ static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = at2440evb_serial_clocks,
- .clocks_size = ARRAY_SIZE(at2440evb_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
},
[1] = {
.hwport = 1,
@@ -89,8 +72,7 @@ static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = at2440evb_serial_clocks,
- .clocks_size = ARRAY_SIZE(at2440evb_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
},
};
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index dc142ebf8cb..d7e47b2b6ec 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -100,21 +100,6 @@ static struct map_desc osiris_iodesc[] __initdata = {
#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
-static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = {
- [0] = {
- .name = "uclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "pclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- }
-};
-
static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -122,8 +107,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = osiris_serial_clocks,
- .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
},
[1] = {
.hwport = 1,
@@ -131,8 +115,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = osiris_serial_clocks,
- .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
},
[2] = {
.hwport = 2,
@@ -140,8 +123,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
.ucon = UCON,
.ulcon = ULCON,
.ufcon = UFCON,
- .clocks = osiris_serial_clocks,
- .clocks_size = ARRAY_SIZE(osiris_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2,
}
};
diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c
index 0d3453bf567..4267cd56bfe 100644
--- a/arch/arm/mach-s3c2440/mach-rx1950.c
+++ b/arch/arm/mach-s3c2440/mach-rx1950.c
@@ -68,15 +68,6 @@
static struct map_desc rx1950_iodesc[] __initdata = {
};
-static struct s3c24xx_uart_clksrc rx1950_serial_clocks[] = {
- [0] = {
- .name = "fclk",
- .divisor = 0x0a,
- .min_baud = 0,
- .max_baud = 0,
- },
-};
-
static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
@@ -84,8 +75,7 @@ static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
- .clocks = rx1950_serial_clocks,
- .clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL3,
},
[1] = {
.hwport = 1,
@@ -93,8 +83,7 @@ static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
- .clocks = rx1950_serial_clocks,
- .clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL3,
},
/* IR port */
[2] = {
@@ -103,8 +92,7 @@ static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
.ucon = 0x3c5,
.ulcon = 0x43,
.ufcon = 0xf1,
- .clocks = rx1950_serial_clocks,
- .clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL3,
},
};
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index e19499c2f90..3d5e2e67971 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -67,16 +67,6 @@ static struct map_desc rx3715_iodesc[] __initdata = {
},
};
-
-static struct s3c24xx_uart_clksrc rx3715_serial_clocks[] = {
- [0] = {
- .name = "fclk",
- .divisor = 0,
- .min_baud = 0,
- .max_baud = 0,
- }
-};
-
static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
[0] = {
.hwport = 0,
@@ -84,8 +74,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x51,
- .clocks = rx3715_serial_clocks,
- .clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL3,
},
[1] = {
.hwport = 1,
@@ -93,8 +82,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
.ucon = 0x3c5,
.ulcon = 0x03,
.ufcon = 0x00,
- .clocks = rx3715_serial_clocks,
- .clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL3,
},
/* IR port */
[2] = {
@@ -103,8 +91,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
.ucon = 0x3c5,
.ulcon = 0x43,
.ufcon = 0x51,
- .clocks = rx3715_serial_clocks,
- .clocks_size = ARRAY_SIZE(rx3715_serial_clocks),
+ .clk_sel = S3C2410_UCON_CLKSEL3,
}
};
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 39c238d7a3d..2addd988141 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -617,16 +617,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_uhost,
}, {
.clk = {
- .name = "uclk1",
- .ctrlbit = S3C_CLKCON_SCLK_UART,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 },
- .sources = &clkset_uart,
- }, {
-/* Where does UCLK0 come from? */
- .clk = {
.name = "spi-bus",
.devname = "s3c64xx-spi.0",
.ctrlbit = S3C_CLKCON_SCLK_SPI0,
@@ -695,6 +685,18 @@ static struct clksrc_clk clksrcs[] = {
},
};
+/* Where does UCLK0 come from? */
+static struct clksrc_clk clk_sclk_uclk = {
+ .clk = {
+ .name = "uclk1",
+ .ctrlbit = S3C_CLKCON_SCLK_UART,
+ .enable = s3c64xx_sclk_ctrl,
+ },
+ .reg_src = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1 },
+ .reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 },
+ .sources = &clkset_uart,
+};
+
/* Clock initialisation code */
static struct clksrc_clk *init_parents[] = {
@@ -703,6 +705,15 @@ static struct clksrc_clk *init_parents[] = {
&clk_mout_mpll,
};
+static struct clksrc_clk *clksrc_cdev[] = {
+ &clk_sclk_uclk,
+};
+
+static struct clk_lookup s3c64xx_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
+};
+
#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
void __init_or_cpufreq s3c6400_setup_clocks(void)
@@ -811,6 +822,8 @@ static struct clk *clks[] __initdata = {
void __init s3c64xx_register_clocks(unsigned long xtal,
unsigned armclk_divlimit)
{
+ unsigned int cnt;
+
armclk_mask = armclk_divlimit;
s3c24xx_register_baseclocks(xtal);
@@ -823,5 +836,9 @@ void __init s3c64xx_register_clocks(unsigned long xtal,
s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+ for (cnt = 0; cnt < ARRAY_SIZE(clksrc_cdev); cnt++)
+ s3c_register_clksrc(clksrc_cdev[cnt], 1);
+ clkdev_add_table(s3c64xx_clk_lookup, ARRAY_SIZE(s3c64xx_clk_lookup));
+
s3c_pwmclk_init();
}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index c54c65d511f..bfb1917ad0d 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -421,15 +421,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
}, {
.clk = {
- .name = "uclk1",
- .ctrlbit = (1 << 5),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
- }, {
- .clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 20),
@@ -487,6 +478,17 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk clk_sclk_uclk = {
+ .clk = {
+ .name = "uclk1",
+ .ctrlbit = (1 << 5),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+};
+
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -505,6 +507,15 @@ static struct clk dummy_apb_pclk = {
.id = -1,
};
+static struct clksrc_clk *clksrc_cdev[] = {
+ &clk_sclk_uclk,
+};
+
+static struct clk_lookup s5p6440_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
+};
+
void __init_or_cpufreq s5p6440_setup_clocks(void)
{
struct clk *xtal_clk;
@@ -583,9 +594,12 @@ void __init s5p6440_register_clocks(void)
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ clkdev_add_table(s5p6440_clk_lookup, ARRAY_SIZE(s5p6440_clk_lookup));
s3c24xx_register_clock(&dummy_apb_pclk);
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index 2d04abfba12..d132638c7b2 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -443,15 +443,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 },
}, {
.clk = {
- .name = "uclk1",
- .ctrlbit = (1 << 5),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
- }, {
- .clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 20),
@@ -536,6 +527,26 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk clk_sclk_uclk = {
+ .clk = {
+ .name = "uclk1",
+ .ctrlbit = (1 << 5),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 13, .size = 1 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &clk_sclk_uclk,
+};
+
+static struct clk_lookup s5p6450_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
+};
+
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -634,9 +645,12 @@ void __init s5p6450_register_clocks(void)
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ clkdev_add_table(s5p6450_clk_lookup, ARRAY_SIZE(s5p6450_clk_lookup));
s3c24xx_register_clock(&dummy_apb_pclk);
diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c
index 442dd4ad12d..f820c074440 100644
--- a/arch/arm/mach-s5p64x0/dma.c
+++ b/arch/arm/mach-s5p64x0/dma.c
@@ -38,176 +38,74 @@
static u64 dma_dmamask = DMA_BIT_MASK(32);
-struct dma_pl330_peri s5p6440_pdma_peri[22] = {
- {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = DMACH_MAX,
- }, {
- .peri_id = DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_PCM0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- },
+u8 s5p6440_pdma_peri[] = {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_PCM0_TX,
+ DMACH_PCM0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI0_RX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_SPI1_TX,
+ DMACH_SPI1_RX,
};
struct dma_pl330_platdata s5p6440_pdma_pdata = {
.nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
- .peri = s5p6440_pdma_peri,
+ .peri_id = s5p6440_pdma_peri,
};
-struct dma_pl330_peri s5p6450_pdma_peri[32] = {
- {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART4_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART4_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_USI_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_USI_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_I2S1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PWM,
- }, {
- .peri_id = (u8)DMACH_UART5_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART5_TX,
- .rqtype = MEMTODEV,
- },
+u8 s5p6450_pdma_peri[] = {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_UART4_RX,
+ DMACH_UART4_TX,
+ DMACH_PCM0_TX,
+ DMACH_PCM0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI0_RX,
+ DMACH_PCM1_TX,
+ DMACH_PCM1_RX,
+ DMACH_PCM2_TX,
+ DMACH_PCM2_RX,
+ DMACH_SPI1_TX,
+ DMACH_SPI1_RX,
+ DMACH_USI_TX,
+ DMACH_USI_RX,
+ DMACH_MAX,
+ DMACH_I2S1_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S2_TX,
+ DMACH_I2S2_RX,
+ DMACH_PWM,
+ DMACH_UART5_RX,
+ DMACH_UART5_TX,
};
struct dma_pl330_platdata s5p6450_pdma_pdata = {
.nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
- .peri = s5p6450_pdma_peri,
+ .peri_id = s5p6450_pdma_peri,
};
struct amba_device s5p64x0_device_pdma = {
@@ -227,10 +125,15 @@ struct amba_device s5p64x0_device_pdma = {
static int __init s5p64x0_dma_init(void)
{
- if (soc_is_s5p6450())
+ if (soc_is_s5p6450()) {
+ dma_cap_set(DMA_SLAVE, s5p6450_pdma_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, s5p6450_pdma_pdata.cap_mask);
s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
- else
+ } else {
+ dma_cap_set(DMA_SLAVE, s5p6440_pdma_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, s5p6440_pdma_pdata.cap_mask);
s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
+ }
amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 53982db9d25..5b845e849b3 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -141,6 +141,8 @@
#define IRQ_EINT_GROUP(grp, x) (IRQ_EINT_GROUP##grp##_BASE + (x))
+#define IRQ_TIMER_BASE (11)
+
/* Set the default NR_IRQS */
#define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c
index 79833caf816..659a66c131a 100644
--- a/arch/arm/mach-s5p64x0/init.c
+++ b/arch/arm/mach-s5p64x0/init.c
@@ -23,36 +23,7 @@
#include <plat/s5p6450.h>
#include <plat/regs-serial.h>
-static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = {
- [0] = {
- .name = "pclk_low",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
- [1] = {
- .name = "uclk1",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
-};
-
/* uart registration process */
-
-void __init s5p64x0_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
- struct s3c2410_uartcfg *tcfg = cfg;
- u32 ucnt;
-
- for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
- if (!tcfg->clocks) {
- tcfg->clocks = s5p64x0_serial_clocks;
- tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks);
- }
- }
-}
-
void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
int uart;
@@ -62,12 +33,10 @@ void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART;
}
- s5p64x0_common_init_uarts(cfg, no);
s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
}
void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
- s5p64x0_common_init_uarts(cfg, no);
s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no);
}
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 8d47709da71..9d644ece260 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -962,16 +962,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
}, {
.clk = {
- .name = "uclk1",
- .ctrlbit = (1 << 3),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_group2,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
- }, {
- .clk = {
.name = "sclk_mixer",
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
@@ -1098,6 +1088,17 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk clk_sclk_uart = {
+ .clk = {
+ .name = "uclk1",
+ .ctrlbit = (1 << 3),
+ .enable = s5pc100_sclk0_ctrl,
+ },
+ .sources = &clk_src_group2,
+ .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
+ .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
+};
+
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -1127,6 +1128,10 @@ static struct clksrc_clk *sysclks[] = {
&clk_sclk_spdif,
};
+static struct clksrc_clk *clksrc_cdev[] = {
+ &clk_sclk_uart,
+};
+
void __init_or_cpufreq s5pc100_setup_clocks(void)
{
unsigned long xtal;
@@ -1266,6 +1271,11 @@ static struct clk *clks[] __initdata = {
&clk_pcmcdclk1,
};
+static struct clk_lookup s5pc100_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uart.clk),
+};
+
void __init s5pc100_register_clocks(void)
{
int ptr;
@@ -1277,9 +1287,12 @@ void __init s5pc100_register_clocks(void)
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ clkdev_add_table(s5pc100_clk_lookup, ARRAY_SIZE(s5pc100_clk_lookup));
s3c24xx_register_clock(&dummy_apb_pclk);
diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c
index 065a087f5a8..c841f4d313f 100644
--- a/arch/arm/mach-s5pc100/dma.c
+++ b/arch/arm/mach-s5pc100/dma.c
@@ -35,100 +35,42 @@
static u64 dma_dmamask = DMA_BIT_MASK(32);
-struct dma_pl330_peri pdma0_peri[30] = {
- {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = DMACH_IRDA,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0S_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_AC97_MICIN,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_AC97_PCMIN,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_AC97_PCMOUT,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_EXTERNAL,
- }, {
- .peri_id = (u8)DMACH_PWM,
- }, {
- .peri_id = (u8)DMACH_SPDIF,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_HSI_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_HSI_TX,
- .rqtype = MEMTODEV,
- },
+u8 pdma0_peri[] = {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_IRDA,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_I2S2_RX,
+ DMACH_I2S2_TX,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_SPI2_RX,
+ DMACH_SPI2_TX,
+ DMACH_AC97_MICIN,
+ DMACH_AC97_PCMIN,
+ DMACH_AC97_PCMOUT,
+ DMACH_EXTERNAL,
+ DMACH_PWM,
+ DMACH_SPDIF,
+ DMACH_HSI_RX,
+ DMACH_HSI_TX,
};
struct dma_pl330_platdata s5pc100_pdma0_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
- .peri = pdma0_peri,
+ .peri_id = pdma0_peri,
};
struct amba_device s5pc100_device_pdma0 = {
@@ -147,98 +89,42 @@ struct amba_device s5pc100_device_pdma0 = {
.periphid = 0x00041330,
};
-struct dma_pl330_peri pdma1_peri[30] = {
- {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = DMACH_IRDA,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0S_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ0,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ1,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ2,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ3,
- },
+u8 pdma1_peri[] = {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_IRDA,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_I2S2_RX,
+ DMACH_I2S2_TX,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_SPI2_RX,
+ DMACH_SPI2_TX,
+ DMACH_PCM0_RX,
+ DMACH_PCM0_TX,
+ DMACH_PCM1_RX,
+ DMACH_PCM1_TX,
+ DMACH_MSM_REQ0,
+ DMACH_MSM_REQ1,
+ DMACH_MSM_REQ2,
+ DMACH_MSM_REQ3,
};
struct dma_pl330_platdata s5pc100_pdma1_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
- .peri = pdma1_peri,
+ .peri_id = pdma1_peri,
};
struct amba_device s5pc100_device_pdma1 = {
@@ -259,7 +145,12 @@ struct amba_device s5pc100_device_pdma1 = {
static int __init s5pc100_dma_init(void)
{
+ dma_cap_set(DMA_SLAVE, s5pc100_pdma0_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, s5pc100_pdma0_pdata.cap_mask);
amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
+
+ dma_cap_set(DMA_SLAVE, s5pc100_pdma1_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, s5pc100_pdma1_pdata.cap_mask);
amba_device_register(&s5pc100_device_pdma1, &iomem_resource);
return 0;
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index d2eb4757381..2870f12c792 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -97,6 +97,8 @@
#define IRQ_SDMFIQ S5P_IRQ_VIC2(31)
#define IRQ_VIC_END S5P_IRQ_VIC2(31)
+#define IRQ_TIMER_BASE (11)
+
#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 4c5ac7a69e9..43a045d354e 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -809,46 +809,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
}, {
.clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 12),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 13),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.2",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 14),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
- }, {
- .clk = {
- .name = "uclk1",
- .devname = "s5pv210-uart.3",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 15),
- },
- .sources = &clkset_uart,
- .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
- }, {
- .clk = {
.name = "sclk_fimc",
.devname = "s5pv210-fimc.0",
.enable = s5pv210_clk_mask1_ctrl,
@@ -1022,6 +982,61 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk clk_sclk_uart0 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.0",
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 12),
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_sclk_uart1 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.1",
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 13),
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
+};
+
+static struct clksrc_clk clk_sclk_uart2 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.2",
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 14),
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
+};
+
+static struct clksrc_clk clk_sclk_uart3 = {
+ .clk = {
+ .name = "uclk1",
+ .devname = "s5pv210-uart.3",
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 15),
+ },
+ .sources = &clkset_uart,
+ .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &clk_sclk_uart0,
+ &clk_sclk_uart1,
+ &clk_sclk_uart2,
+ &clk_sclk_uart3,
+};
+
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -1261,6 +1276,14 @@ static struct clk *clks[] __initdata = {
&clk_pcmcdclk2,
};
+static struct clk_lookup s5pv210_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p),
+ CLKDEV_INIT("s5pv210-uart.0", "clk_uart_baud1", &clk_sclk_uart0.clk),
+ CLKDEV_INIT("s5pv210-uart.1", "clk_uart_baud1", &clk_sclk_uart1.clk),
+ CLKDEV_INIT("s5pv210-uart.2", "clk_uart_baud1", &clk_sclk_uart2.clk),
+ CLKDEV_INIT("s5pv210-uart.3", "clk_uart_baud1", &clk_sclk_uart3.clk),
+};
+
void __init s5pv210_register_clocks(void)
{
int ptr;
@@ -1273,11 +1296,15 @@ void __init s5pv210_register_clocks(void)
for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
s3c_register_clksrc(sclk_tv[ptr], 1);
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ clkdev_add_table(s5pv210_clk_lookup, ARRAY_SIZE(s5pv210_clk_lookup));
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 86b749c18b7..a6113e0267f 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -35,90 +35,40 @@
static u64 dma_dmamask = DMA_BIT_MASK(32);
-struct dma_pl330_peri pdma0_peri[28] = {
- {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0S_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_AC97_MICIN,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_AC97_PCMIN,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_AC97_PCMOUT,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_PWM,
- }, {
- .peri_id = (u8)DMACH_SPDIF,
- .rqtype = MEMTODEV,
- },
+u8 pdma0_peri[] = {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_MAX,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_AC97_MICIN,
+ DMACH_AC97_PCMIN,
+ DMACH_AC97_PCMOUT,
+ DMACH_MAX,
+ DMACH_PWM,
+ DMACH_SPDIF,
};
struct dma_pl330_platdata s5pv210_pdma0_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
- .peri = pdma0_peri,
+ .peri_id = pdma0_peri,
};
struct amba_device s5pv210_device_pdma0 = {
@@ -137,102 +87,44 @@ struct amba_device s5pv210_device_pdma0 = {
.periphid = 0x00041330,
};
-struct dma_pl330_peri pdma1_peri[32] = {
- {
- .peri_id = (u8)DMACH_UART0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_UART3_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_UART3_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_I2S0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S0S_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_I2S2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_I2S2_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_SPI1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_SPI1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_MAX,
- }, {
- .peri_id = (u8)DMACH_PCM0_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM0_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_PCM1_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM1_TX,
- .rqtype = MEMTODEV,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ0,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ1,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ2,
- }, {
- .peri_id = (u8)DMACH_MSM_REQ3,
- }, {
- .peri_id = (u8)DMACH_PCM2_RX,
- .rqtype = DEVTOMEM,
- }, {
- .peri_id = (u8)DMACH_PCM2_TX,
- .rqtype = MEMTODEV,
- },
+u8 pdma1_peri[] = {
+ DMACH_UART0_RX,
+ DMACH_UART0_TX,
+ DMACH_UART1_RX,
+ DMACH_UART1_TX,
+ DMACH_UART2_RX,
+ DMACH_UART2_TX,
+ DMACH_UART3_RX,
+ DMACH_UART3_TX,
+ DMACH_MAX,
+ DMACH_I2S0_RX,
+ DMACH_I2S0_TX,
+ DMACH_I2S0S_TX,
+ DMACH_I2S1_RX,
+ DMACH_I2S1_TX,
+ DMACH_I2S2_RX,
+ DMACH_I2S2_TX,
+ DMACH_SPI0_RX,
+ DMACH_SPI0_TX,
+ DMACH_SPI1_RX,
+ DMACH_SPI1_TX,
+ DMACH_MAX,
+ DMACH_MAX,
+ DMACH_PCM0_RX,
+ DMACH_PCM0_TX,
+ DMACH_PCM1_RX,
+ DMACH_PCM1_TX,
+ DMACH_MSM_REQ0,
+ DMACH_MSM_REQ1,
+ DMACH_MSM_REQ2,
+ DMACH_MSM_REQ3,
+ DMACH_PCM2_RX,
+ DMACH_PCM2_TX,
};
struct dma_pl330_platdata s5pv210_pdma1_pdata = {
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
- .peri = pdma1_peri,
+ .peri_id = pdma1_peri,
};
struct amba_device s5pv210_device_pdma1 = {
@@ -253,7 +145,12 @@ struct amba_device s5pv210_device_pdma1 = {
static int __init s5pv210_dma_init(void)
{
+ dma_cap_set(DMA_SLAVE, s5pv210_pdma0_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, s5pv210_pdma0_pdata.cap_mask);
amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
+
+ dma_cap_set(DMA_SLAVE, s5pv210_pdma1_pdata.cap_mask);
+ dma_cap_set(DMA_CYCLIC, s5pv210_pdma1_pdata.cap_mask);
amba_device_register(&s5pv210_device_pdma1, &iomem_resource);
return 0;
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index 5e0de3a31f3..e777e010ed2 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -118,6 +118,8 @@
#define IRQ_MDNIE3 S5P_IRQ_VIC3(8)
#define IRQ_VIC_END S5P_IRQ_VIC3(31)
+#define IRQ_TIMER_BASE (11)
+
#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
diff --git a/arch/arm/mach-s5pv210/init.c b/arch/arm/mach-s5pv210/init.c
index 4865ae2c475..468a5f88619 100644
--- a/arch/arm/mach-s5pv210/init.c
+++ b/arch/arm/mach-s5pv210/init.c
@@ -18,27 +18,8 @@
#include <plat/s5pv210.h>
#include <plat/regs-serial.h>
-static struct s3c24xx_uart_clksrc s5pv210_serial_clocks[] = {
- [0] = {
- .name = "pclk",
- .divisor = 1,
- .min_baud = 0,
- .max_baud = 0,
- },
-};
-
/* uart registration process */
void __init s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
{
- struct s3c2410_uartcfg *tcfg = cfg;
- u32 ucnt;
-
- for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
- if (!tcfg->clocks) {
- tcfg->clocks = s5pv210_serial_clocks;
- tcfg->clocks_size = ARRAY_SIZE(s5pv210_serial_clocks);
- }
- }
-
s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
}
diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c
index 5a21b15b2a9..4eab2cca2d9 100644
--- a/arch/arm/plat-s3c24xx/s3c2443-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c
@@ -297,13 +297,6 @@ static struct clksrc_clk clk_usb_bus_host = {
static struct clksrc_clk clksrc_clks[] = {
{
- /* ART baud-rate clock sourced from esysclk via a divisor */
- .clk = {
- .name = "uartclk",
- .parent = &clk_esysclk.clk,
- },
- .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
- }, {
/* camera interface bus-clock, divided down from esysclk */
.clk = {
.name = "camif-upll", /* same as 2440 name */
@@ -323,6 +316,15 @@ static struct clksrc_clk clksrc_clks[] = {
},
};
+static struct clksrc_clk clk_esys_uart = {
+ /* ART baud-rate clock sourced from esysclk via a divisor */
+ .clk = {
+ .name = "uartclk",
+ .parent = &clk_esysclk.clk,
+ },
+ .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 },
+};
+
static struct clk clk_i2s_ext = {
.name = "i2s-ext",
};
@@ -589,6 +591,12 @@ static struct clksrc_clk *clksrcs[] __initdata = {
&clk_arm,
};
+static struct clk_lookup s3c2443_clk_lookup[] = {
+ CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
+ CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
+ CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk),
+};
+
void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
unsigned int *divs, int nr_divs,
int divmask)
@@ -618,6 +626,7 @@ void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
/* See s3c2443/etc notes on disabling clocks at init time */
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ clkdev_add_table(s3c2443_clk_lookup, ARRAY_SIZE(s3c2443_clk_lookup));
s3c2443_common_setup_clocks(get_mpll);
}
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index 93a994a5dd8..2cded872f22 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -18,23 +18,24 @@
#include <mach/dma.h>
-static inline bool pl330_filter(struct dma_chan *chan, void *param)
-{
- struct dma_pl330_peri *peri = chan->private;
- return peri->peri_id == (unsigned)param;
-}
-
static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
struct samsung_dma_info *info)
{
struct dma_chan *chan;
dma_cap_mask_t mask;
struct dma_slave_config slave_config;
+ void *filter_param;
dma_cap_zero(mask);
dma_cap_set(info->cap, mask);
- chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
+ /*
+ * If a dma channel property of a device node from device tree is
+ * specified, use that as the fliter parameter.
+ */
+ filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop :
+ (void *)dma_ch;
+ chan = dma_request_channel(mask, pl330_filter, filter_param);
if (info->direction == DMA_FROM_DEVICE) {
memset(&slave_config, 0, sizeof(struct dma_slave_config));
diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h
index 4c1a363526c..22eafc310bd 100644
--- a/arch/arm/plat-samsung/include/plat/dma-ops.h
+++ b/arch/arm/plat-samsung/include/plat/dma-ops.h
@@ -31,6 +31,7 @@ struct samsung_dma_info {
enum dma_slave_buswidth width;
dma_addr_t fifo;
struct s3c2410_dma_client *client;
+ struct property *dt_dmach_prop;
};
struct samsung_dma_ops {
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index 2e55e595867..c5eaad529de 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -21,7 +21,8 @@
* use these just as IDs.
*/
enum dma_ch {
- DMACH_UART0_RX,
+ DMACH_DT_PROP = -1,
+ DMACH_UART0_RX = 0,
DMACH_UART0_TX,
DMACH_UART1_RX,
DMACH_UART1_TX,
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
index 08d1a7ef97b..df46b776976 100644
--- a/arch/arm/plat-samsung/include/plat/irqs.h
+++ b/arch/arm/plat-samsung/include/plat/irqs.h
@@ -44,13 +44,14 @@
#define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x))
#define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x))
-#define S5P_TIMER_IRQ(x) (11 + (x))
+#define S5P_TIMER_IRQ(x) (IRQ_TIMER_BASE + (x))
#define IRQ_TIMER0 S5P_TIMER_IRQ(0)
#define IRQ_TIMER1 S5P_TIMER_IRQ(1)
#define IRQ_TIMER2 S5P_TIMER_IRQ(2)
#define IRQ_TIMER3 S5P_TIMER_IRQ(3)
#define IRQ_TIMER4 S5P_TIMER_IRQ(4)
+#define IRQ_TIMER_COUNT (5)
#define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \
: ((x) - 16 + S5P_EINT_BASE2))
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
index 72073484702..29c26a81884 100644
--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
+++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
@@ -71,6 +71,7 @@
#define S3C2410_LCON_IRM (1<<6)
#define S3C2440_UCON_CLKMASK (3<<10)
+#define S3C2440_UCON_CLKSHIFT (10)
#define S3C2440_UCON_PCLK (0<<10)
#define S3C2440_UCON_UCLK (1<<10)
#define S3C2440_UCON_PCLK2 (2<<10)
@@ -78,6 +79,7 @@
#define S3C2443_UCON_EPLL (3<<10)
#define S3C6400_UCON_CLKMASK (3<<10)
+#define S3C6400_UCON_CLKSHIFT (10)
#define S3C6400_UCON_PCLK (0<<10)
#define S3C6400_UCON_PCLK2 (2<<10)
#define S3C6400_UCON_UCLK0 (1<<10)
@@ -90,11 +92,14 @@
#define S3C2440_UCON_DIVSHIFT (12)
#define S3C2412_UCON_CLKMASK (3<<10)
+#define S3C2412_UCON_CLKSHIFT (10)
#define S3C2412_UCON_UCLK (1<<10)
#define S3C2412_UCON_USYSCLK (3<<10)
#define S3C2412_UCON_PCLK (0<<10)
#define S3C2412_UCON_PCLK2 (2<<10)
+#define S3C2410_UCON_CLKMASK (1 << 10)
+#define S3C2410_UCON_CLKSHIFT (10)
#define S3C2410_UCON_UCLK (1<<10)
#define S3C2410_UCON_SBREAK (1<<4)
@@ -193,6 +198,7 @@
/* Following are specific to S5PV210 */
#define S5PV210_UCON_CLKMASK (1<<10)
+#define S5PV210_UCON_CLKSHIFT (10)
#define S5PV210_UCON_PCLK (0<<10)
#define S5PV210_UCON_UCLK (1<<10)
@@ -221,29 +227,24 @@
#define S5PV210_UFSTAT_RXMASK (255<<0)
#define S5PV210_UFSTAT_RXSHIFT (0)
-#define NO_NEED_CHECK_CLKSRC 1
+#define S3C2410_UCON_CLKSEL0 (1 << 0)
+#define S3C2410_UCON_CLKSEL1 (1 << 1)
+#define S3C2410_UCON_CLKSEL2 (1 << 2)
+#define S3C2410_UCON_CLKSEL3 (1 << 3)
-#ifndef __ASSEMBLY__
+/* Default values for s5pv210 UCON and UFCON uart registers */
+#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
+ S3C2410_UCON_RXILEVEL | \
+ S3C2410_UCON_TXIRQMODE | \
+ S3C2410_UCON_RXIRQMODE | \
+ S3C2410_UCON_RXFIFO_TOI | \
+ S3C2443_UCON_RXERR_IRQEN)
-/* struct s3c24xx_uart_clksrc
- *
- * this structure defines a named clock source that can be used for the
- * uart, so that the best clock can be selected for the requested baud
- * rate.
- *
- * min_baud and max_baud define the range of baud-rates this clock is
- * acceptable for, if they are both zero, it is assumed any baud rate that
- * can be generated from this clock will be used.
- *
- * divisor gives the divisor from the clock to the one seen by the uart
-*/
+#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \
+ S5PV210_UFCON_TXTRIG4 | \
+ S5PV210_UFCON_RXTRIG4)
-struct s3c24xx_uart_clksrc {
- const char *name;
- unsigned int divisor;
- unsigned int min_baud;
- unsigned int max_baud;
-};
+#ifndef __ASSEMBLY__
/* configuration structure for per-machine configurations for the
* serial port
@@ -257,15 +258,13 @@ struct s3c2410_uartcfg {
unsigned char unused;
unsigned short flags;
upf_t uart_flags; /* default uart flags */
+ unsigned int clk_sel;
unsigned int has_fracval;
unsigned long ucon; /* value of ucon for port */
unsigned long ulcon; /* value of ulcon for port */
unsigned long ufcon; /* value of ufcon for port */
-
- struct s3c24xx_uart_clksrc *clocks;
- unsigned int clocks_size;
};
/* s3c24xx_uart_devs
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 571041477ab..a626e15799a 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -19,6 +19,7 @@
#include <linux/amba/pl330.h>
#include <linux/pm_runtime.h>
#include <linux/scatterlist.h>
+#include <linux/of.h>
#define NR_DEFAULT_DESC 16
@@ -116,6 +117,9 @@ struct dma_pl330_desc {
struct dma_pl330_chan *pchan;
};
+/* forward declaration */
+static struct amba_driver pl330_driver;
+
static inline struct dma_pl330_chan *
to_pchan(struct dma_chan *ch)
{
@@ -267,6 +271,32 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
tasklet_schedule(&pch->task);
}
+bool pl330_filter(struct dma_chan *chan, void *param)
+{
+ u8 *peri_id;
+
+ if (chan->device->dev->driver != &pl330_driver.drv)
+ return false;
+
+#ifdef CONFIG_OF
+ if (chan->device->dev->of_node) {
+ const __be32 *prop_value;
+ phandle phandle;
+ struct device_node *node;
+
+ prop_value = ((struct property *)param)->value;
+ phandle = be32_to_cpup(prop_value++);
+ node = of_find_node_by_phandle(phandle);
+ return ((chan->private == node) &&
+ (chan->chan_id == be32_to_cpup(prop_value)));
+ }
+#endif
+
+ peri_id = chan->private;
+ return *peri_id == (unsigned)param;
+}
+EXPORT_SYMBOL(pl330_filter);
+
static int pl330_alloc_chan_resources(struct dma_chan *chan)
{
struct dma_pl330_chan *pch = to_pchan(chan);
@@ -497,7 +527,7 @@ pluck_desc(struct dma_pl330_dmac *pdmac)
static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
{
struct dma_pl330_dmac *pdmac = pch->dmac;
- struct dma_pl330_peri *peri = pch->chan.private;
+ u8 *peri_id = pch->chan.private;
struct dma_pl330_desc *desc;
/* Pluck one desc from the pool of DMAC */
@@ -522,13 +552,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
desc->txd.cookie = 0;
async_tx_ack(&desc->txd);
- if (peri) {
- desc->req.rqtype = peri->rqtype;
- desc->req.peri = pch->chan.chan_id;
- } else {
- desc->req.rqtype = MEMTOMEM;
- desc->req.peri = 0;
- }
+ desc->req.peri = peri_id ? pch->chan.chan_id : 0;
dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
@@ -615,12 +639,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
case DMA_TO_DEVICE:
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
+ desc->req.rqtype = MEMTODEV;
src = dma_addr;
dst = pch->fifo_addr;
break;
case DMA_FROM_DEVICE:
desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1;
+ desc->req.rqtype = DEVTOMEM;
src = pch->fifo_addr;
dst = dma_addr;
break;
@@ -646,16 +672,12 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
{
struct dma_pl330_desc *desc;
struct dma_pl330_chan *pch = to_pchan(chan);
- struct dma_pl330_peri *peri = chan->private;
struct pl330_info *pi;
int burst;
if (unlikely(!pch || !len))
return NULL;
- if (peri && peri->rqtype != MEMTOMEM)
- return NULL;
-
pi = &pch->dmac->pif;
desc = __pl330_prep_dma_memcpy(pch, dst, src, len);
@@ -664,6 +686,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 1;
+ desc->req.rqtype = MEMTOMEM;
/* Select max possible burst size */
burst = pi->pcfg.data_bus_width / 8;
@@ -692,25 +715,14 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
{
struct dma_pl330_desc *first, *desc = NULL;
struct dma_pl330_chan *pch = to_pchan(chan);
- struct dma_pl330_peri *peri = chan->private;
struct scatterlist *sg;
unsigned long flags;
int i;
dma_addr_t addr;
- if (unlikely(!pch || !sgl || !sg_len || !peri))
+ if (unlikely(!pch || !sgl || !sg_len))
return NULL;
- /* Make sure the direction is consistent */
- if ((direction == DMA_TO_DEVICE &&
- peri->rqtype != MEMTODEV) ||
- (direction == DMA_FROM_DEVICE &&
- peri->rqtype != DEVTOMEM)) {
- dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n",
- __func__, __LINE__);
- return NULL;
- }
-
addr = pch->fifo_addr;
first = NULL;
@@ -750,11 +762,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (direction == DMA_TO_DEVICE) {
desc->rqcfg.src_inc = 1;
desc->rqcfg.dst_inc = 0;
+ desc->req.rqtype = MEMTODEV;
fill_px(&desc->px,
addr, sg_dma_address(sg), sg_dma_len(sg));
} else {
desc->rqcfg.src_inc = 0;
desc->rqcfg.dst_inc = 1;
+ desc->req.rqtype = DEVTOMEM;
fill_px(&desc->px,
sg_dma_address(sg), addr, sg_dma_len(sg));
}
@@ -856,32 +870,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
INIT_LIST_HEAD(&pd->channels);
/* Initialize channel parameters */
- num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan);
+ num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri,
+ (u8)pi->pcfg.num_chan);
pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
for (i = 0; i < num_chan; i++) {
pch = &pdmac->peripherals[i];
- if (pdat) {
- struct dma_pl330_peri *peri = &pdat->peri[i];
-
- switch (peri->rqtype) {
- case MEMTOMEM:
- dma_cap_set(DMA_MEMCPY, pd->cap_mask);
- break;
- case MEMTODEV:
- case DEVTOMEM:
- dma_cap_set(DMA_SLAVE, pd->cap_mask);
- dma_cap_set(DMA_CYCLIC, pd->cap_mask);
- break;
- default:
- dev_err(&adev->dev, "DEVTODEV Not Supported\n");
- continue;
- }
- pch->chan.private = peri;
- } else {
- dma_cap_set(DMA_MEMCPY, pd->cap_mask);
- pch->chan.private = NULL;
- }
+ if (!adev->dev.of_node)
+ pch->chan.private = pdat ? &pdat->peri_id[i] : NULL;
+ else
+ pch->chan.private = adev->dev.of_node;
INIT_LIST_HEAD(&pch->work_list);
spin_lock_init(&pch->lock);
@@ -894,6 +892,15 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
}
pd->dev = &adev->dev;
+ if (pdat) {
+ pd->cap_mask = pdat->cap_mask;
+ } else {
+ dma_cap_set(DMA_MEMCPY, pd->cap_mask);
+ if (pi->pcfg.num_peri) {
+ dma_cap_set(DMA_SLAVE, pd->cap_mask);
+ dma_cap_set(DMA_CYCLIC, pd->cap_mask);
+ }
+ }
pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
pd->device_free_chan_resources = pl330_free_chan_resources;
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 86625185271..6b4d23fd158 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -24,6 +24,9 @@
#include <linux/interrupt.h>
#include <linux/sysdev.h>
#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
#include <asm/irq.h>
@@ -2374,6 +2377,63 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {
#endif
};
+#if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF)
+static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np,
+ const void *gpio_spec, u32 *flags)
+{
+ const __be32 *gpio = gpio_spec;
+ const u32 n = be32_to_cpup(gpio);
+ unsigned int pin = gc->base + be32_to_cpu(gpio[0]);
+
+ if (WARN_ON(gc->of_gpio_n_cells < 4))
+ return -EINVAL;
+
+ if (n > gc->ngpio)
+ return -EINVAL;
+
+ if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1]))))
+ pr_warn("gpio_xlate: failed to set pin function\n");
+ if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2])))
+ pr_warn("gpio_xlate: failed to set pin pull up/down\n");
+ if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3])))
+ pr_warn("gpio_xlate: failed to set pin drive strength\n");
+
+ return n;
+}
+
+static const struct of_device_id exynos4_gpio_dt_match[] __initdata = {
+ { .compatible = "samsung,exynos4-gpio", },
+ {}
+};
+
+static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+ u64 base, u64 offset)
+{
+ struct gpio_chip *gc = &chip->chip;
+ u64 address;
+
+ if (!of_have_populated_dt())
+ return;
+
+ address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
+ gc->of_node = of_find_matching_node_by_address(NULL,
+ exynos4_gpio_dt_match, address);
+ if (!gc->of_node) {
+ pr_info("gpio: device tree node not found for gpio controller"
+ " with base address %08llx\n", address);
+ return;
+ }
+ gc->of_gpio_n_cells = 4;
+ gc->of_xlate = exynos4_gpio_xlate;
+}
+#elif defined(CONFIG_ARCH_EXYNOS4)
+static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+ u64 base, u64 offset)
+{
+ return;
+}
+#endif /* defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) */
+
/* TODO: cleanup soc_is_* */
static __init int samsung_gpiolib_init(void)
{
@@ -2455,6 +2515,10 @@ static __init int samsung_gpiolib_init(void)
chip->config = &exynos4_gpio_cfg;
chip->group = group++;
}
+#ifdef CONFIG_CPU_EXYNOS4210
+ exynos4_gpiolib_attach_ofnode(chip,
+ EXYNOS4_PA_GPIO1, i * 0x20);
+#endif
}
samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
@@ -2467,6 +2531,10 @@ static __init int samsung_gpiolib_init(void)
chip->config = &exynos4_gpio_cfg;
chip->group = group++;
}
+#ifdef CONFIG_CPU_EXYNOS4210
+ exynos4_gpiolib_attach_ofnode(chip,
+ EXYNOS4_PA_GPIO2, i * 0x20);
+#endif
}
samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
@@ -2479,6 +2547,10 @@ static __init int samsung_gpiolib_init(void)
chip->config = &exynos4_gpio_cfg;
chip->group = group++;
}
+#ifdef CONFIG_CPU_EXYNOS4210
+ exynos4_gpiolib_attach_ofnode(chip,
+ EXYNOS4_PA_GPIO3, i * 0x20);
+#endif
}
samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index f689f49e310..8a0060cd398 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -21,6 +21,8 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/sched.h>
#include <plat/keypad.h>
@@ -68,31 +70,26 @@ struct samsung_keypad {
wait_queue_head_t wait;
bool stopped;
int irq;
+ enum samsung_keypad_type type;
unsigned int row_shift;
unsigned int rows;
unsigned int cols;
unsigned int row_state[SAMSUNG_MAX_COLS];
+#ifdef CONFIG_OF
+ int row_gpios[SAMSUNG_MAX_ROWS];
+ int col_gpios[SAMSUNG_MAX_COLS];
+#endif
unsigned short keycodes[];
};
-static int samsung_keypad_is_s5pv210(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- enum samsung_keypad_type type =
- platform_get_device_id(pdev)->driver_data;
-
- return type == KEYPAD_TYPE_S5PV210;
-}
-
static void samsung_keypad_scan(struct samsung_keypad *keypad,
unsigned int *row_state)
{
- struct device *dev = keypad->input_dev->dev.parent;
unsigned int col;
unsigned int val;
for (col = 0; col < keypad->cols; col++) {
- if (samsung_keypad_is_s5pv210(dev)) {
+ if (keypad->type == KEYPAD_TYPE_S5PV210) {
val = S5PV210_KEYIFCOLEN_MASK;
val &= ~(1 << col) << 8;
} else {
@@ -235,6 +232,126 @@ static void samsung_keypad_close(struct input_dev *input_dev)
samsung_keypad_stop(keypad);
}
+#ifdef CONFIG_OF
+static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
+ struct device *dev)
+{
+ struct samsung_keypad_platdata *pdata;
+ struct matrix_keymap_data *keymap_data;
+ uint32_t *keymap, num_rows = 0, num_cols = 0;
+ struct device_node *np = dev->of_node, *key_np;
+ unsigned int key_count = 0;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "could not allocate memory for platform data\n");
+ return NULL;
+ }
+
+ of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows);
+ of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols);
+ if (!num_rows || !num_cols) {
+ dev_err(dev, "number of keypad rows/columns not specified\n");
+ return NULL;
+ }
+ pdata->rows = num_rows;
+ pdata->cols = num_cols;
+
+ keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL);
+ if (!keymap_data) {
+ dev_err(dev, "could not allocate memory for keymap data\n");
+ return NULL;
+ }
+ pdata->keymap_data = keymap_data;
+
+ for_each_child_of_node(np, key_np)
+ key_count++;
+
+ keymap_data->keymap_size = key_count;
+ keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL);
+ if (!keymap) {
+ dev_err(dev, "could not allocate memory for keymap\n");
+ return NULL;
+ }
+ keymap_data->keymap = keymap;
+
+ for_each_child_of_node(np, key_np) {
+ u32 row, col, key_code;
+ of_property_read_u32(key_np, "keypad,row", &row);
+ of_property_read_u32(key_np, "keypad,column", &col);
+ of_property_read_u32(key_np, "linux,code", &key_code);
+ *keymap++ = KEY(row, col, key_code);
+ }
+
+ if (of_get_property(np, "linux,input-no-autorepeat", NULL))
+ pdata->no_autorepeat = true;
+ if (of_get_property(np, "linux,input-wakeup", NULL))
+ pdata->wakeup = true;
+
+ return pdata;
+}
+
+static void samsung_keypad_parse_dt_gpio(struct device *dev,
+ struct samsung_keypad *keypad)
+{
+ struct device_node *np = dev->of_node;
+ int gpio, ret, row, col;
+
+ for (row = 0; row < keypad->rows; row++) {
+ gpio = of_get_named_gpio(np, "row-gpios", row);
+ keypad->row_gpios[row] = gpio;
+ if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "keypad row[%d]: invalid gpio %d\n",
+ row, gpio);
+ continue;
+ }
+
+ ret = gpio_request(gpio, "keypad-row");
+ if (ret)
+ dev_err(dev, "keypad row[%d] gpio request failed\n",
+ row);
+ }
+
+ for (col = 0; col < keypad->cols; col++) {
+ gpio = of_get_named_gpio(np, "col-gpios", col);
+ keypad->col_gpios[col] = gpio;
+ if (!gpio_is_valid(gpio)) {
+ dev_err(dev, "keypad column[%d]: invalid gpio %d\n",
+ col, gpio);
+ continue;
+ }
+
+ ret = gpio_request(gpio, "keypad-col");
+ if (ret)
+ dev_err(dev, "keypad column[%d] gpio request failed\n",
+ col);
+ }
+}
+
+static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad)
+{
+ int cnt;
+
+ for (cnt = 0; cnt < keypad->rows; cnt++)
+ if (gpio_is_valid(keypad->row_gpios[cnt]))
+ gpio_free(keypad->row_gpios[cnt]);
+
+ for (cnt = 0; cnt < keypad->cols; cnt++)
+ if (gpio_is_valid(keypad->col_gpios[cnt]))
+ gpio_free(keypad->col_gpios[cnt]);
+}
+#else
+static
+struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev)
+{
+ return NULL;
+}
+
+static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad)
+{
+}
+#endif
+
static int __devinit samsung_keypad_probe(struct platform_device *pdev)
{
const struct samsung_keypad_platdata *pdata;
@@ -246,7 +363,10 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
unsigned int keymap_size;
int error;
- pdata = pdev->dev.platform_data;
+ if (pdev->dev.of_node)
+ pdata = samsung_keypad_parse_dt(&pdev->dev);
+ else
+ pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data defined\n");
return -EINVAL;
@@ -303,6 +423,16 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
keypad->cols = pdata->cols;
init_waitqueue_head(&keypad->wait);
+ if (pdev->dev.of_node) {
+#ifdef CONFIG_OF
+ samsung_keypad_parse_dt_gpio(&pdev->dev, keypad);
+ keypad->type = of_device_is_compatible(pdev->dev.of_node,
+ "samsung,s5pv210-keypad");
+#endif
+ } else {
+ keypad->type = platform_get_device_id(pdev)->driver_data;
+ }
+
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
@@ -343,12 +473,19 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, pdata->wakeup);
platform_set_drvdata(pdev, keypad);
+
+ if (pdev->dev.of_node) {
+ devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap);
+ devm_kfree(&pdev->dev, (void *)pdata->keymap_data);
+ devm_kfree(&pdev->dev, (void *)pdata);
+ }
return 0;
err_free_irq:
free_irq(keypad->irq, keypad);
err_put_clk:
clk_put(keypad->clk);
+ samsung_keypad_dt_gpio_free(keypad);
err_unmap_base:
iounmap(keypad->base);
err_free_mem:
@@ -374,6 +511,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev)
free_irq(keypad->irq, keypad);
clk_put(keypad->clk);
+ samsung_keypad_dt_gpio_free(keypad);
iounmap(keypad->base);
kfree(keypad);
@@ -447,6 +585,17 @@ static const struct dev_pm_ops samsung_keypad_pm_ops = {
};
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_keypad_dt_match[] = {
+ { .compatible = "samsung,s3c6410-keypad" },
+ { .compatible = "samsung,s5pv210-keypad" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match);
+#else
+#define samsung_keypad_dt_match NULL
+#endif
+
static struct platform_device_id samsung_keypad_driver_ids[] = {
{
.name = "samsung-keypad",
@@ -465,6 +614,7 @@ static struct platform_driver samsung_keypad_driver = {
.driver = {
.name = "samsung-keypad",
.owner = THIS_MODULE,
+ .of_match_table = samsung_keypad_dt_match,
#ifdef CONFIG_PM
.pm = &samsung_keypad_pm_ops,
#endif
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 5b979d9cc33..175067a17c4 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -25,6 +25,7 @@
#include <linux/clk.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/of.h>
#include <mach/hardware.h>
#include <asm/uaccess.h>
@@ -507,7 +508,13 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
goto err_nortc;
}
- s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
+#ifdef CONFIG_OF
+ if (pdev->dev.of_node)
+ s3c_rtc_cpu_type = of_device_is_compatible(pdev->dev.of_node,
+ "samsung,s3c6410-rtc") ? TYPE_S3C64XX : TYPE_S3C2410;
+ else
+#endif
+ s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
/* Check RTC Time */
@@ -629,6 +636,17 @@ static int s3c_rtc_resume(struct platform_device *pdev)
#define s3c_rtc_resume NULL
#endif
+#ifdef CONFIG_OF
+static const struct of_device_id s3c_rtc_dt_match[] = {
+ { .compatible = "samsung,s3c2410-rtc" },
+ { .compatible = "samsung,s3c6410-rtc" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
+#else
+#define s3c_rtc_dt_match NULL
+#endif
+
static struct platform_device_id s3c_rtc_driver_ids[] = {
{
.name = "s3c2410-rtc",
@@ -651,6 +669,7 @@ static struct platform_driver s3c_rtc_driver = {
.driver = {
.name = "s3c-rtc",
.owner = THIS_MODULE,
+ .of_match_table = s3c_rtc_dt_match,
},
};
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 925a1e547a8..fb89b85d0d8 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -457,7 +457,7 @@ config SERIAL_SAMSUNG
config SERIAL_SAMSUNG_UARTS_4
bool
depends on ARM && PLAT_SAMSUNG
- default y if CPU_S3C2443
+ default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
help
Internal node for the common case of 4 Samsung compatible UARTs
@@ -465,7 +465,7 @@ config SERIAL_SAMSUNG_UARTS
int
depends on ARM && PLAT_SAMSUNG
default 6 if ARCH_S5P6450
- default 4 if SERIAL_SAMSUNG_UARTS_4
+ default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
default 3
help
Select the number of available UART ports for the Samsung S3C
@@ -495,47 +495,6 @@ config SERIAL_SAMSUNG_CONSOLE
your boot loader about how to pass options to the kernel at
boot time.)
-config SERIAL_S3C2410
- tristate "Samsung S3C2410 Serial port support"
- depends on SERIAL_SAMSUNG && CPU_S3C2410
- default y if CPU_S3C2410
- help
- Serial port support for the Samsung S3C2410 SoC
-
-config SERIAL_S3C2412
- tristate "Samsung S3C2412/S3C2413 Serial port support"
- depends on SERIAL_SAMSUNG && CPU_S3C2412
- default y if CPU_S3C2412
- help
- Serial port support for the Samsung S3C2412 and S3C2413 SoC
-
-config SERIAL_S3C2440
- tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416)
- default y if CPU_S3C2440
- default y if CPU_S3C2442
- select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416
- help
- Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC
-
-config SERIAL_S3C6400
- tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100)
- select SERIAL_SAMSUNG_UARTS_4
- default y
- help
- Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450
- and S5PC100 SoCs
-
-config SERIAL_S5PV210
- tristate "Samsung S5PV210 Serial port support"
- depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212)
- select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212)
- default y
- help
- Serial port support for Samsung's S5P Family of SoC's
-
-
config SERIAL_MAX3100
tristate "MAX3100 support"
depends on SPI
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index e10cf5b54b6..84bc2e5a57b 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -39,11 +39,6 @@ obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o
obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o
obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
-obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
-obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o
-obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o
-obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o
-obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c
deleted file mode 100644
index b1d7e7c1849..00000000000
--- a/drivers/tty/serial/s3c2410.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Driver for Samsung S3C2410 SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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 <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c2410_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2410_UCON_UCLK;
- else
- ucon &= ~S3C2410_UCON_UCLK;
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-static int s3c2410_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
- clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk";
-
- return 0;
-}
-
-static int s3c2410_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- wr_regl(port, S3C2410_UCON, cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2410_uart_inf = {
- .name = "Samsung S3C2410 UART",
- .type = PORT_S3C2410,
- .fifosize = 16,
- .rx_fifomask = S3C2410_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2410_UFSTAT_RXFULL,
- .tx_fifofull = S3C2410_UFSTAT_TXFULL,
- .tx_fifomask = S3C2410_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2410_serial_getsource,
- .set_clksrc = s3c2410_serial_setsource,
- .reset_port = s3c2410_serial_resetport,
-};
-
-static int s3c2410_serial_probe(struct platform_device *dev)
-{
- return s3c24xx_serial_probe(dev, &s3c2410_uart_inf);
-}
-
-static struct platform_driver s3c2410_serial_driver = {
- .probe = s3c2410_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2410-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s3c2410_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
-}
-
-static void __exit s3c2410_serial_exit(void)
-{
- platform_driver_unregister(&s3c2410_serial_driver);
-}
-
-module_init(s3c2410_serial_init);
-module_exit(s3c2410_serial_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2410 SoC Serial port driver");
-MODULE_ALIAS("platform:s3c2410-uart");
diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c
deleted file mode 100644
index 2234bf9ced4..00000000000
--- a/drivers/tty/serial/s3c2412.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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 <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-static int s3c2412_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- ucon &= ~S3C2412_UCON_CLKMASK;
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2440_UCON_UCLK;
- else if (strcmp(clk->name, "pclk") == 0)
- ucon |= S3C2440_UCON_PCLK;
- else if (strcmp(clk->name, "usysclk") == 0)
- ucon |= S3C2412_UCON_USYSCLK;
- else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s3c2412_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- switch (ucon & S3C2412_UCON_CLKMASK) {
- case S3C2412_UCON_UCLK:
- clk->divisor = 1;
- clk->name = "uclk";
- break;
-
- case S3C2412_UCON_PCLK:
- case S3C2412_UCON_PCLK2:
- clk->divisor = 1;
- clk->name = "pclk";
- break;
-
- case S3C2412_UCON_USYSCLK:
- clk->divisor = 1;
- clk->name = "usysclk";
- break;
- }
-
- return 0;
-}
-
-static int s3c2412_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- dbg("%s: port=%p (%08lx), cfg=%p\n",
- __func__, port, port->mapbase, cfg);
-
- /* ensure we don't change the clock settings... */
-
- ucon &= S3C2412_UCON_CLKMASK;
-
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2412_uart_inf = {
- .name = "Samsung S3C2412 UART",
- .type = PORT_S3C2412,
- .fifosize = 64,
- .has_divslot = 1,
- .rx_fifomask = S3C2440_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2440_UFSTAT_RXFULL,
- .tx_fifofull = S3C2440_UFSTAT_TXFULL,
- .tx_fifomask = S3C2440_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2412_serial_getsource,
- .set_clksrc = s3c2412_serial_setsource,
- .reset_port = s3c2412_serial_resetport,
-};
-
-/* device management */
-
-static int s3c2412_serial_probe(struct platform_device *dev)
-{
- dbg("s3c2440_serial_probe: dev=%p\n", dev);
- return s3c24xx_serial_probe(dev, &s3c2412_uart_inf);
-}
-
-static struct platform_driver s3c2412_serial_driver = {
- .probe = s3c2412_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2412-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static inline int s3c2412_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
-}
-
-static inline void s3c2412_serial_exit(void)
-{
- platform_driver_unregister(&s3c2412_serial_driver);
-}
-
-module_init(s3c2412_serial_init);
-module_exit(s3c2412_serial_exit);
-
-MODULE_DESCRIPTION("Samsung S3C2412,S3C2413 SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s3c2412-uart");
diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c
deleted file mode 100644
index 1d0c324b813..00000000000
--- a/drivers/tty/serial/s3c2440.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs.
- *
- * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- *
- * 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 <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-#include <mach/regs-gpio.h>
-
-#include "samsung.h"
-
-
-static int s3c2440_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- /* todo - proper fclk<>nonfclk switch. */
-
- ucon &= ~S3C2440_UCON_CLKMASK;
-
- if (strcmp(clk->name, "uclk") == 0)
- ucon |= S3C2440_UCON_UCLK;
- else if (strcmp(clk->name, "pclk") == 0)
- ucon |= S3C2440_UCON_PCLK;
- else if (strcmp(clk->name, "fclk") == 0)
- ucon |= S3C2440_UCON_FCLK;
- else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s3c2440_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
- unsigned long ucon0, ucon1, ucon2;
-
- switch (ucon & S3C2440_UCON_CLKMASK) {
- case S3C2440_UCON_UCLK:
- clk->divisor = 1;
- clk->name = "uclk";
- break;
-
- case S3C2440_UCON_PCLK:
- case S3C2440_UCON_PCLK2:
- clk->divisor = 1;
- clk->name = "pclk";
- break;
-
- case S3C2440_UCON_FCLK:
- /* the fun of calculating the uart divisors on
- * the s3c2440 */
-
- ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
- ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
- ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
-
- printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
-
- ucon0 &= S3C2440_UCON0_DIVMASK;
- ucon1 &= S3C2440_UCON1_DIVMASK;
- ucon2 &= S3C2440_UCON2_DIVMASK;
-
- if (ucon0 != 0) {
- clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
- clk->divisor += 6;
- } else if (ucon1 != 0) {
- clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
- clk->divisor += 21;
- } else if (ucon2 != 0) {
- clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
- clk->divisor += 36;
- } else {
- /* manual calims 44, seems to be 9 */
- clk->divisor = 9;
- }
-
- clk->name = "fclk";
- break;
- }
-
- return 0;
-}
-
-static int s3c2440_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- /* ensure we don't change the clock settings... */
-
- ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
-
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c2440_uart_inf = {
- .name = "Samsung S3C2440 UART",
- .type = PORT_S3C2440,
- .fifosize = 64,
- .rx_fifomask = S3C2440_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2440_UFSTAT_RXFULL,
- .tx_fifofull = S3C2440_UFSTAT_TXFULL,
- .tx_fifomask = S3C2440_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
- .get_clksrc = s3c2440_serial_getsource,
- .set_clksrc = s3c2440_serial_setsource,
- .reset_port = s3c2440_serial_resetport,
-};
-
-/* device management */
-
-static int s3c2440_serial_probe(struct platform_device *dev)
-{
- dbg("s3c2440_serial_probe: dev=%p\n", dev);
- return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
-}
-
-static struct platform_driver s3c2440_serial_driver = {
- .probe = s3c2440_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c2440-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s3c2440_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
-}
-
-static void __exit s3c2440_serial_exit(void)
-{
- platform_driver_unregister(&s3c2440_serial_driver);
-}
-
-module_init(s3c2440_serial_init);
-module_exit(s3c2440_serial_exit);
-
-MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s3c2440-uart");
diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c
deleted file mode 100644
index e2f6913d84d..00000000000
--- a/drivers/tty/serial/s3c6400.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs.
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
- * http://armlinux.simtec.co.uk/
- *
- * 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 <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <plat/regs-serial.h>
-
-#include "samsung.h"
-
-static int s3c6400_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if (strcmp(clk->name, "uclk0") == 0) {
- ucon &= ~S3C6400_UCON_CLKMASK;
- ucon |= S3C6400_UCON_UCLK0;
- } else if (strcmp(clk->name, "uclk1") == 0)
- ucon |= S3C6400_UCON_UCLK1;
- else if (strcmp(clk->name, "pclk") == 0) {
- /* See notes about transitioning from UCLK to PCLK */
- ucon &= ~S3C6400_UCON_UCLK0;
- } else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s3c6400_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- u32 ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
-
- switch (ucon & S3C6400_UCON_CLKMASK) {
- case S3C6400_UCON_UCLK0:
- clk->name = "uclk0";
- break;
-
- case S3C6400_UCON_UCLK1:
- clk->name = "uclk1";
- break;
-
- case S3C6400_UCON_PCLK:
- case S3C6400_UCON_PCLK2:
- clk->name = "pclk";
- break;
- }
-
- return 0;
-}
-
-static int s3c6400_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n",
- port, port->mapbase, cfg);
-
- /* ensure we don't change the clock settings... */
-
- ucon &= S3C6400_UCON_CLKMASK;
-
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
-
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- return 0;
-}
-
-static struct s3c24xx_uart_info s3c6400_uart_inf = {
- .name = "Samsung S3C6400 UART",
- .type = PORT_S3C6400,
- .fifosize = 64,
- .has_divslot = 1,
- .rx_fifomask = S3C2440_UFSTAT_RXMASK,
- .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
- .rx_fifofull = S3C2440_UFSTAT_RXFULL,
- .tx_fifofull = S3C2440_UFSTAT_TXFULL,
- .tx_fifomask = S3C2440_UFSTAT_TXMASK,
- .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
- .get_clksrc = s3c6400_serial_getsource,
- .set_clksrc = s3c6400_serial_setsource,
- .reset_port = s3c6400_serial_resetport,
-};
-
-/* device management */
-
-static int s3c6400_serial_probe(struct platform_device *dev)
-{
- dbg("s3c6400_serial_probe: dev=%p\n", dev);
- return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);
-}
-
-static struct platform_driver s3c6400_serial_driver = {
- .probe = s3c6400_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s3c6400-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s3c6400_serial_init(void)
-{
- return s3c24xx_serial_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
-}
-
-static void __exit s3c6400_serial_exit(void)
-{
- platform_driver_unregister(&s3c6400_serial_driver);
-}
-
-module_init(s3c6400_serial_init);
-module_exit(s3c6400_serial_exit);
-
-MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver");
-MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:s3c6400-uart");
diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c
deleted file mode 100644
index 8b0b888a1b7..00000000000
--- a/drivers/tty/serial/s5pv210.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Based on drivers/serial/s3c6400.c
- *
- * Driver for Samsung S5PV210 SoC UARTs.
- *
- * 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 <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/delay.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <plat/regs-serial.h>
-#include "samsung.h"
-
-static int s5pv210_serial_setsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- struct s3c2410_uartcfg *cfg = port->dev->platform_data;
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- if (cfg->flags & NO_NEED_CHECK_CLKSRC)
- return 0;
-
- if (strcmp(clk->name, "pclk") == 0)
- ucon &= ~S5PV210_UCON_CLKMASK;
- else if (strcmp(clk->name, "uclk1") == 0)
- ucon |= S5PV210_UCON_CLKMASK;
- else {
- printk(KERN_ERR "unknown clock source %s\n", clk->name);
- return -EINVAL;
- }
-
- wr_regl(port, S3C2410_UCON, ucon);
- return 0;
-}
-
-
-static int s5pv210_serial_getsource(struct uart_port *port,
- struct s3c24xx_uart_clksrc *clk)
-{
- struct s3c2410_uartcfg *cfg = port->dev->platform_data;
- u32 ucon = rd_regl(port, S3C2410_UCON);
-
- clk->divisor = 1;
-
- if (cfg->flags & NO_NEED_CHECK_CLKSRC)
- return 0;
-
- switch (ucon & S5PV210_UCON_CLKMASK) {
- case S5PV210_UCON_PCLK:
- clk->name = "pclk";
- break;
- case S5PV210_UCON_UCLK:
- clk->name = "uclk1";
- break;
- }
-
- return 0;
-}
-
-static int s5pv210_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
-{
- unsigned long ucon = rd_regl(port, S3C2410_UCON);
-
- ucon &= S5PV210_UCON_CLKMASK;
- wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
- wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
- /* reset both fifos */
- wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
- wr_regl(port, S3C2410_UFCON, cfg->ufcon);
-
- /* It is need to delay When reset FIFO register */
- udelay(1);
-
- return 0;
-}
-
-#define S5PV210_UART_DEFAULT_INFO(fifo_size) \
- .name = "Samsung S5PV210 UART0", \
- .type = PORT_S3C6400, \
- .fifosize = fifo_size, \
- .has_divslot = 1, \
- .rx_fifomask = S5PV210_UFSTAT_RXMASK, \
- .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \
- .rx_fifofull = S5PV210_UFSTAT_RXFULL, \
- .tx_fifofull = S5PV210_UFSTAT_TXFULL, \
- .tx_fifomask = S5PV210_UFSTAT_TXMASK, \
- .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \
- .get_clksrc = s5pv210_serial_getsource, \
- .set_clksrc = s5pv210_serial_setsource, \
- .reset_port = s5pv210_serial_resetport
-
-static struct s3c24xx_uart_info s5p_port_fifo256 = {
- S5PV210_UART_DEFAULT_INFO(256),
-};
-
-static struct s3c24xx_uart_info s5p_port_fifo64 = {
- S5PV210_UART_DEFAULT_INFO(64),
-};
-
-static struct s3c24xx_uart_info s5p_port_fifo16 = {
- S5PV210_UART_DEFAULT_INFO(16),
-};
-
-static struct s3c24xx_uart_info *s5p_uart_inf[] = {
- [0] = &s5p_port_fifo256,
- [1] = &s5p_port_fifo64,
- [2] = &s5p_port_fifo16,
- [3] = &s5p_port_fifo16,
-};
-
-/* device management */
-static int s5p_serial_probe(struct platform_device *pdev)
-{
- return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]);
-}
-
-static struct platform_driver s5p_serial_driver = {
- .probe = s5p_serial_probe,
- .remove = __devexit_p(s3c24xx_serial_remove),
- .driver = {
- .name = "s5pv210-uart",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s5p_serial_init(void)
-{
- return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf);
-}
-
-static void __exit s5p_serial_exit(void)
-{
- platform_driver_unregister(&s5p_serial_driver);
-}
-
-module_init(s5p_serial_init);
-module_exit(s5p_serial_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:s5pv210-uart");
-MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support");
-MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>");
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index b31f1c3a2c4..f96f37b5fec 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -42,6 +42,7 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
+#include <linux/of.h>
#include <asm/irq.h>
@@ -49,6 +50,7 @@
#include <mach/map.h>
#include <plat/regs-serial.h>
+#include <plat/clock.h>
#include "samsung.h"
@@ -190,10 +192,13 @@ static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *p
static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port)
{
+ struct s3c24xx_uart_port *ourport;
+
if (port->dev == NULL)
return NULL;
- return (struct s3c2410_uartcfg *)port->dev->platform_data;
+ ourport = container_of(port, struct s3c24xx_uart_port, port);
+ return ourport->cfg;
}
static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
@@ -202,7 +207,7 @@ static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport,
struct s3c24xx_uart_info *info = ourport->info;
if (ufstat & info->rx_fifofull)
- return info->fifosize;
+ return ourport->port.fifosize;
return (ufstat & info->rx_fifomask) >> info->rx_fifoshift;
}
@@ -555,154 +560,98 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
*
*/
+#define MAX_CLK_NAME_LENGTH 15
-#define MAX_CLKS (8)
-
-static struct s3c24xx_uart_clksrc tmp_clksrc = {
- .name = "pclk",
- .min_baud = 0,
- .max_baud = 0,
- .divisor = 1,
-};
-
-static inline int
-s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
+static inline int s3c24xx_serial_getsource(struct uart_port *port)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+ unsigned int ucon;
- return (info->get_clksrc)(port, c);
-}
-
-static inline int
-s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c)
-{
- struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+ if (info->num_clks == 1)
+ return 0;
- return (info->set_clksrc)(port, c);
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= info->clksel_mask;
+ return ucon >> info->clksel_shift;
}
-struct baud_calc {
- struct s3c24xx_uart_clksrc *clksrc;
- unsigned int calc;
- unsigned int divslot;
- unsigned int quot;
- struct clk *src;
-};
-
-static int s3c24xx_serial_calcbaud(struct baud_calc *calc,
- struct uart_port *port,
- struct s3c24xx_uart_clksrc *clksrc,
- unsigned int baud)
+static void s3c24xx_serial_setsource(struct uart_port *port,
+ unsigned int clk_sel)
{
- struct s3c24xx_uart_port *ourport = to_ourport(port);
- unsigned long rate;
-
- calc->src = clk_get(port->dev, clksrc->name);
- if (calc->src == NULL || IS_ERR(calc->src))
- return 0;
-
- rate = clk_get_rate(calc->src);
- rate /= clksrc->divisor;
+ struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+ unsigned int ucon;
- calc->clksrc = clksrc;
+ if (info->num_clks == 1)
+ return;
- if (ourport->info->has_divslot) {
- unsigned long div = rate / baud;
-
- /* The UDIVSLOT register on the newer UARTs allows us to
- * get a divisor adjustment of 1/16th on the baud clock.
- *
- * We don't keep the UDIVSLOT value (the 16ths we calculated
- * by not multiplying the baud by 16) as it is easy enough
- * to recalculate.
- */
-
- calc->quot = div / 16;
- calc->calc = rate / div;
- } else {
- calc->quot = (rate + (8 * baud)) / (16 * baud);
- calc->calc = (rate / (calc->quot * 16));
- }
+ ucon = rd_regl(port, S3C2410_UCON);
+ if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel)
+ return;
- calc->quot--;
- return 1;
+ ucon &= ~info->clksel_mask;
+ ucon |= clk_sel << info->clksel_shift;
+ wr_regl(port, S3C2410_UCON, ucon);
}
-static unsigned int s3c24xx_serial_getclk(struct uart_port *port,
- struct s3c24xx_uart_clksrc **clksrc,
- struct clk **clk,
- unsigned int baud)
+static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport,
+ unsigned int req_baud, struct clk **best_clk,
+ unsigned int *clk_num)
{
- struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
- struct s3c24xx_uart_clksrc *clkp;
- struct baud_calc res[MAX_CLKS];
- struct baud_calc *resptr, *best, *sptr;
- int i;
-
- clkp = cfg->clocks;
- best = NULL;
-
- if (cfg->clocks_size < 2) {
- if (cfg->clocks_size == 0)
- clkp = &tmp_clksrc;
-
- /* check to see if we're sourcing fclk, and if so we're
- * going to have to update the clock source
- */
-
- if (strcmp(clkp->name, "fclk") == 0) {
- struct s3c24xx_uart_clksrc src;
-
- s3c24xx_serial_getsource(port, &src);
-
- /* check that the port already using fclk, and if
- * not, then re-select fclk
+ struct s3c24xx_uart_info *info = ourport->info;
+ struct clk *clk;
+ unsigned long rate;
+ unsigned int cnt, baud, quot, clk_sel, best_quot = 0;
+ char clkname[MAX_CLK_NAME_LENGTH];
+ int calc_deviation, deviation = (1 << 30) - 1;
+
+ *best_clk = NULL;
+ clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel :
+ ourport->info->def_clk_sel;
+ for (cnt = 0; cnt < info->num_clks; cnt++) {
+ if (!(clk_sel & (1 << cnt)))
+ continue;
+
+ sprintf(clkname, "clk_uart_baud%d", cnt);
+ clk = clk_get(ourport->port.dev, clkname);
+ if (IS_ERR_OR_NULL(clk))
+ continue;
+
+ rate = clk_get_rate(clk);
+ if (!rate)
+ continue;
+
+ if (ourport->info->has_divslot) {
+ unsigned long div = rate / req_baud;
+
+ /* The UDIVSLOT register on the newer UARTs allows us to
+ * get a divisor adjustment of 1/16th on the baud clock.
+ *
+ * We don't keep the UDIVSLOT value (the 16ths we
+ * calculated by not multiplying the baud by 16) as it
+ * is easy enough to recalculate.
*/
- if (strcmp(src.name, clkp->name) == 0) {
- s3c24xx_serial_setsource(port, clkp);
- s3c24xx_serial_getsource(port, &src);
- }
-
- clkp->divisor = src.divisor;
- }
-
- s3c24xx_serial_calcbaud(res, port, clkp, baud);
- best = res;
- resptr = best + 1;
- } else {
- resptr = res;
-
- for (i = 0; i < cfg->clocks_size; i++, clkp++) {
- if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud))
- resptr++;
+ quot = div / 16;
+ baud = rate / div;
+ } else {
+ quot = (rate + (8 * req_baud)) / (16 * req_baud);
+ baud = rate / (quot * 16);
}
- }
-
- /* ok, we now need to select the best clock we found */
-
- if (!best) {
- unsigned int deviation = (1<<30)|((1<<30)-1);
- int calc_deviation;
+ quot--;
- for (sptr = res; sptr < resptr; sptr++) {
- calc_deviation = baud - sptr->calc;
- if (calc_deviation < 0)
- calc_deviation = -calc_deviation;
+ calc_deviation = req_baud - baud;
+ if (calc_deviation < 0)
+ calc_deviation = -calc_deviation;
- if (calc_deviation < deviation) {
- best = sptr;
- deviation = calc_deviation;
- }
+ if (calc_deviation < deviation) {
+ *best_clk = clk;
+ best_quot = quot;
+ *clk_num = cnt;
+ deviation = calc_deviation;
}
}
- /* store results to pass back */
-
- *clksrc = best->clksrc;
- *clk = best->src;
-
- return best->quot;
+ return best_quot;
}
/* udivslot_table[]
@@ -735,10 +684,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
{
struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- struct s3c24xx_uart_clksrc *clksrc = NULL;
struct clk *clk = NULL;
unsigned long flags;
- unsigned int baud, quot;
+ unsigned int baud, quot, clk_sel = 0;
unsigned int ulcon;
unsigned int umcon;
unsigned int udivslot = 0;
@@ -754,17 +702,16 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
*/
baud = uart_get_baud_rate(port, termios, old, 0, 115200*8);
-
+ quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel);
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
- else
- quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud);
+ if (!clk)
+ return;
/* check to see if we need to change clock source */
- if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
- dbg("selecting clock %p\n", clk);
- s3c24xx_serial_setsource(port, clksrc);
+ if (ourport->baudclk != clk) {
+ s3c24xx_serial_setsource(port, clk_sel);
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
clk_disable(ourport->baudclk);
@@ -773,7 +720,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
clk_enable(clk);
- ourport->clksrc = clksrc;
ourport->baudclk = clk;
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
}
@@ -1020,16 +966,29 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS
/* s3c24xx_serial_resetport
*
- * wrapper to call the specific reset for this port (reset the fifos
- * and the settings)
+ * reset the fifos and other the settings.
*/
-static inline int s3c24xx_serial_resetport(struct uart_port *port,
- struct s3c2410_uartcfg *cfg)
+static void s3c24xx_serial_resetport(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg)
{
struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+ unsigned int ucon_mask;
+
+ ucon_mask = info->clksel_mask;
+ if (info->type == PORT_S3C2440)
+ ucon_mask |= S3C2440_UCON0_DIVMASK;
- return (info->reset_port)(port, cfg);
+ ucon &= ucon_mask;
+ wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+
+ /* reset both fifos */
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+ wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+ /* some delay is required after fifo reset */
+ udelay(1);
}
@@ -1121,11 +1080,10 @@ static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *p
*/
static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
- struct s3c24xx_uart_info *info,
struct platform_device *platdev)
{
struct uart_port *port = &ourport->port;
- struct s3c2410_uartcfg *cfg;
+ struct s3c2410_uartcfg *cfg = ourport->cfg;
struct resource *res;
int ret;
@@ -1134,30 +1092,16 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
if (platdev == NULL)
return -ENODEV;
- cfg = s3c24xx_dev_to_cfg(&platdev->dev);
-
if (port->mapbase != 0)
return 0;
- if (cfg->hwport > CONFIG_SERIAL_SAMSUNG_UARTS) {
- printk(KERN_ERR "%s: port %d bigger than %d\n", __func__,
- cfg->hwport, CONFIG_SERIAL_SAMSUNG_UARTS);
- return -ERANGE;
- }
-
/* setup info for port */
port->dev = &platdev->dev;
- ourport->info = info;
/* Startup sequence is different for s3c64xx and higher SoC's */
if (s3c24xx_serial_has_interrupt_mask(port))
s3c24xx_serial_ops.startup = s3c64xx_serial_startup;
- /* copy the info in from provided structure */
- ourport->port.fifosize = info->fifosize;
-
- dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport);
-
port->uartclk = 1;
if (cfg->uart_flags & UPF_CONS_FLOW) {
@@ -1215,43 +1159,74 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
- return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->clksrc->name);
+ return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name);
}
static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
+
/* Device driver serial port probe */
+static const struct of_device_id s3c24xx_uart_dt_match[];
static int probe_index;
-int s3c24xx_serial_probe(struct platform_device *dev,
- struct s3c24xx_uart_info *info)
+static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(
+ struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+ if (pdev->dev.of_node) {
+ const struct of_device_id *match;
+ match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node);
+ return (struct s3c24xx_serial_drv_data *)match->data;
+ }
+#endif
+ return (struct s3c24xx_serial_drv_data *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
+static int s3c24xx_serial_probe(struct platform_device *pdev)
{
struct s3c24xx_uart_port *ourport;
int ret;
- dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index);
+ dbg("s3c24xx_serial_probe(%p) %d\n", pdev, probe_index);
ourport = &s3c24xx_serial_ports[probe_index];
+
+ ourport->drv_data = s3c24xx_get_driver_data(pdev);
+ if (!ourport->drv_data) {
+ dev_err(&pdev->dev, "could not find driver data\n");
+ return -ENODEV;
+ }
+
+ ourport->info = ourport->drv_data->info;
+ ourport->cfg = (pdev->dev.platform_data) ?
+ (struct s3c2410_uartcfg *)pdev->dev.platform_data :
+ ourport->drv_data->def_cfg;
+
+ ourport->port.fifosize = (ourport->info->fifosize) ?
+ ourport->info->fifosize :
+ ourport->drv_data->fifosize[probe_index];
+
probe_index++;
dbg("%s: initialising port %p...\n", __func__, ourport);
- ret = s3c24xx_serial_init_port(ourport, info, dev);
+ ret = s3c24xx_serial_init_port(ourport, pdev);
if (ret < 0)
goto probe_err;
dbg("%s: adding port\n", __func__);
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
- platform_set_drvdata(dev, &ourport->port);
+ platform_set_drvdata(pdev, &ourport->port);
- ret = device_create_file(&dev->dev, &dev_attr_clock_source);
+ ret = device_create_file(&pdev->dev, &dev_attr_clock_source);
if (ret < 0)
- printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__);
+ dev_err(&pdev->dev, "failed to add clock source attr.\n");
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
- dev_err(&dev->dev, "failed to add cpufreq notifier\n");
+ dev_err(&pdev->dev, "failed to add cpufreq notifier\n");
return 0;
@@ -1259,9 +1234,7 @@ int s3c24xx_serial_probe(struct platform_device *dev,
return ret;
}
-EXPORT_SYMBOL_GPL(s3c24xx_serial_probe);
-
-int __devexit s3c24xx_serial_remove(struct platform_device *dev)
+static int __devexit s3c24xx_serial_remove(struct platform_device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
@@ -1274,8 +1247,6 @@ int __devexit s3c24xx_serial_remove(struct platform_device *dev)
return 0;
}
-EXPORT_SYMBOL_GPL(s3c24xx_serial_remove);
-
/* UART power management code */
#ifdef CONFIG_PM_SLEEP
static int s3c24xx_serial_suspend(struct device *dev)
@@ -1315,41 +1286,6 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
#define SERIAL_SAMSUNG_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
-int s3c24xx_serial_init(struct platform_driver *drv,
- struct s3c24xx_uart_info *info)
-{
- dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
-
- drv->driver.pm = SERIAL_SAMSUNG_PM_OPS;
-
- return platform_driver_register(drv);
-}
-
-EXPORT_SYMBOL_GPL(s3c24xx_serial_init);
-
-/* module initialisation code */
-
-static int __init s3c24xx_serial_modinit(void)
-{
- int ret;
-
- ret = uart_register_driver(&s3c24xx_uart_drv);
- if (ret < 0) {
- printk(KERN_ERR "failed to register UART driver\n");
- return -1;
- }
-
- return 0;
-}
-
-static void __exit s3c24xx_serial_modexit(void)
-{
- uart_unregister_driver(&s3c24xx_uart_drv);
-}
-
-module_init(s3c24xx_serial_modinit);
-module_exit(s3c24xx_serial_modexit);
-
/* Console code */
#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
@@ -1395,12 +1331,13 @@ static void __init
s3c24xx_serial_get_options(struct uart_port *port, int *baud,
int *parity, int *bits)
{
- struct s3c24xx_uart_clksrc clksrc;
struct clk *clk;
unsigned int ulcon;
unsigned int ucon;
unsigned int ubrdiv;
unsigned long rate;
+ unsigned int clk_sel;
+ char clk_name[MAX_CLK_NAME_LENGTH];
ulcon = rd_regl(port, S3C2410_ULCON);
ucon = rd_regl(port, S3C2410_UCON);
@@ -1445,44 +1382,21 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
/* now calculate the baud rate */
- s3c24xx_serial_getsource(port, &clksrc);
+ clk_sel = s3c24xx_serial_getsource(port);
+ sprintf(clk_name, "clk_uart_baud%d", clk_sel);
- clk = clk_get(port->dev, clksrc.name);
+ clk = clk_get(port->dev, clk_name);
if (!IS_ERR(clk) && clk != NULL)
- rate = clk_get_rate(clk) / clksrc.divisor;
+ rate = clk_get_rate(clk);
else
rate = 1;
-
*baud = rate / (16 * (ubrdiv + 1));
dbg("calculated baud %d\n", *baud);
}
}
-/* s3c24xx_serial_init_ports
- *
- * initialise the serial ports from the machine provided initialisation
- * data.
-*/
-
-static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info)
-{
- struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports;
- struct platform_device **platdev_ptr;
- int i;
-
- dbg("s3c24xx_serial_init_ports: initialising ports...\n");
-
- platdev_ptr = s3c24xx_uart_devs;
-
- for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) {
- s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr);
- }
-
- return 0;
-}
-
static int __init
s3c24xx_serial_console_setup(struct console *co, char *options)
{
@@ -1526,11 +1440,6 @@ s3c24xx_serial_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-/* s3c24xx_serial_initconsole
- *
- * initialise the console from one of the uart drivers
-*/
-
static struct console s3c24xx_serial_console = {
.name = S3C24XX_SERIAL_NAME,
.device = uart_console_device,
@@ -1540,34 +1449,250 @@ static struct console s3c24xx_serial_console = {
.setup = s3c24xx_serial_console_setup,
.data = &s3c24xx_uart_drv,
};
+#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
-int s3c24xx_serial_initconsole(struct platform_driver *drv,
- struct s3c24xx_uart_info **info)
+#ifdef CONFIG_CPU_S3C2410
+static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Samsung S3C2410 UART",
+ .type = PORT_S3C2410,
+ .fifosize = 16,
+ .rx_fifomask = S3C2410_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2410_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2410_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2410_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL0,
+ .num_clks = 2,
+ .clksel_mask = S3C2410_UCON_CLKMASK,
+ .clksel_shift = S3C2410_UCON_CLKSHIFT,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = S3C2410_UCON_DEFAULT,
+ .ufcon = S3C2410_UFCON_DEFAULT,
+ },
+};
+#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data)
+#else
+#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#endif
-{
- struct platform_device *dev = s3c24xx_uart_devs[0];
+#ifdef CONFIG_CPU_S3C2412
+static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Samsung S3C2412 UART",
+ .type = PORT_S3C2412,
+ .fifosize = 64,
+ .has_divslot = 1,
+ .rx_fifomask = S3C2440_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2440_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2440_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2440_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL2,
+ .num_clks = 4,
+ .clksel_mask = S3C2412_UCON_CLKMASK,
+ .clksel_shift = S3C2412_UCON_CLKSHIFT,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = S3C2410_UCON_DEFAULT,
+ .ufcon = S3C2410_UFCON_DEFAULT,
+ },
+};
+#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data)
+#else
+#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#endif
- dbg("s3c24xx_serial_initconsole\n");
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \
+ defined(CONFIG_CPU_S3C2443)
+static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Samsung S3C2440 UART",
+ .type = PORT_S3C2440,
+ .fifosize = 64,
+ .has_divslot = 1,
+ .rx_fifomask = S3C2440_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2440_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2440_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2440_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL2,
+ .num_clks = 4,
+ .clksel_mask = S3C2412_UCON_CLKMASK,
+ .clksel_shift = S3C2412_UCON_CLKSHIFT,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = S3C2410_UCON_DEFAULT,
+ .ufcon = S3C2410_UFCON_DEFAULT,
+ },
+};
+#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data)
+#else
+#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#endif
- /* select driver based on the cpu */
+#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \
+ defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \
+ defined(CONFIG_CPU_S5PC100)
+static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Samsung S3C6400 UART",
+ .type = PORT_S3C6400,
+ .fifosize = 64,
+ .has_divslot = 1,
+ .rx_fifomask = S3C2440_UFSTAT_RXMASK,
+ .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
+ .rx_fifofull = S3C2440_UFSTAT_RXFULL,
+ .tx_fifofull = S3C2440_UFSTAT_TXFULL,
+ .tx_fifomask = S3C2440_UFSTAT_TXMASK,
+ .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL2,
+ .num_clks = 4,
+ .clksel_mask = S3C6400_UCON_CLKMASK,
+ .clksel_shift = S3C6400_UCON_CLKSHIFT,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = S3C2410_UCON_DEFAULT,
+ .ufcon = S3C2410_UFCON_DEFAULT,
+ },
+};
+#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data)
+#else
+#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#endif
- if (dev == NULL) {
- printk(KERN_ERR "s3c24xx: no devices for console init\n");
- return 0;
- }
+#ifdef CONFIG_CPU_S5PV210
+static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Samsung S5PV210 UART",
+ .type = PORT_S3C6400,
+ .has_divslot = 1,
+ .rx_fifomask = S5PV210_UFSTAT_RXMASK,
+ .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
+ .rx_fifofull = S5PV210_UFSTAT_RXFULL,
+ .tx_fifofull = S5PV210_UFSTAT_TXFULL,
+ .tx_fifomask = S5PV210_UFSTAT_TXMASK,
+ .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL0,
+ .num_clks = 2,
+ .clksel_mask = S5PV210_UCON_CLKMASK,
+ .clksel_shift = S5PV210_UCON_CLKSHIFT,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = S5PV210_UCON_DEFAULT,
+ .ufcon = S5PV210_UFCON_DEFAULT,
+ },
+ .fifosize = { 256, 64, 16, 16 },
+};
+#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data)
+#else
+#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#endif
- if (strcmp(dev->name, drv->driver.name) != 0)
- return 0;
+#ifdef CONFIG_CPU_EXYNOS4210
+static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {
+ .info = &(struct s3c24xx_uart_info) {
+ .name = "Samsung Exynos4 UART",
+ .type = PORT_S3C6400,
+ .has_divslot = 1,
+ .rx_fifomask = S5PV210_UFSTAT_RXMASK,
+ .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT,
+ .rx_fifofull = S5PV210_UFSTAT_RXFULL,
+ .tx_fifofull = S5PV210_UFSTAT_TXFULL,
+ .tx_fifomask = S5PV210_UFSTAT_TXMASK,
+ .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT,
+ .def_clk_sel = S3C2410_UCON_CLKSEL0,
+ .num_clks = 1,
+ .clksel_mask = 0,
+ .clksel_shift = 0,
+ },
+ .def_cfg = &(struct s3c2410_uartcfg) {
+ .ucon = S5PV210_UCON_DEFAULT,
+ .ufcon = S5PV210_UFCON_DEFAULT,
+ .has_fracval = 1,
+ },
+ .fifosize = { 256, 64, 16, 16 },
+};
+#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data)
+#else
+#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL
+#endif
- s3c24xx_serial_console.data = &s3c24xx_uart_drv;
- s3c24xx_serial_init_ports(info);
+static struct platform_device_id s3c24xx_serial_driver_ids[] = {
+ {
+ .name = "s3c2410-uart",
+ .driver_data = S3C2410_SERIAL_DRV_DATA,
+ }, {
+ .name = "s3c2412-uart",
+ .driver_data = S3C2412_SERIAL_DRV_DATA,
+ }, {
+ .name = "s3c2440-uart",
+ .driver_data = S3C2440_SERIAL_DRV_DATA,
+ }, {
+ .name = "s3c6400-uart",
+ .driver_data = S3C6400_SERIAL_DRV_DATA,
+ }, {
+ .name = "s5pv210-uart",
+ .driver_data = S5PV210_SERIAL_DRV_DATA,
+ }, {
+ .name = "exynos4210-uart",
+ .driver_data = EXYNOS4210_SERIAL_DRV_DATA,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids);
- register_console(&s3c24xx_serial_console);
- return 0;
+#ifdef CONFIG_OF
+static const struct of_device_id s3c24xx_uart_dt_match[] = {
+ { .compatible = "samsung,exynos4210-uart",
+ .data = (void *)EXYNOS4210_SERIAL_DRV_DATA },
+ {},
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
+#else
+#define s3c24xx_uart_dt_match NULL
+#endif
+
+static struct platform_driver samsung_serial_driver = {
+ .probe = s3c24xx_serial_probe,
+ .remove = __devexit_p(s3c24xx_serial_remove),
+ .id_table = s3c24xx_serial_driver_ids,
+ .driver = {
+ .name = "samsung-uart",
+ .owner = THIS_MODULE,
+ .pm = SERIAL_SAMSUNG_PM_OPS,
+ .of_match_table = s3c24xx_uart_dt_match,
+ },
+};
+
+/* module initialisation code */
+
+static int __init s3c24xx_serial_modinit(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&s3c24xx_uart_drv);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to register UART driver\n");
+ return -1;
+ }
+
+ return platform_driver_register(&samsung_serial_driver);
}
-#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
+static void __exit s3c24xx_serial_modexit(void)
+{
+ uart_unregister_driver(&s3c24xx_uart_drv);
+}
+
+module_init(s3c24xx_serial_modinit);
+module_exit(s3c24xx_serial_modexit);
+MODULE_ALIAS("platform:samsung-uart");
MODULE_DESCRIPTION("Samsung SoC Serial port driver");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index 8e87b788e5c..1a4bca3e417 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -19,20 +19,25 @@ struct s3c24xx_uart_info {
unsigned long tx_fifomask;
unsigned long tx_fifoshift;
unsigned long tx_fifofull;
+ unsigned int def_clk_sel;
+ unsigned long num_clks;
+ unsigned long clksel_mask;
+ unsigned long clksel_shift;
/* uart port features */
unsigned int has_divslot:1;
- /* clock source control */
-
- int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
- int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
-
/* uart controls */
int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);
};
+struct s3c24xx_serial_drv_data {
+ struct s3c24xx_uart_info *info;
+ struct s3c2410_uartcfg *def_cfg;
+ unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS];
+};
+
struct s3c24xx_uart_port {
unsigned char rx_claimed;
unsigned char tx_claimed;
@@ -43,10 +48,13 @@ struct s3c24xx_uart_port {
unsigned int tx_irq;
struct s3c24xx_uart_info *info;
- struct s3c24xx_uart_clksrc *clksrc;
struct clk *clk;
struct clk *baudclk;
struct uart_port port;
+ struct s3c24xx_serial_drv_data *drv_data;
+
+ /* reference to platform data */
+ struct s3c2410_uartcfg *cfg;
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
@@ -56,7 +64,6 @@ struct s3c24xx_uart_port {
/* conversion functions */
#define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev)
-#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data)
/* register access controls */
@@ -69,17 +76,6 @@ struct s3c24xx_uart_port {
#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
-extern int s3c24xx_serial_probe(struct platform_device *dev,
- struct s3c24xx_uart_info *uart);
-
-extern int __devexit s3c24xx_serial_remove(struct platform_device *dev);
-
-extern int s3c24xx_serial_initconsole(struct platform_driver *drv,
- struct s3c24xx_uart_info **uart);
-
-extern int s3c24xx_serial_init(struct platform_driver *drv,
- struct s3c24xx_uart_info *info);
-
#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
extern void printascii(const char *);
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
index d12f077a6da..12e023c19ac 100644
--- a/include/linux/amba/pl330.h
+++ b/include/linux/amba/pl330.h
@@ -12,17 +12,9 @@
#ifndef __AMBA_PL330_H_
#define __AMBA_PL330_H_
+#include <linux/dmaengine.h>
#include <asm/hardware/pl330.h>
-struct dma_pl330_peri {
- /*
- * Peri_Req i/f of the DMAC that is
- * peripheral could be reached from.
- */
- u8 peri_id; /* specific dma id */
- enum pl330_reqtype rqtype;
-};
-
struct dma_pl330_platdata {
/*
* Number of valid peripherals connected to DMAC.
@@ -33,9 +25,12 @@ struct dma_pl330_platdata {
*/
u8 nr_valid_peri;
/* Array of valid peripherals */
- struct dma_pl330_peri *peri;
+ u8 *peri_id;
+ /* Operational capabilities */
+ dma_cap_mask_t cap_mask;
/* Bytes to allocate for MC buffer */
unsigned mcbuf_sz;
};
+extern bool pl330_filter(struct dma_chan *chan, void *param);
#endif /* __AMBA_PL330_H_ */