Commit bd4b9ba4 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge branch 'samsung/cleanup' into next/drivers

Dependency for the samsung/drivers branch

Conflicts:
	arch/arm/mach-exynos/Makefile
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents e814fb63 8a44930a
* 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.
* 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.
* 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>;
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;
};
* 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>;
};
};
* 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>;
};
* 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.
/*
* 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";
};
};
/*
* 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";
};
};
/*
* 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>;
};
};
};
......@@ -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
......@@ -182,6 +187,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_USB_OHCI
......@@ -203,6 +209,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
......@@ -228,6 +235,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
......@@ -261,6 +269,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
......@@ -293,6 +302,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_DEV_USB_OHCI
select EXYNOS4_SETUP_FIMD0
......@@ -334,6 +344,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"
......
......@@ -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_DEV_USB_OHCI) += dev-ohci.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
......@@ -56,6 +59,5 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C5) += setup-i2c5.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C6) += setup-i2c6.o
obj-$(CONFIG_EXYNOS4_SETUP_I2C7) += setup-i2c7.o
obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_EXYNOS4_SETUP_USB_PHY) += setup-usb-phy.o
......@@ -552,16 +552,6 @@ static struct clk init_clocks_off[] = {
.devname = "s5p-sdo",
.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,
......@@ -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,
......@@ -1190,42 +1154,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_mout_mfc,
.reg_src = { .reg = S5P_CLKSRC_MFC, .shift = 8, .size = 1 },
.reg_div = { .reg = S5P_CLKDIV_MFC, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.0",
.parent = &clk_dout_mmc0.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 0),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.1",
.parent = &clk_dout_mmc1.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 4),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.2",
.parent = &clk_dout_mmc2.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 8),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.3",
.parent = &clk_dout_mmc3.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 12),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
}, {
.clk = {
.name = "sclk_dwmmc",
......@@ -1237,6 +1165,98 @@ 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 },
};
static struct clksrc_clk clk_sclk_mmc0 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.0",
.parent = &clk_dout_mmc0.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 0),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
};
static struct clksrc_clk clk_sclk_mmc1 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.1",
.parent = &clk_dout_mmc1.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 4),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
};
static struct clksrc_clk clk_sclk_mmc2 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.2",
.parent = &clk_dout_mmc2.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 8),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
};
static struct clksrc_clk clk_sclk_mmc3 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.3",
.parent = &clk_dout_mmc3.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 12),
},
.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
};
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
......@@ -1271,6 +1291,35 @@ 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,
&clk_sclk_mmc0,
&clk_sclk_mmc1,
&clk_sclk_mmc2,
&clk_sclk_mmc3,
};
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("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.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 +1527,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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -72,7 +72,6 @@
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
addne \irqnr, \irqnr, #32
.endm
......
......@@ -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 */
......@@ -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);
}
/*
* 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
/* linux/arch/arm/mach-exynos4/setup-sdhci.c
*
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* EXYNOS4 - Helper functions for settign up SDHCI device(s) (HSMMC)
*
* 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/types.h>
/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
char *exynos4_hsmmc_clksrcs[4] = {
[0] = NULL,
[1] = NULL,
[2] = "sclk_mmc", /* mmc_bus */
[3] = NULL,
};
......@@ -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),
}
};
......
......@@ -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),
}
};
......
......@@ -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 = {
......
......@@ -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;
}
......@@ -15,7 +15,6 @@ obj-$(CONFIG_S3C2416_PM) += pm.o
#obj-$(CONFIG_S3C2416_DMA) += dma.o
# Device setup
obj-$(CONFIG_S3C2416_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S3C2416_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
# Machine support
......
......@@ -90,39 +90,38 @@ static struct clksrc_clk hsmmc_div[] = {
},
};
static struct clksrc_clk hsmmc_mux[] = {
[0] = {
.clk = {
.name = "hsmmc-if",
.devname = "s3c-sdhci.0",
.ctrlbit = (1 << 6),
.enable = s3c2443_clkcon_enable_s,
},
.sources = &(struct clksrc_sources) {
.nr_sources = 2,
.sources = (struct clk *[]) {
[0] = &hsmmc_div[0].clk,
[1] = NULL, /* to fix */
},
},
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 },
static struct clksrc_clk hsmmc_mux0 = {
.clk = {
.name = "hsmmc-if",
.devname = "s3c-sdhci.0",
.ctrlbit = (1 << 6),
.enable = s3c2443_clkcon_enable_s,
},
[1] = {
.clk = {
.name = "hsmmc-if",
.devname = "s3c-sdhci.1",
.ctrlbit = (1 << 12),
.enable = s3c2443_clkcon_enable_s,
.sources = &(struct clksrc_sources) {
.nr_sources = 2,
.sources = (struct clk * []) {
[0] = &hsmmc_div[0].clk,
[1] = NULL, /* to fix */
},
.sources = &(struct clksrc_sources) {
.nr_sources = 2,
.sources = (struct clk *[]) {
[0] = &hsmmc_div[1].clk,
[1] = NULL, /* to fix */
},
},
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 },
};
static struct clksrc_clk hsmmc_mux1 = {
.clk = {
.name = "hsmmc-if",
.devname = "s3c-sdhci.1",
.ctrlbit = (1 << 12),
.enable = s3c2443_clkcon_enable_s,
},
.sources = &(struct clksrc_sources) {
.nr_sources = 2,
.sources = (struct clk * []) {
[0] = &hsmmc_div[1].clk,
[1] = NULL, /* to fix */
},
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 },
},
.reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 },
};
static struct clk hsmmc0_clk = {
......@@ -144,8 +143,14 @@ static struct clksrc_clk *clksrcs[] __initdata = {
&hsspi_mux,
&hsmmc_div[0],
&hsmmc_div[1],
&hsmmc_mux[0],
&hsmmc_mux[1],
&hsmmc_mux0,
&hsmmc_mux1,
};
static struct clk_lookup s3c2416_clk_lookup[] = {
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk),
};
void __init s3c2416_init_clocks(int xtal)
......@@ -167,6 +172,7 @@ void __init s3c2416_init_clocks(int xtal)
s3c_register_clksrc(clksrcs[ptr], 1);
s3c24xx_register_clock(&hsmmc0_clk);
clkdev_add_table(s3c2416_clk_lookup, ARRAY_SIZE(s3c2416_clk_lookup));
s3c_pwmclk_init();
......
/* linux/arch/arm/mach-s3c2416/setup-sdhci.c
*
* Copyright 2010 Promwad Innovation Company
* Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com>
*
* S3C2416 - Helper functions for settign up SDHCI device(s) (HSMMC)
*
* Based on mach-s3c64xx/setup-sdhci.c
*
* 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/types.h>
/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
char *s3c2416_hsmmc_clksrcs[4] = {
[0] = "hsmmc",
[1] = "hsmmc",
[2] = "hsmmc-if",
/* [3] = "48m", - note not successfully used yet */
};
......@@ -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);
......
......@@ -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,
},
};
......
......@@ -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,
},
};
......
......@@ -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,
}
};
......
......@@ -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,
},
};
......
......@@ -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,
}
};
......
......@@ -77,6 +77,11 @@ config S3C64XX_SETUP_SDHCI_GPIO
help
Common setup code for S3C64XX SDHCI GPIO configurations
config S3C64XX_SETUP_SPI
bool
help
Common setup code for SPI GPIO configurations
# S36400 Macchine support
config MACH_SMDK6400
......@@ -276,6 +281,7 @@ config MACH_WLF_CRAGG_6410
select S3C64XX_SETUP_IDE
select S3C64XX_SETUP_FB_24BPP
select S3C64XX_SETUP_KEYPAD
select S3C64XX_SETUP_SPI
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_KEYPAD
select S3C_DEV_USB_HOST
......@@ -286,7 +292,7 @@ config MACH_WLF_CRAGG_6410
select S3C_DEV_I2C1
select S3C_DEV_WDT
select S3C_DEV_RTC
select S3C64XX_DEV_SPI
select S3C64XX_DEV_SPI0
select S3C24XX_GPIO_EXTRA128
select I2C
help
......
......@@ -32,9 +32,9 @@ obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S3C64XX_SETUP_IDE) += setup-ide.o
obj-$(CONFIG_S3C64XX_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_S3C64XX_SETUP_SPI) += setup-spi.o
# PM
......@@ -60,4 +60,3 @@ obj-$(CONFIG_MACH_WLF_CRAGG_6410) += mach-crag6410.o mach-crag6410-module.o
obj-y += dev-uart.o
obj-y += dev-audio.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
......@@ -183,18 +183,6 @@ static struct clk init_clocks_off[] = {
.parent = &clk_p,
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_SPI1,
}, {
.name = "spi_48m",
.devname = "s3c64xx-spi.0",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
}, {
.name = "spi_48m",
.devname = "s3c64xx-spi.1",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
}, {
.name = "48m",
.devname = "s3c-sdhci.0",
......@@ -226,6 +214,22 @@ static struct clk init_clocks_off[] = {
},
};
static struct clk clk_48m_spi0 = {
.name = "spi_48m",
.devname = "s3c64xx-spi.0",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
};
static struct clk clk_48m_spi1 = {
.name = "spi_48m",
.devname = "s3c64xx-spi.1",
.parent = &clk_48m,
.enable = s3c64xx_sclk_ctrl,
.ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
};
static struct clk init_clocks[] = {
{
.name = "lcd",
......@@ -242,24 +246,6 @@ static struct clk init_clocks[] = {
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_UHOST,
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.2",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
}, {
.name = "otg",
.parent = &clk_h,
......@@ -310,6 +296,29 @@ static struct clk init_clocks[] = {
}
};
static struct clk clk_hsmmc0 = {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
};
static struct clk clk_hsmmc1 = {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
};
static struct clk clk_hsmmc2 = {
.name = "hsmmc",
.devname = "s3c-sdhci.2",
.parent = &clk_h,
.enable = s3c64xx_hclk_ctrl,
.ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
};
static struct clk clk_fout_apll = {
.name = "fout_apll",
......@@ -577,36 +586,6 @@ static struct clksrc_sources clkset_camif = {
static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "mmc_bus",
.devname = "s3c-sdhci.0",
.ctrlbit = S3C_CLKCON_SCLK_MMC0,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4 },
.sources = &clkset_spi_mmc,
}, {
.clk = {
.name = "mmc_bus",
.devname = "s3c-sdhci.1",
.ctrlbit = S3C_CLKCON_SCLK_MMC1,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4 },
.sources = &clkset_spi_mmc,
}, {
.clk = {
.name = "mmc_bus",
.devname = "s3c-sdhci.2",
.ctrlbit = S3C_CLKCON_SCLK_MMC2,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4 },
.sources = &clkset_spi_mmc,
}, {
.clk = {
.name = "usb-bus-host",
.ctrlbit = S3C_CLKCON_SCLK_UHOST,
......@@ -615,35 +594,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_src = { .reg = S3C_CLK_SRC, .shift = 5, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 20, .size = 4 },
.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,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
.sources = &clkset_spi_mmc,
}, {
.clk = {
.name = "spi-bus",
.devname = "s3c64xx-spi.1",
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
.sources = &clkset_spi_mmc,
}, {
.clk = {
.name = "audio-bus",
......@@ -695,6 +645,78 @@ 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,
};
static struct clksrc_clk clk_sclk_mmc0 = {
.clk = {
.name = "mmc_bus",
.devname = "s3c-sdhci.0",
.ctrlbit = S3C_CLKCON_SCLK_MMC0,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 18, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 0, .size = 4 },
.sources = &clkset_spi_mmc,
};
static struct clksrc_clk clk_sclk_mmc1 = {
.clk = {
.name = "mmc_bus",
.devname = "s3c-sdhci.1",
.ctrlbit = S3C_CLKCON_SCLK_MMC1,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 20, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 4, .size = 4 },
.sources = &clkset_spi_mmc,
};
static struct clksrc_clk clk_sclk_mmc2 = {
.clk = {
.name = "mmc_bus",
.devname = "s3c-sdhci.2",
.ctrlbit = S3C_CLKCON_SCLK_MMC2,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 22, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV1, .shift = 8, .size = 4 },
.sources = &clkset_spi_mmc,
};
static struct clksrc_clk clk_sclk_spi0 = {
.clk = {
.name = "spi-bus",
.devname = "s3c64xx-spi.0",
.ctrlbit = S3C_CLKCON_SCLK_SPI0,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
.sources = &clkset_spi_mmc,
};
static struct clksrc_clk clk_sclk_spi1 = {
.clk = {
.name = "spi-bus",
.devname = "s3c64xx-spi.1",
.ctrlbit = S3C_CLKCON_SCLK_SPI1,
.enable = s3c64xx_sclk_ctrl,
},
.reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
.sources = &clkset_spi_mmc,
};
/* Clock initialisation code */
static struct clksrc_clk *init_parents[] = {
......@@ -703,6 +725,39 @@ static struct clksrc_clk *init_parents[] = {
&clk_mout_mpll,
};
static struct clksrc_clk *clksrc_cdev[] = {
&clk_sclk_uclk,
&clk_sclk_mmc0,
&clk_sclk_mmc1,
&clk_sclk_mmc2,
&clk_sclk_spi0,
&clk_sclk_spi1,
};
static struct clk *clk_cdev[] = {
&clk_hsmmc0,
&clk_hsmmc1,
&clk_hsmmc2,
&clk_48m_spi0,
&clk_48m_spi1,
};
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),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_48m_spi0),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_48m_spi1),
};
#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
void __init_or_cpufreq s3c6400_setup_clocks(void)
......@@ -811,6 +866,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);
......@@ -821,7 +878,15 @@ void __init s3c64xx_register_clocks(unsigned long xtal,
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
for (cnt = 0; cnt < ARRAY_SIZE(clk_cdev); cnt++)
s3c_disable_clocks(clk_cdev[cnt], 1);
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();
}
/* linux/arch/arm/plat-s3c64xx/dev-spi.c
*
* Copyright (C) 2009 Samsung Electronics Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/spi-clocks.h>
#include <mach/irqs.h>
#include <plat/s3c64xx-spi.h>
#include <plat/gpio-cfg.h>
#include <plat/devs.h>
static char *spi_src_clks[] = {
[S3C64XX_SPI_SRCCLK_PCLK] = "pclk",
[S3C64XX_SPI_SRCCLK_SPIBUS] = "spi-bus",
[S3C64XX_SPI_SRCCLK_48M] = "spi_48m",
};
/* SPI Controller platform_devices */
/* Since we emulate multi-cs capability, we do not touch the GPC-3,7.
* The emulated CS is toggled by board specific mechanism, as it can
* be either some immediate GPIO or some signal out of some other
* chip in between ... or some yet another way.
* We simply do not assume anything about CS.
*/
static int s3c64xx_spi_cfg_gpio(struct platform_device *pdev)
{
unsigned int base;
switch (pdev->id) {
case 0:
base = S3C64XX_GPC(0);
break;
case 1:
base = S3C64XX_GPC(4);
break;
default:
dev_err(&pdev->dev, "Invalid SPI Controller number!");
return -EINVAL;
}
s3c_gpio_cfgall_range(base, 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
static struct resource s3c64xx_spi0_resource[] = {
[0] = {
.start = S3C64XX_PA_SPI0,
.end = S3C64XX_PA_SPI0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI0_TX,
.end = DMACH_SPI0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI0_RX,
.end = DMACH_SPI0_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI0,
.end = IRQ_SPI0,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s3c64xx_spi0_pdata = {
.cfg_gpio = s3c64xx_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.tx_st_done = 21,
};
static u64 spi_dmamask = DMA_BIT_MASK(32);
struct platform_device s3c64xx_device_spi0 = {
.name = "s3c64xx-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s3c64xx_spi0_resource),
.resource = s3c64xx_spi0_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s3c64xx_spi0_pdata,
},
};
EXPORT_SYMBOL(s3c64xx_device_spi0);
static struct resource s3c64xx_spi1_resource[] = {
[0] = {
.start = S3C64XX_PA_SPI1,
.end = S3C64XX_PA_SPI1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI1_TX,
.end = DMACH_SPI1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI1_RX,
.end = DMACH_SPI1_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI1,
.end = IRQ_SPI1,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s3c64xx_spi1_pdata = {
.cfg_gpio = s3c64xx_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.tx_st_done = 21,
};
struct platform_device s3c64xx_device_spi1 = {
.name = "s3c64xx-spi",
.id = 1,
.num_resources = ARRAY_SIZE(s3c64xx_spi1_resource),
.resource = s3c64xx_spi1_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s3c64xx_spi1_pdata,
},
};
EXPORT_SYMBOL(s3c64xx_device_spi1);
void __init s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
{
struct s3c64xx_spi_info *pd;
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0
|| src_clk_nr > S3C64XX_SPI_SRCCLK_48M) {
printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
return;
}
switch (cntrlr) {
case 0:
pd = &s3c64xx_spi0_pdata;
break;
case 1:
pd = &s3c64xx_spi1_pdata;
break;
default:
printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
__func__, cntrlr);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
pd->src_clk_name = spi_src_clks[src_clk_nr];
}
......@@ -115,6 +115,8 @@
#define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG
#define S3C_PA_RTC S3C64XX_PA_RTC
#define S3C_PA_WDT S3C64XX_PA_WATCHDOG
#define S3C_PA_SPI0 S3C64XX_PA_SPI0
#define S3C_PA_SPI1 S3C64XX_PA_SPI1
#define SAMSUNG_PA_ADC S3C64XX_PA_ADC
#define SAMSUNG_PA_CFCON S3C64XX_PA_CFCON
......
/* linux/arch/arm/mach-s3c64xx/setup-sdhci.c
*
* Copyright 2008 Simtec Electronics
* Copyright 2008 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* http://armlinux.simtec.co.uk/
*
* S3C6400/S3C6410 - Helper functions for settign up SDHCI device(s) (HSMMC)
*
* 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/types.h>
/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
char *s3c64xx_hsmmc_clksrcs[4] = {
[0] = "hsmmc",
[1] = "hsmmc",
[2] = "mmc_bus",
/* [3] = "48m", - note not successfully used yet */
};
/* linux/arch/arm/mach-s3c64xx/setup-spi.c
*
* Copyright (C) 2011 Samsung Electronics Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <plat/gpio-cfg.h>
#include <plat/s3c64xx-spi.h>
#ifdef CONFIG_S3C64XX_DEV_SPI0
struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.tx_st_done = 21,
};
int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI1
struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.tx_st_done = 21,
};
int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
......@@ -36,6 +36,11 @@ config S5P64X0_SETUP_I2C1
help
Common setup code for i2c bus 1.
config S5P64X0_SETUP_SPI
bool
help
Common setup code for SPI GPIO configurations
# machine support
config MACH_SMDK6440
......@@ -45,7 +50,6 @@ config MACH_SMDK6440
select S3C_DEV_I2C1
select S3C_DEV_RTC
select S3C_DEV_WDT
select S3C64XX_DEV_SPI
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
......@@ -62,7 +66,6 @@ config MACH_SMDK6450
select S3C_DEV_I2C1
select S3C_DEV_RTC
select S3C_DEV_WDT
select S3C64XX_DEV_SPI
select SAMSUNG_DEV_ADC
select SAMSUNG_DEV_BACKLIGHT
select SAMSUNG_DEV_PWM
......
......@@ -26,7 +26,7 @@ obj-$(CONFIG_MACH_SMDK6450) += mach-smdk6450.o
# device support
obj-y += dev-audio.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
obj-$(CONFIG_S5P64X0_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5P64X0_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5P64X0_SETUP_SPI) += setup-spi.o
......@@ -267,18 +267,6 @@ static struct clk init_clocks_off[] = {
.parent = &clk_pclk.clk,
.enable = s5p64x0_pclk_ctrl,
.ctrlbit = (1 << 31),
}, {
.name = "sclk_spi_48",
.devname = "s3c64xx-spi.0",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 22),
}, {
.name = "sclk_spi_48",
.devname = "s3c64xx-spi.1",
.parent = &clk_48m,
.enable = s5p64x0_sclk_ctrl,
.ctrlbit = (1 << 23),
}, {
.name = "mmc_48m",
.devname = "s3c-sdhci.0",
......@@ -419,35 +407,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_group1,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
.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),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 21),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_post",
......@@ -487,6 +446,41 @@ 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 clk_sclk_spi0 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 20),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi1 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 21),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group1,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
};
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
......@@ -505,6 +499,20 @@ static struct clk dummy_apb_pclk = {
.id = -1,
};
static struct clksrc_clk *clksrc_cdev[] = {
&clk_sclk_uclk,
&clk_sclk_spi0,
&clk_sclk_spi1,
};
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),
CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
};
void __init_or_cpufreq s5p6440_setup_clocks(void)
{
struct clk *xtal_clk;
......@@ -583,9 +591,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);
......
......@@ -441,35 +441,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_group2,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 },
.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),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 21),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_fimc",
......@@ -536,6 +507,55 @@ 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 clk_sclk_spi0 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 20),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi1 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 21),
.enable = s5p64x0_sclk_ctrl,
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
};
static struct clksrc_clk *clksrc_cdev[] = {
&clk_sclk_uclk,
&clk_sclk_spi0,
&clk_sclk_spi1,
};
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),
CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
};
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
......@@ -634,9 +654,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);
......
/* linux/arch/arm/mach-s5p64x0/dev-spi.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/regs-clock.h>
#include <mach/spi-clocks.h>
#include <plat/cpu.h>
#include <plat/s3c64xx-spi.h>
#include <plat/gpio-cfg.h>
static char *s5p64x0_spi_src_clks[] = {
[S5P64X0_SPI_SRCCLK_PCLK] = "pclk",
[S5P64X0_SPI_SRCCLK_SCLK] = "sclk_spi",
};
/* SPI Controller platform_devices */
/* Since we emulate multi-cs capability, we do not touch the CS.
* The emulated CS is toggled by board specific mechanism, as it can
* be either some immediate GPIO or some signal out of some other
* chip in between ... or some yet another way.
* We simply do not assume anything about CS.
*/
static int s5p6440_spi_cfg_gpio(struct platform_device *pdev)
{
unsigned int base;
switch (pdev->id) {
case 0:
base = S5P6440_GPC(0);
break;
case 1:
base = S5P6440_GPC(4);
break;
default:
dev_err(&pdev->dev, "Invalid SPI Controller number!");
return -EINVAL;
}
s3c_gpio_cfgall_range(base, 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
static int s5p6450_spi_cfg_gpio(struct platform_device *pdev)
{
unsigned int base;
switch (pdev->id) {
case 0:
base = S5P6450_GPC(0);
break;
case 1:
base = S5P6450_GPC(4);
break;
default:
dev_err(&pdev->dev, "Invalid SPI Controller number!");
return -EINVAL;
}
s3c_gpio_cfgall_range(base, 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
static struct resource s5p64x0_spi0_resource[] = {
[0] = {
.start = S5P64X0_PA_SPI0,
.end = S5P64X0_PA_SPI0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI0_TX,
.end = DMACH_SPI0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI0_RX,
.end = DMACH_SPI0_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI0,
.end = IRQ_SPI0,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5p6440_spi0_pdata = {
.cfg_gpio = s5p6440_spi_cfg_gpio,
.fifo_lvl_mask = 0x1ff,
.rx_lvl_offset = 15,
.tx_st_done = 25,
};
static struct s3c64xx_spi_info s5p6450_spi0_pdata = {
.cfg_gpio = s5p6450_spi_cfg_gpio,
.fifo_lvl_mask = 0x1ff,
.rx_lvl_offset = 15,
.tx_st_done = 25,
};
static u64 spi_dmamask = DMA_BIT_MASK(32);
struct platform_device s5p64x0_device_spi0 = {
.name = "s3c64xx-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s5p64x0_spi0_resource),
.resource = s5p64x0_spi0_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
static struct resource s5p64x0_spi1_resource[] = {
[0] = {
.start = S5P64X0_PA_SPI1,
.end = S5P64X0_PA_SPI1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI1_TX,
.end = DMACH_SPI1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI1_RX,
.end = DMACH_SPI1_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI1,
.end = IRQ_SPI1,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5p6440_spi1_pdata = {
.cfg_gpio = s5p6440_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 15,
.tx_st_done = 25,
};
static struct s3c64xx_spi_info s5p6450_spi1_pdata = {
.cfg_gpio = s5p6450_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 15,
.tx_st_done = 25,
};
struct platform_device s5p64x0_device_spi1 = {
.name = "s3c64xx-spi",
.id = 1,
.num_resources = ARRAY_SIZE(s5p64x0_spi1_resource),
.resource = s5p64x0_spi1_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
void __init s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
{
struct s3c64xx_spi_info *pd;
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0
|| src_clk_nr > S5P64X0_SPI_SRCCLK_SCLK) {
printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
return;
}
switch (cntrlr) {
case 0:
if (soc_is_s5p6450())
pd = &s5p6450_spi0_pdata;
else
pd = &s5p6440_spi0_pdata;
s5p64x0_device_spi0.dev.platform_data = pd;
break;
case 1:
if (soc_is_s5p6450())
pd = &s5p6450_spi1_pdata;
else
pd = &s5p6440_spi1_pdata;
s5p64x0_device_spi1.dev.platform_data = pd;
break;
default:
printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
__func__, cntrlr);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
pd->src_clk_name = s5p64x0_spi_src_clks[src_clk_nr];
}
......@@ -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);
......
......@@ -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)
......
......@@ -67,6 +67,8 @@
#define S3C_PA_RTC S5P64X0_PA_RTC
#define S3C_PA_WDT S5P64X0_PA_WDT
#define S3C_PA_FB S5P64X0_PA_FB
#define S3C_PA_SPI0 S5P64X0_PA_SPI0
#define S3C_PA_SPI1 S5P64X0_PA_SPI1
#define S5P_PA_CHIPID S5P64X0_PA_CHIPID
#define S5P_PA_SROMC S5P64X0_PA_SROMC
......
......@@ -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);
}
/* linux/arch/arm/mach-s5p64x0/setup-spi.c
*
* Copyright (C) 2011 Samsung Electronics Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <plat/gpio-cfg.h>
#include <plat/cpu.h>
#include <plat/s3c64xx-spi.h>
#ifdef CONFIG_S3C64XX_DEV_SPI0
struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
.fifo_lvl_mask = 0x1ff,
.rx_lvl_offset = 15,
.tx_st_done = 25,
};
int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
{
if (soc_is_s5p6450())
s3c_gpio_cfgall_range(S5P6450_GPC(0), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
else
s3c_gpio_cfgall_range(S5P6440_GPC(0), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI1
struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 15,
.tx_st_done = 25,
};
int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
{
if (soc_is_s5p6450())
s3c_gpio_cfgall_range(S5P6450_GPC(4), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
else
s3c_gpio_cfgall_range(S5P6440_GPC(4), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
......@@ -45,6 +45,11 @@ config S5PC100_SETUP_SDHCI_GPIO
help
Common setup code for SDHCI gpio.
config S5PC100_SETUP_SPI
bool
help
Common setup code for SPI GPIO configurations.
config MACH_SMDKC100
bool "SMDKC100"
select CPU_S5PC100
......
......@@ -21,12 +21,11 @@ obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PC100_SETUP_IDE) += setup-ide.o
obj-$(CONFIG_S5PC100_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_S5PC100_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_S5PC100_SETUP_SPI) += setup-spi.o
# device support
obj-y += dev-audio.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
# machine support
......
......@@ -425,24 +425,6 @@ static struct clk init_clocks_off[] = {
.parent = &clk_div_d0_bus.clk,
.enable = s5pc100_d0_2_ctrl,
.ctrlbit = (1 << 1),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.2",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "modemif",
.parent = &clk_div_d1_bus.clk,
......@@ -672,24 +654,6 @@ static struct clk init_clocks_off[] = {
.parent = &clk_div_pclkd1.clk,
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "spi_48m",
.devname = "s3c64xx-spi.0",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "spi_48m",
.devname = "s3c64xx-spi.1",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 8),
}, {
.name = "spi_48m",
.devname = "s3c64xx-spi.2",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 9),
}, {
.name = "mmc_48m",
.devname = "s3c-sdhci.0",
......@@ -711,6 +675,54 @@ static struct clk init_clocks_off[] = {
},
};
static struct clk clk_hsmmc2 = {
.name = "hsmmc",
.devname = "s3c-sdhci.2",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 7),
};
static struct clk clk_hsmmc1 = {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 6),
};
static struct clk clk_hsmmc0 = {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_div_d1_bus.clk,
.enable = s5pc100_d1_0_ctrl,
.ctrlbit = (1 << 5),
};
static struct clk clk_48m_spi0 = {
.name = "spi_48m",
.devname = "s3c64xx-spi.0",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 7),
};
static struct clk clk_48m_spi1 = {
.name = "spi_48m",
.devname = "s3c64xx-spi.1",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 8),
};
static struct clk clk_48m_spi2 = {
.name = "spi_48m",
.devname = "s3c64xx-spi.2",
.parent = &clk_mout_48m.clk,
.enable = s5pc100_sclk0_ctrl,
.ctrlbit = (1 << 9),
};
static struct clk clk_vclk54m = {
.name = "vclk_54m",
.rate = 54000000,
......@@ -928,49 +940,6 @@ static struct clksrc_clk clk_sclk_spdif = {
static struct clksrc_clk clksrcs[] = {
{
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 4),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 5),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.2",
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
.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),
......@@ -1022,39 +991,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clk_src_group7,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 24, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 24, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.0",
.ctrlbit = (1 << 12),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc0,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.1",
.ctrlbit = (1 << 13),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.2",
.ctrlbit = (1 << 14),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_irda",
......@@ -1098,6 +1034,89 @@ 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 },
};
static struct clksrc_clk clk_sclk_mmc0 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.0",
.ctrlbit = (1 << 12),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc0,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
};
static struct clksrc_clk clk_sclk_mmc1 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.1",
.ctrlbit = (1 << 13),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
};
static struct clksrc_clk clk_sclk_mmc2 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.2",
.ctrlbit = (1 << 14),
.enable = s5pc100_sclk1_ctrl,
},
.sources = &clk_src_mmc12,
.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi0 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.ctrlbit = (1 << 4),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi1 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.ctrlbit = (1 << 5),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi2 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.2",
.ctrlbit = (1 << 6),
.enable = s5pc100_sclk0_ctrl,
},
.sources = &clk_src_group1,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
.reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
};
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
......@@ -1127,6 +1146,25 @@ static struct clksrc_clk *sysclks[] = {
&clk_sclk_spdif,
};
static struct clk *clk_cdev[] = {
&clk_hsmmc0,
&clk_hsmmc1,
&clk_hsmmc2,
&clk_48m_spi0,
&clk_48m_spi1,
&clk_48m_spi2,
};
static struct clksrc_clk *clksrc_cdev[] = {
&clk_sclk_uart,
&clk_sclk_mmc0,
&clk_sclk_mmc1,
&clk_sclk_mmc2,
&clk_sclk_spi0,
&clk_sclk_spi1,
&clk_sclk_spi2,
};
void __init_or_cpufreq s5pc100_setup_clocks(void)
{
unsigned long xtal;
......@@ -1266,6 +1304,24 @@ 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),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_48m_spi0),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_48m_spi1),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk1", &clk_48m_spi2),
CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
};
void __init s5pc100_register_clocks(void)
{
int ptr;
......@@ -1277,9 +1333,16 @@ 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_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
s3c_disable_clocks(clk_cdev[ptr], 1);
s3c24xx_register_clock(&dummy_apb_pclk);
......
/* linux/arch/arm/mach-s5pc100/dev-spi.c
*
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/spi-clocks.h>
#include <mach/irqs.h>
#include <plat/s3c64xx-spi.h>
#include <plat/gpio-cfg.h>
#include <plat/irqs.h>
static char *spi_src_clks[] = {
[S5PC100_SPI_SRCCLK_PCLK] = "pclk",
[S5PC100_SPI_SRCCLK_48M] = "spi_48m",
[S5PC100_SPI_SRCCLK_SPIBUS] = "spi_bus",
};
/* SPI Controller platform_devices */
/* Since we emulate multi-cs capability, we do not touch the CS.
* The emulated CS is toggled by board specific mechanism, as it can
* be either some immediate GPIO or some signal out of some other
* chip in between ... or some yet another way.
* We simply do not assume anything about CS.
*/
static int s5pc100_spi_cfg_gpio(struct platform_device *pdev)
{
switch (pdev->id) {
case 0:
s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
break;
case 1:
s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
break;
case 2:
s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
s3c_gpio_cfgall_range(S5PC100_GPB(2), 2,
S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
break;
default:
dev_err(&pdev->dev, "Invalid SPI Controller number!");
return -EINVAL;
}
return 0;
}
static struct resource s5pc100_spi0_resource[] = {
[0] = {
.start = S5PC100_PA_SPI0,
.end = S5PC100_PA_SPI0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI0_TX,
.end = DMACH_SPI0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI0_RX,
.end = DMACH_SPI0_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI0,
.end = IRQ_SPI0,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5pc100_spi0_pdata = {
.cfg_gpio = s5pc100_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.high_speed = 1,
.tx_st_done = 21,
};
static u64 spi_dmamask = DMA_BIT_MASK(32);
struct platform_device s5pc100_device_spi0 = {
.name = "s3c64xx-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s5pc100_spi0_resource),
.resource = s5pc100_spi0_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pc100_spi0_pdata,
},
};
static struct resource s5pc100_spi1_resource[] = {
[0] = {
.start = S5PC100_PA_SPI1,
.end = S5PC100_PA_SPI1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI1_TX,
.end = DMACH_SPI1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI1_RX,
.end = DMACH_SPI1_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI1,
.end = IRQ_SPI1,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5pc100_spi1_pdata = {
.cfg_gpio = s5pc100_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.high_speed = 1,
.tx_st_done = 21,
};
struct platform_device s5pc100_device_spi1 = {
.name = "s3c64xx-spi",
.id = 1,
.num_resources = ARRAY_SIZE(s5pc100_spi1_resource),
.resource = s5pc100_spi1_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pc100_spi1_pdata,
},
};
static struct resource s5pc100_spi2_resource[] = {
[0] = {
.start = S5PC100_PA_SPI2,
.end = S5PC100_PA_SPI2 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI2_TX,
.end = DMACH_SPI2_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI2_RX,
.end = DMACH_SPI2_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI2,
.end = IRQ_SPI2,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5pc100_spi2_pdata = {
.cfg_gpio = s5pc100_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.high_speed = 1,
.tx_st_done = 21,
};
struct platform_device s5pc100_device_spi2 = {
.name = "s3c64xx-spi",
.id = 2,
.num_resources = ARRAY_SIZE(s5pc100_spi2_resource),
.resource = s5pc100_spi2_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pc100_spi2_pdata,
},
};
void __init s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
{
struct s3c64xx_spi_info *pd;
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0
|| src_clk_nr > S5PC100_SPI_SRCCLK_SPIBUS) {
printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
return;
}
switch (cntrlr) {
case 0:
pd = &s5pc100_spi0_pdata;
break;
case 1:
pd = &s5pc100_spi1_pdata;
break;
case 2:
pd = &s5pc100_spi2_pdata;
break;
default:
printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
__func__, cntrlr);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
pd->src_clk_name = spi_src_clks[src_clk_nr];
}
......@@ -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;
......
......@@ -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)
......
......@@ -100,6 +100,9 @@
#define S3C_PA_USB_HSOTG S5PC100_PA_USB_HSOTG
#define S3C_PA_USB_HSPHY S5PC100_PA_USB_HSPHY
#define S3C_PA_WDT S5PC100_PA_WATCHDOG
#define S3C_PA_SPI0 S5PC100_PA_SPI0
#define S3C_PA_SPI1 S5PC100_PA_SPI1
#define S3C_PA_SPI2 S5PC100_PA_SPI2
#define S5P_PA_CHIPID S5PC100_PA_CHIPID
#define S5P_PA_FIMC0 S5PC100_PA_FIMC0
......
/* linux/arch/arm/mach-s5pc100/setup-sdhci.c
*
* Copyright 2008 Samsung Electronics
*
* S5PC100 - Helper functions for settign up SDHCI device(s) (HSMMC)
*
* Based on mach-s3c6410/setup-sdhci.c
*
* 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/types.h>
/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
char *s5pc100_hsmmc_clksrcs[4] = {
[0] = "hsmmc", /* HCLK */
/* [1] = "hsmmc", - duplicate HCLK entry */
[2] = "sclk_mmc", /* mmc_bus */
/* [3] = "48m", - note not successfully used yet */
};
/* linux/arch/arm/mach-s5pc100/setup-spi.c
*
* Copyright (C) 2011 Samsung Electronics Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <plat/gpio-cfg.h>
#include <plat/s3c64xx-spi.h>
#ifdef CONFIG_S3C64XX_DEV_SPI0
struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.high_speed = 1,
.tx_st_done = 21,
};
int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI1
struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.high_speed = 1,
.tx_st_done = 21,
};
int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI2
struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 13,
.high_speed = 1,
.tx_st_done = 21,
};
int s3c64xx_spi2_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
s3c_gpio_cfgall_range(S5PC100_GPB(2), 2,
S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
return 0;
}
#endif
......@@ -60,6 +60,11 @@ config S5PV210_SETUP_FIMC
help
Common setup code for the camera interfaces.
config S5PV210_SETUP_SPI
bool
help
Common setup code for SPI GPIO configurations.
menu "S5PC110 Machines"
config MACH_AQUILA
......
......@@ -27,7 +27,6 @@ obj-$(CONFIG_MACH_TORBRECK) += mach-torbreck.o
# device support
obj-y += dev-audio.o
obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PV210_SETUP_FIMC) += setup-fimc.o
......@@ -35,5 +34,5 @@ obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o
obj-$(CONFIG_S5PV210_SETUP_IDE) += setup-ide.o
obj-$(CONFIG_S5PV210_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_S5PV210_SETUP_SPI) += setup-spi.o
......@@ -398,30 +398,6 @@ static struct clk init_clocks_off[] = {
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1<<25),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<16),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<17),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.2",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<18),
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.3",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<19),
}, {
.name = "systimer",
.parent = &clk_pclk_psys.clk,
......@@ -559,6 +535,38 @@ static struct clk init_clocks[] = {
},
};
static struct clk clk_hsmmc0 = {
.name = "hsmmc",
.devname = "s3c-sdhci.0",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<16),
};
static struct clk clk_hsmmc1 = {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<17),
};
static struct clk clk_hsmmc2 = {
.name = "hsmmc",
.devname = "s3c-sdhci.2",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<18),
};
static struct clk clk_hsmmc3 = {
.name = "hsmmc",
.devname = "s3c-sdhci.3",
.parent = &clk_hclk_psys.clk,
.enable = s5pv210_clk_ip2_ctrl,
.ctrlbit = (1<<19),
};
static struct clk *clkset_uart_list[] = {
[6] = &clk_mout_mpll.clk,
[7] = &clk_mout_epll.clk,
......@@ -807,46 +815,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_sclk_onenand,
.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
.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",
......@@ -904,46 +872,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 8),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 9),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.2",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 10),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
}, {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.3",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 11),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
}, {
.clk = {
.name = "sclk_mfc",
......@@ -981,26 +909,6 @@ static struct clksrc_clk clksrcs[] = {
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 16),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
}, {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 17),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
}, {
.clk = {
.name = "sclk_pwi",
......@@ -1022,6 +930,147 @@ 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 clk_sclk_mmc0 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 8),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
};
static struct clksrc_clk clk_sclk_mmc1 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 9),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
};
static struct clksrc_clk clk_sclk_mmc2 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.2",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 10),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
};
static struct clksrc_clk clk_sclk_mmc3 = {
.clk = {
.name = "sclk_mmc",
.devname = "s3c-sdhci.3",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 11),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi0 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.0",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 16),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
};
static struct clksrc_clk clk_sclk_spi1 = {
.clk = {
.name = "sclk_spi",
.devname = "s3c64xx-spi.1",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 17),
},
.sources = &clkset_group2,
.reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
.reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
};
static struct clksrc_clk *clksrc_cdev[] = {
&clk_sclk_uart0,
&clk_sclk_uart1,
&clk_sclk_uart2,
&clk_sclk_uart3,
&clk_sclk_mmc0,
&clk_sclk_mmc1,
&clk_sclk_mmc2,
&clk_sclk_mmc3,
&clk_sclk_spi0,
&clk_sclk_spi1,
};
static struct clk *clk_cdev[] = {
&clk_hsmmc0,
&clk_hsmmc1,
&clk_hsmmc2,
&clk_hsmmc3,
};
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
......@@ -1261,6 +1310,25 @@ 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),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &clk_hsmmc0),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &clk_hsmmc1),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.0", &clk_hsmmc2),
CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.0", &clk_hsmmc3),
CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
};
void __init s5pv210_register_clocks(void)
{
int ptr;
......@@ -1273,11 +1341,19 @@ 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_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
s3c_disable_clocks(clk_cdev[ptr], 1);
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
......
/* linux/arch/arm/mach-s5pv210/dev-spi.c
*
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
* Jaswinder Singh <jassi.brar@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <mach/dma.h>
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/spi-clocks.h>
#include <plat/s3c64xx-spi.h>
#include <plat/gpio-cfg.h>
static char *spi_src_clks[] = {
[S5PV210_SPI_SRCCLK_PCLK] = "pclk",
[S5PV210_SPI_SRCCLK_SCLK] = "sclk_spi",
};
/* SPI Controller platform_devices */
/* Since we emulate multi-cs capability, we do not touch the CS.
* The emulated CS is toggled by board specific mechanism, as it can
* be either some immediate GPIO or some signal out of some other
* chip in between ... or some yet another way.
* We simply do not assume anything about CS.
*/
static int s5pv210_spi_cfg_gpio(struct platform_device *pdev)
{
unsigned int base;
switch (pdev->id) {
case 0:
base = S5PV210_GPB(0);
break;
case 1:
base = S5PV210_GPB(4);
break;
default:
dev_err(&pdev->dev, "Invalid SPI Controller number!");
return -EINVAL;
}
s3c_gpio_cfgall_range(base, 3,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
static struct resource s5pv210_spi0_resource[] = {
[0] = {
.start = S5PV210_PA_SPI0,
.end = S5PV210_PA_SPI0 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI0_TX,
.end = DMACH_SPI0_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI0_RX,
.end = DMACH_SPI0_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI0,
.end = IRQ_SPI0,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5pv210_spi0_pdata = {
.cfg_gpio = s5pv210_spi_cfg_gpio,
.fifo_lvl_mask = 0x1ff,
.rx_lvl_offset = 15,
.high_speed = 1,
.tx_st_done = 25,
};
static u64 spi_dmamask = DMA_BIT_MASK(32);
struct platform_device s5pv210_device_spi0 = {
.name = "s3c64xx-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s5pv210_spi0_resource),
.resource = s5pv210_spi0_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pv210_spi0_pdata,
},
};
static struct resource s5pv210_spi1_resource[] = {
[0] = {
.start = S5PV210_PA_SPI1,
.end = S5PV210_PA_SPI1 + 0x100 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DMACH_SPI1_TX,
.end = DMACH_SPI1_TX,
.flags = IORESOURCE_DMA,
},
[2] = {
.start = DMACH_SPI1_RX,
.end = DMACH_SPI1_RX,
.flags = IORESOURCE_DMA,
},
[3] = {
.start = IRQ_SPI1,
.end = IRQ_SPI1,
.flags = IORESOURCE_IRQ,
},
};
static struct s3c64xx_spi_info s5pv210_spi1_pdata = {
.cfg_gpio = s5pv210_spi_cfg_gpio,
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 15,
.high_speed = 1,
.tx_st_done = 25,
};
struct platform_device s5pv210_device_spi1 = {
.name = "s3c64xx-spi",
.id = 1,
.num_resources = ARRAY_SIZE(s5pv210_spi1_resource),
.resource = s5pv210_spi1_resource,
.dev = {
.dma_mask = &spi_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &s5pv210_spi1_pdata,
},
};
void __init s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
{
struct s3c64xx_spi_info *pd;
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0
|| src_clk_nr > S5PV210_SPI_SRCCLK_SCLK) {
printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
return;
}
switch (cntrlr) {
case 0:
pd = &s5pv210_spi0_pdata;
break;
case 1:
pd = &s5pv210_spi1_pdata;
break;
default:
printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
__func__, cntrlr);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
pd->src_clk_name = spi_src_clks[src_clk_nr];
}
......@@ -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;
......
......@@ -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)
......
......@@ -109,6 +109,8 @@
#define S3C_PA_RTC S5PV210_PA_RTC
#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG
#define S3C_PA_WDT S5PV210_PA_WATCHDOG
#define S3C_PA_SPI0 S5PV210_PA_SPI0
#define S3C_PA_SPI1 S5PV210_PA_SPI1
#define S5P_PA_CHIPID S5PV210_PA_CHIPID
#define S5P_PA_FIMC0 S5PV210_PA_FIMC0
......
......@@ -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);
}
/* linux/arch/arm/mach-s5pv210/setup-sdhci.c
*
* Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S5PV210 - Helper functions for settign up SDHCI device(s) (HSMMC)
*
* 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/types.h>
/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
char *s5pv210_hsmmc_clksrcs[4] = {
[0] = "hsmmc", /* HCLK */
/* [1] = "hsmmc", - duplicate HCLK entry */
[2] = "sclk_mmc", /* mmc_bus */
/* [3] = NULL, - reserved */
};
/* linux/arch/arm/mach-s5pv210/setup-spi.c
*
* Copyright (C) 2011 Samsung Electronics Ltd.
* http://www.samsung.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <plat/gpio-cfg.h>
#include <plat/s3c64xx-spi.h>
#ifdef CONFIG_S3C64XX_DEV_SPI0
struct s3c64xx_spi_info s3c64xx_spi0_pdata = {
.fifo_lvl_mask = 0x1ff,
.rx_lvl_offset = 15,
.high_speed = 1,
.tx_st_done = 25,
};
int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
s3c_gpio_cfgall_range(S5PV210_GPB(2), 2,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
#ifdef CONFIG_S3C64XX_DEV_SPI1
struct s3c64xx_spi_info s3c64xx_spi1_pdata = {
.fifo_lvl_mask = 0x7f,
.rx_lvl_offset = 15,
.high_speed = 1,
.tx_st_done = 25,
};
int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
{
s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2));
s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
s3c_gpio_cfgall_range(S5PV210_GPB(6), 2,
S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
return 0;
}
#endif
......@@ -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",
};
......@@ -424,12 +426,6 @@ static struct clk init_clocks[] = {
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_DMA5,
}, {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_HSMMC,
}, {
.name = "gpio",
.parent = &clk_p,
......@@ -512,6 +508,14 @@ static struct clk init_clocks[] = {
}
};
static struct clk hsmmc1_clk = {
.name = "hsmmc",
.devname = "s3c-sdhci.1",
.parent = &clk_h,
.enable = s3c2443_clkcon_enable_h,
.ctrlbit = S3C2443_HCLKCON_HSMMC,
};
static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0)
{
clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK;
......@@ -577,6 +581,7 @@ static struct clk *clks[] __initdata = {
&clk_epll,
&clk_usb_bus,
&clk_armdiv,
&hsmmc1_clk,
};
static struct clksrc_clk *clksrcs[] __initdata = {
......@@ -589,6 +594,13 @@ 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),
CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk),
};
void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
unsigned int *divs, int nr_divs,
int divmask)
......@@ -618,6 +630,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);
}
......@@ -226,11 +226,23 @@ config SAMSUNG_DEV_IDE
help
Compile in platform device definitions for IDE
config S3C64XX_DEV_SPI
config S3C64XX_DEV_SPI0
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controllers.
SPI controller 0
config S3C64XX_DEV_SPI1
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controller 1
config S3C64XX_DEV_SPI2
bool
help
Compile in platform device definitions for S3C64XX's type
SPI controller 2
config SAMSUNG_DEV_TS
bool
......
......@@ -61,6 +61,7 @@
#include <plat/regs-iic.h>
#include <plat/regs-serial.h>
#include <plat/regs-spi.h>
#include <plat/s3c64xx-spi.h>
static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
......@@ -1461,3 +1462,129 @@ struct platform_device s3c_device_wdt = {
.resource = s3c_wdt_resource,
};
#endif /* CONFIG_S3C_DEV_WDT */
#ifdef CONFIG_S3C64XX_DEV_SPI0
static struct resource s3c64xx_spi0_resource[] = {
[0] = DEFINE_RES_MEM(S3C_PA_SPI0, SZ_256),
[1] = DEFINE_RES_DMA(DMACH_SPI0_TX),
[2] = DEFINE_RES_DMA(DMACH_SPI0_RX),
[3] = DEFINE_RES_IRQ(IRQ_SPI0),
};
struct platform_device s3c64xx_device_spi0 = {
.name = "s3c64xx-spi",
.id = 0,
.num_resources = ARRAY_SIZE(s3c64xx_spi0_resource),
.resource = s3c64xx_spi0_resource,
.dev = {
.dma_mask = &samsung_device_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
int src_clk_nr, int num_cs)
{
if (!pd) {
pr_err("%s:Need to pass platform data\n", __func__);
return;
}
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0) {
pr_err("%s: Invalid SPI configuration\n", __func__);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
if (!pd->cfg_gpio)
pd->cfg_gpio = s3c64xx_spi0_cfg_gpio;
s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi0);
}
#endif /* CONFIG_S3C64XX_DEV_SPI0 */
#ifdef CONFIG_S3C64XX_DEV_SPI1
static struct resource s3c64xx_spi1_resource[] = {
[0] = DEFINE_RES_MEM(S3C_PA_SPI1, SZ_256),
[1] = DEFINE_RES_DMA(DMACH_SPI1_TX),
[2] = DEFINE_RES_DMA(DMACH_SPI1_RX),
[3] = DEFINE_RES_IRQ(IRQ_SPI1),
};
struct platform_device s3c64xx_device_spi1 = {
.name = "s3c64xx-spi",
.id = 1,
.num_resources = ARRAY_SIZE(s3c64xx_spi1_resource),
.resource = s3c64xx_spi1_resource,
.dev = {
.dma_mask = &samsung_device_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
void __init s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
int src_clk_nr, int num_cs)
{
if (!pd) {
pr_err("%s:Need to pass platform data\n", __func__);
return;
}
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0) {
pr_err("%s: Invalid SPI configuration\n", __func__);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
if (!pd->cfg_gpio)
pd->cfg_gpio = s3c64xx_spi1_cfg_gpio;
s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi1);
}
#endif /* CONFIG_S3C64XX_DEV_SPI1 */
#ifdef CONFIG_S3C64XX_DEV_SPI2
static struct resource s3c64xx_spi2_resource[] = {
[0] = DEFINE_RES_MEM(S3C_PA_SPI2, SZ_256),
[1] = DEFINE_RES_DMA(DMACH_SPI2_TX),
[2] = DEFINE_RES_DMA(DMACH_SPI2_RX),
[3] = DEFINE_RES_IRQ(IRQ_SPI2),
};
struct platform_device s3c64xx_device_spi2 = {
.name = "s3c64xx-spi",
.id = 2,
.num_resources = ARRAY_SIZE(s3c64xx_spi2_resource),
.resource = s3c64xx_spi2_resource,
.dev = {
.dma_mask = &samsung_device_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
int src_clk_nr, int num_cs)
{
if (!pd) {
pr_err("%s:Need to pass platform data\n", __func__);
return;
}
/* Reject invalid configuration */
if (!num_cs || src_clk_nr < 0) {
pr_err("%s: Invalid SPI configuration\n", __func__);
return;
}
pd->num_cs = num_cs;
pd->src_clk_nr = src_clk_nr;
if (!pd->cfg_gpio)
pd->cfg_gpio = s3c64xx_spi2_cfg_gpio;
s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi2);
}
#endif /* CONFIG_S3C64XX_DEV_SPI2 */
......@@ -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));
......
......@@ -39,6 +39,7 @@ extern struct platform_device s3c64xx_device_pcm0;
extern struct platform_device s3c64xx_device_pcm1;
extern struct platform_device s3c64xx_device_spi0;
extern struct platform_device s3c64xx_device_spi1;
extern struct platform_device s3c64xx_device_spi2;
extern struct platform_device s3c_device_adc;
extern struct platform_device s3c_device_cfcon;
......@@ -98,8 +99,6 @@ extern struct platform_device s5p6450_device_iis1;
extern struct platform_device s5p6450_device_iis2;
extern struct platform_device s5p6450_device_pcm0;
extern struct platform_device s5p64x0_device_spi0;
extern struct platform_device s5p64x0_device_spi1;
extern struct platform_device s5pc100_device_ac97;
extern struct platform_device s5pc100_device_iis0;
......@@ -108,9 +107,6 @@ extern struct platform_device s5pc100_device_iis2;
extern struct platform_device s5pc100_device_pcm0;
extern struct platform_device s5pc100_device_pcm1;
extern struct platform_device s5pc100_device_spdif;
extern struct platform_device s5pc100_device_spi0;
extern struct platform_device s5pc100_device_spi1;
extern struct platform_device s5pc100_device_spi2;
extern struct platform_device s5pv210_device_ac97;
extern struct platform_device s5pv210_device_iis0;
......@@ -120,8 +116,6 @@ extern struct platform_device s5pv210_device_pcm0;
extern struct platform_device s5pv210_device_pcm1;
extern struct platform_device s5pv210_device_pcm2;
extern struct platform_device s5pv210_device_spdif;
extern struct platform_device s5pv210_device_spi0;
extern struct platform_device s5pv210_device_spi1;
extern struct platform_device exynos4_device_ac97;
extern struct platform_device exynos4_device_ahci;
......
......@@ -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 {
......
......@@ -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,
......
......@@ -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))
......
......@@ -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
......
......@@ -31,7 +31,6 @@ struct s3c64xx_spi_csinfo {
/**
* struct s3c64xx_spi_info - SPI Controller defining structure
* @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
* @src_clk_name: Platform name of the corresponding clock.
* @clk_from_cmu: If the SPI clock/prescalar control block is present
* by the platform's clock-management-unit and not in SPI controller.
* @num_cs: Number of CS this controller emulates.
......@@ -43,7 +42,6 @@ struct s3c64xx_spi_csinfo {
*/
struct s3c64xx_spi_info {
int src_clk_nr;
char *src_clk_name;
bool clk_from_cmu;
int num_cs;
......@@ -58,18 +56,28 @@ struct s3c64xx_spi_info {
};
/**
* s3c64xx_spi_set_info - SPI Controller configure callback by the board
* s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
* initialization code.
* @cntrlr: SPI controller number the configuration is for.
* @pd: SPI platform data to set.
* @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
* @num_cs: Number of elements in the 'cs' array.
*
* Call this from machine init code for each SPI Controller that
* has some chips attached to it.
*/
extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
int src_clk_nr, int num_cs);
extern void s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
int src_clk_nr, int num_cs);
extern void s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
int src_clk_nr, int num_cs);
/* defined by architecture to configure gpio */
extern int s3c64xx_spi0_cfg_gpio(struct platform_device *dev);
extern int s3c64xx_spi1_cfg_gpio(struct platform_device *dev);
extern int s3c64xx_spi2_cfg_gpio(struct platform_device *dev);
extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
extern struct s3c64xx_spi_info s3c64xx_spi2_pdata;
#endif /* __S3C64XX_PLAT_SPI_H */
......@@ -66,8 +66,6 @@ struct s3c_sdhci_platdata {
enum cd_types cd_type;
enum clk_types clk_type;
char **clocks; /* set of clock sources */
int ext_cd_gpio;
bool ext_cd_gpio_invert;
int (*ext_cd_init)(void (*notify_func)(struct platform_device *,
......@@ -129,12 +127,9 @@ extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
/* S3C2416 SDHCI setup */
#ifdef CONFIG_S3C2416_SETUP_SDHCI
extern char *s3c2416_hsmmc_clksrcs[4];
static inline void s3c2416_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = s3c2416_setup_sdhci0_cfg_gpio;
#endif /* CONFIG_S3C_DEV_HSMMC */
}
......@@ -142,7 +137,6 @@ static inline void s3c2416_default_sdhci0(void)
static inline void s3c2416_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.clocks = s3c2416_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = s3c2416_setup_sdhci1_cfg_gpio;
#endif /* CONFIG_S3C_DEV_HSMMC1 */
}
......@@ -155,12 +149,9 @@ static inline void s3c2416_default_sdhci1(void) { }
/* S3C64XX SDHCI setup */
#ifdef CONFIG_S3C64XX_SETUP_SDHCI
extern char *s3c64xx_hsmmc_clksrcs[4];
static inline void s3c6400_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
#endif
}
......@@ -168,7 +159,6 @@ static inline void s3c6400_default_sdhci0(void)
static inline void s3c6400_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
#endif
}
......@@ -176,7 +166,6 @@ static inline void s3c6400_default_sdhci1(void)
static inline void s3c6400_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
#endif
}
......@@ -184,7 +173,6 @@ static inline void s3c6400_default_sdhci2(void)
static inline void s3c6410_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = s3c64xx_setup_sdhci0_cfg_gpio;
#endif
}
......@@ -192,7 +180,6 @@ static inline void s3c6410_default_sdhci0(void)
static inline void s3c6410_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = s3c64xx_setup_sdhci1_cfg_gpio;
#endif
}
......@@ -200,7 +187,6 @@ static inline void s3c6410_default_sdhci1(void)
static inline void s3c6410_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.clocks = s3c64xx_hsmmc_clksrcs;
s3c_hsmmc2_def_platdata.cfg_gpio = s3c64xx_setup_sdhci2_cfg_gpio;
#endif
}
......@@ -218,12 +204,9 @@ static inline void s3c6400_default_sdhci2(void) { }
/* S5PC100 SDHCI setup */
#ifdef CONFIG_S5PC100_SETUP_SDHCI
extern char *s5pc100_hsmmc_clksrcs[4];
static inline void s5pc100_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = s5pc100_setup_sdhci0_cfg_gpio;
#endif
}
......@@ -231,7 +214,6 @@ static inline void s5pc100_default_sdhci0(void)
static inline void s5pc100_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = s5pc100_setup_sdhci1_cfg_gpio;
#endif
}
......@@ -239,7 +221,6 @@ static inline void s5pc100_default_sdhci1(void)
static inline void s5pc100_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.clocks = s5pc100_hsmmc_clksrcs;
s3c_hsmmc2_def_platdata.cfg_gpio = s5pc100_setup_sdhci2_cfg_gpio;
#endif
}
......@@ -254,12 +235,9 @@ static inline void s5pc100_default_sdhci2(void) { }
/* S5PV210 SDHCI setup */
#ifdef CONFIG_S5PV210_SETUP_SDHCI
extern char *s5pv210_hsmmc_clksrcs[4];
static inline void s5pv210_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = s5pv210_setup_sdhci0_cfg_gpio;
#endif
}
......@@ -267,7 +245,6 @@ static inline void s5pv210_default_sdhci0(void)
static inline void s5pv210_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = s5pv210_setup_sdhci1_cfg_gpio;
#endif
}
......@@ -275,7 +252,6 @@ static inline void s5pv210_default_sdhci1(void)
static inline void s5pv210_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc2_def_platdata.cfg_gpio = s5pv210_setup_sdhci2_cfg_gpio;
#endif
}
......@@ -283,7 +259,6 @@ static inline void s5pv210_default_sdhci2(void)
static inline void s5pv210_default_sdhci3(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC3
s3c_hsmmc3_def_platdata.clocks = s5pv210_hsmmc_clksrcs;
s3c_hsmmc3_def_platdata.cfg_gpio = s5pv210_setup_sdhci3_cfg_gpio;
#endif
}
......@@ -298,12 +273,9 @@ static inline void s5pv210_default_sdhci3(void) { }
/* EXYNOS4 SDHCI setup */
#ifdef CONFIG_EXYNOS4_SETUP_SDHCI
extern char *exynos4_hsmmc_clksrcs[4];
static inline void exynos4_default_sdhci0(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC
s3c_hsmmc0_def_platdata.clocks = exynos4_hsmmc_clksrcs;
s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio;
#endif
}
......@@ -311,7 +283,6 @@ static inline void exynos4_default_sdhci0(void)
static inline void exynos4_default_sdhci1(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC1
s3c_hsmmc1_def_platdata.clocks = exynos4_hsmmc_clksrcs;
s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio;
#endif
}
......@@ -319,7 +290,6 @@ static inline void exynos4_default_sdhci1(void)
static inline void exynos4_default_sdhci2(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC2
s3c_hsmmc2_def_platdata.clocks = exynos4_hsmmc_clksrcs;
s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio;
#endif
}
......@@ -327,7 +297,6 @@ static inline void exynos4_default_sdhci2(void)
static inline void exynos4_default_sdhci3(void)
{
#ifdef CONFIG_S3C_DEV_HSMMC3
s3c_hsmmc3_def_platdata.clocks = exynos4_hsmmc_clksrcs;
s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio;
#endif
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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
......
......@@ -435,14 +435,11 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
struct clk *clk;
char *name = pdata->clocks[ptr];
if (name == NULL)
continue;
char name[14];
snprintf(name, 14, "mmc_busclk.%d", ptr);
clk = clk_get(dev, name);
if (IS_ERR(clk)) {
dev_err(dev, "failed to get clock %s\n", name);
continue;
}
......
......@@ -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,
},
};
......
......@@ -971,6 +971,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
struct s3c64xx_spi_info *sci;
struct spi_master *master;
int ret;
char clk_name[16];
if (pdev->id < 0) {
dev_err(&pdev->dev,
......@@ -984,11 +985,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
}
sci = pdev->dev.platform_data;
if (!sci->src_clk_name) {
dev_err(&pdev->dev,
"Board init must call s3c64xx_spi_set_info()\n");
return -EINVAL;
}
/* Check for availability of necessary resource */
......@@ -1073,17 +1069,17 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
goto err4;
}
sdd->src_clk = clk_get(&pdev->dev, sci->src_clk_name);
sprintf(clk_name, "spi_busclk%d", sci->src_clk_nr);
sdd->src_clk = clk_get(&pdev->dev, clk_name);
if (IS_ERR(sdd->src_clk)) {
dev_err(&pdev->dev,
"Unable to acquire clock '%s'\n", sci->src_clk_name);
"Unable to acquire clock '%s'\n", clk_name);
ret = PTR_ERR(sdd->src_clk);
goto err5;
}
if (clk_enable(sdd->src_clk)) {
dev_err(&pdev->dev, "Couldn't enable clock '%s'\n",
sci->src_clk_name);
dev_err(&pdev->dev, "Couldn't enable clock '%s'\n", clk_name);
ret = -EBUSY;
goto err6;
}
......
......@@ -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
......
......@@ -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
......
/*
* 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");
/*
* 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");
/*
* 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");
/*
* 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");
/*
* 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>");
......@@ -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");
......@@ -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 *);
......
......@@ -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_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment