diff options
463 files changed, 8740 insertions, 6603 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd index fa72ccb2282e..dbedafb095e2 100644 --- a/Documentation/ABI/testing/sysfs-bus-rbd +++ b/Documentation/ABI/testing/sysfs-bus-rbd @@ -57,13 +57,6 @@ create_snap $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_create -rollback_snap - - Rolls back data to the specified snapshot. This goes over the entire - list of rados blocks and sends a rollback command to each. - - $ echo <snap-name> > /sys/bus/rbd/devices/<dev-id>/snap_rollback - snap_* A directory per each snapshot diff --git a/Documentation/devicetree/bindings/arm/insignal-boards.txt b/Documentation/devicetree/bindings/arm/insignal-boards.txt new file mode 100644 index 000000000000..524c3dc5d808 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/insignal-boards.txt @@ -0,0 +1,8 @@ +* Insignal's Exynos4210 based Origen evaluation board + +Origen low-cost evaluation board is based on Samsung's Exynos4210 SoC. + +Required root node properties: + - compatible = should be one or more of the following. + (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board. + (b) "samsung,exynos4210" - for boards based on Exynos4210 SoC. diff --git a/Documentation/devicetree/bindings/arm/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung-boards.txt new file mode 100644 index 000000000000..0bf68be56fd1 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/samsung-boards.txt @@ -0,0 +1,8 @@ +* Samsung's Exynos4210 based SMDKV310 evaluation board + +SMDKV310 evaluation board is based on Samsung's Exynos4210 SoC. + +Required root node properties: + - compatible = should be one or more of the following. + (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board. + (b) "samsung,exynos4210" - for boards based on Exynos4210 SoC. diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt b/Documentation/devicetree/bindings/dma/arm-pl330.txt new file mode 100644 index 000000000000..a4cd273b2a67 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt @@ -0,0 +1,30 @@ +* ARM PrimeCell PL330 DMA Controller + +The ARM PrimeCell PL330 DMA controller can move blocks of memory contents +between memory and peripherals or memory to memory. + +Required properties: + - compatible: should include both "arm,pl330" and "arm,primecell". + - reg: physical base address of the controller and length of memory mapped + region. + - interrupts: interrupt number to the cpu. + +Example: + + pdma0: pdma@12680000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x12680000 0x1000>; + interrupts = <99>; + }; + +Client drivers (device nodes requiring dma transfers from dev-to-mem or +mem-to-dev) should specify the DMA channel numbers using a two-value pair +as shown below. + + [property name] = <[phandle of the dma controller] [dma request id]>; + + where 'dma request id' is the dma request number which is connected + to the client controller. The 'property name' is recommended to be + of the form <name>-dma-channel. + + Example: tx-dma-channel = <&pdma0 12>; diff --git a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt new file mode 100644 index 000000000000..8f50fe5e6c42 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt @@ -0,0 +1,40 @@ +Samsung Exynos4 GPIO Controller + +Required properties: +- compatible: Compatible property value should be "samsung,exynos4-gpio>". + +- reg: Physical base address of the controller and length of memory mapped + region. + +- #gpio-cells: Should be 4. The syntax of the gpio specifier used by client nodes + should be the following with values derived from the SoC user manual. + <[phandle of the gpio controller node] + [pin number within the gpio controller] + [mux function] + [pull up/down] + [drive strength]> + + Values for gpio specifier: + - Pin number: is a value between 0 to 7. + - Pull Up/Down: 0 - Pull Up/Down Disabled. + 1 - Pull Down Enabled. + 3 - Pull Up Enabled. + - Drive Strength: 0 - 1x, + 1 - 3x, + 2 - 2x, + 3 - 4x + +- gpio-controller: Specifies that the node is a gpio controller. +- #address-cells: should be 1. +- #size-cells: should be 1. + +Example: + + gpa0: gpio-controller@11400000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "samsung,exynos4-gpio"; + reg = <0x11400000 0x20>; + #gpio-cells = <4>; + gpio-controller; + }; diff --git a/Documentation/devicetree/bindings/input/samsung-keypad.txt b/Documentation/devicetree/bindings/input/samsung-keypad.txt new file mode 100644 index 000000000000..ce3e394c0e64 --- /dev/null +++ b/Documentation/devicetree/bindings/input/samsung-keypad.txt @@ -0,0 +1,88 @@ +* Samsung's Keypad Controller device tree bindings + +Samsung's Keypad controller is used to interface a SoC with a matrix-type +keypad device. The keypad controller supports multiple row and column lines. +A key can be placed at each intersection of a unique row and a unique column. +The keypad controller can sense a key-press and key-release and report the +event using a interrupt to the cpu. + +Required SoC Specific Properties: +- compatible: should be one of the following + - "samsung,s3c6410-keypad": For controllers compatible with s3c6410 keypad + controller. + - "samsung,s5pv210-keypad": For controllers compatible with s5pv210 keypad + controller. + +- reg: physical base address of the controller and length of memory mapped + region. + +- interrupts: The interrupt number to the cpu. + +Required Board Specific Properties: +- samsung,keypad-num-rows: Number of row lines connected to the keypad + controller. + +- samsung,keypad-num-columns: Number of column lines connected to the + keypad controller. + +- row-gpios: List of gpios used as row lines. The gpio specifier for + this property depends on the gpio controller to which these row lines + are connected. + +- col-gpios: List of gpios used as column lines. The gpio specifier for + this property depends on the gpio controller to which these column + lines are connected. + +- Keys represented as child nodes: Each key connected to the keypad + controller is represented as a child node to the keypad controller + device node and should include the following properties. + - keypad,row: the row number to which the key is connected. + - keypad,column: the column number to which the key is connected. + - linux,code: the key-code to be reported when the key is pressed + and released. + +Optional Properties specific to linux: +- linux,keypad-no-autorepeat: do no enable autorepeat feature. +- linux,keypad-wakeup: use any event on keypad as wakeup event. + + +Example: + keypad@100A0000 { + compatible = "samsung,s5pv210-keypad"; + reg = <0x100A0000 0x100>; + interrupts = <173>; + samsung,keypad-num-rows = <2>; + samsung,keypad-num-columns = <8>; + linux,input-no-autorepeat; + linux,input-wakeup; + + row-gpios = <&gpx2 0 3 3 0 + &gpx2 1 3 3 0>; + + col-gpios = <&gpx1 0 3 0 0 + &gpx1 1 3 0 0 + &gpx1 2 3 0 0 + &gpx1 3 3 0 0 + &gpx1 4 3 0 0 + &gpx1 5 3 0 0 + &gpx1 6 3 0 0 + &gpx1 7 3 0 0>; + + key_1 { + keypad,row = <0>; + keypad,column = <3>; + linux,code = <2>; + }; + + key_2 { + keypad,row = <0>; + keypad,column = <4>; + linux,code = <3>; + }; + + key_3 { + keypad,row = <0>; + keypad,column = <5>; + linux,code = <4>; + }; + }; diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt new file mode 100644 index 000000000000..44afa0e5057d --- /dev/null +++ b/Documentation/devicetree/bindings/net/macb.txt @@ -0,0 +1,25 @@ +* Cadence MACB/GEM Ethernet controller + +Required properties: +- compatible: Should be "cdns,[<chip>-]{macb|gem}" + Use "cdns,at91sam9260-macb" Atmel at91sam9260 and at91sam9263 SoCs. + Use "cdns,at32ap7000-macb" for other 10/100 usage or use the generic form: "cdns,macb". + Use "cnds,pc302-gem" for Picochip picoXcell pc302 and later devices based on + the Cadence GEM, or the generic form: "cdns,gem". +- reg: Address and length of the register set for the device +- interrupts: Should contain macb interrupt +- phy-mode: String, operation mode of the PHY interface. + Supported values are: "mii", "rmii", "gmii", "rgmii". + +Optional properties: +- local-mac-address: 6 bytes, mac address + +Examples: + + macb0: ethernet@fffc4000 { + compatible = "cdns,at32ap7000-macb"; + reg = <0xfffc4000 0x4000>; + interrupts = <21>; + phy-mode = "rmii"; + local-mac-address = [3a 0e 03 04 05 06]; + }; diff --git a/Documentation/devicetree/bindings/rtc/s3c-rtc.txt b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt new file mode 100644 index 000000000000..90ec45fd33ec --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/s3c-rtc.txt @@ -0,0 +1,20 @@ +* Samsung's S3C Real Time Clock controller + +Required properties: +- compatible: should be one of the following. + * "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc. + * "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc. +- reg: physical base address of the controller and length of memory mapped + region. +- interrupts: Two interrupt numbers to the cpu should be specified. First + interrupt number is the rtc alarm interupt and second interrupt number + is the rtc tick interrupt. The number of cells representing a interrupt + depends on the parent interrupt controller. + +Example: + + rtc@10070000 { + compatible = "samsung,s3c6410-rtc"; + reg = <0x10070000 0x100>; + interrupts = <44 0 45 0>; + }; diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.txt b/Documentation/devicetree/bindings/serial/samsung_uart.txt new file mode 100644 index 000000000000..2c8a17cf5cb5 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/samsung_uart.txt @@ -0,0 +1,14 @@ +* Samsung's UART Controller + +The Samsung's UART controller is used for interfacing SoC with serial communicaion +devices. + +Required properties: +- compatible: should be + - "samsung,exynos4210-uart", for UART's compatible with Exynos4210 uart ports. + +- reg: base physical address of the controller and length of memory mapped + region. + +- interrupts: interrupt number to the cpu. The interrupt specifier format depends + on the interrupt controller parent. @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 2 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 86ebbc5ffcd1..34d13ff3901c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -220,8 +220,9 @@ config NEED_MACH_MEMORY_H be avoided when possible. config PHYS_OFFSET - hex "Physical address of main memory" + hex "Physical address of main memory" if MMU depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H + default DRAM_BASE if !MMU help Please provide the physical address corresponding to the location of main memory in your system. @@ -591,6 +592,7 @@ config ARCH_MMP select ARCH_REQUIRE_GPIOLIB select CLKDEV_LOOKUP select GENERIC_CLOCKEVENTS + select GPIO_PXA select HAVE_SCHED_CLOCK select TICK_ONESHOT select PLAT_PXA @@ -673,6 +675,7 @@ config ARCH_PXA select CLKSRC_MMIO select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS + select GPIO_PXA select HAVE_SCHED_CLOCK select TICK_ONESHOT select PLAT_PXA diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi index aeef04269cf8..07603b8c9503 100644 --- a/arch/arm/boot/dts/at91sam9g20.dtsi +++ b/arch/arm/boot/dts/at91sam9g20.dtsi @@ -114,6 +114,13 @@ atmel,use-dma-tx; status = "disabled"; }; + + macb0: ethernet@fffc4000 { + compatible = "cdns,at32ap7000-macb", "cdns,macb"; + reg = <0xfffc4000 0x100>; + interrupts = <21>; + status = "disabled"; + }; }; }; }; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index db6a45202f26..fffa005300a4 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -101,6 +101,13 @@ atmel,use-dma-tx; status = "disabled"; }; + + macb0: ethernet@fffbc000 { + compatible = "cdns,at32ap7000-macb", "cdns,macb"; + reg = <0xfffbc000 0x100>; + interrupts = <25>; + status = "disabled"; + }; }; }; }; diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts index 85b34f59cd82..a387e7704ce1 100644 --- a/arch/arm/boot/dts/at91sam9m10g45ek.dts +++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts @@ -30,6 +30,11 @@ usart1: serial@fff90000 { status = "okay"; }; + + macb0: ethernet@fffbc000 { + phy-mode = "rmii"; + status = "okay"; + }; }; }; }; diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts new file mode 100644 index 000000000000..b8c476384eef --- /dev/null +++ b/arch/arm/boot/dts/exynos4210-origen.dts @@ -0,0 +1,137 @@ +/* + * Samsung's Exynos4210 based Origen board device tree source + * + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2010-2011 Linaro Ltd. + * www.linaro.org + * + * Device tree source file for Insignal's Origen board which is based on + * Samsung's Exynos4210 SoC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/dts-v1/; +/include/ "exynos4210.dtsi" + +/ { + model = "Insignal Origen evaluation board based on Exynos4210"; + compatible = "insignal,origen", "samsung,exynos4210"; + + memory { + reg = <0x40000000 0x40000000>; + }; + + chosen { + bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc"; + }; + + sdhci@12530000 { + samsung,sdhci-bus-width = <4>; + linux,mmc_cap_4_bit_data; + samsung,sdhci-cd-internal; + gpio-cd = <&gpk2 2 2 3 3>; + gpios = <&gpk2 0 2 0 3>, + <&gpk2 1 2 0 3>, + <&gpk2 3 2 3 3>, + <&gpk2 4 2 3 3>, + <&gpk2 5 2 3 3>, + <&gpk2 6 2 3 3>; + }; + + sdhci@12510000 { + samsung,sdhci-bus-width = <4>; + linux,mmc_cap_4_bit_data; + samsung,sdhci-cd-internal; + gpio-cd = <&gpk0 2 2 3 3>; + gpios = <&gpk0 0 2 0 3>, + <&gpk0 1 2 0 3>, + <&gpk0 3 2 3 3>, + <&gpk0 4 2 3 3>, + <&gpk0 5 2 3 3>, + <&gpk0 6 2 3 3>; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + + up { + label = "Up"; + gpios = <&gpx2 0 0 0 2>; + linux,code = <103>; + }; + + down { + label = "Down"; + gpios = <&gpx2 1 0 0 2>; + linux,code = <108>; + }; + + back { + label = "Back"; + gpios = <&gpx1 7 0 0 2>; + linux,code = <158>; + }; + + home { + label = "Home"; + gpios = <&gpx1 6 0 0 2>; + linux,code = <102>; + }; + + menu { + label = "Menu"; + gpios = <&gpx1 5 0 0 2>; + linux,code = <139>; + }; + }; + + keypad@100A0000 { + status = "disabled"; + }; + + sdhci@12520000 { + status = "disabled"; + }; + + sdhci@12540000 { + status = "disabled"; + }; + + i2c@13860000 { + status = "disabled"; + }; + + i2c@13870000 { + status = "disabled"; + }; + + i2c@13880000 { + status = "disabled"; + }; + + i2c@13890000 { + status = "disabled"; + }; + + i2c@138A0000 { + status = "disabled"; + }; + + i2c@138B0000 { + status = "disabled"; + }; + + i2c@138C0000 { + status = "disabled"; + }; + + i2c@138D0000 { + status = "disabled"; + }; +}; diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts new file mode 100644 index 000000000000..27afc8e535ca --- /dev/null +++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts @@ -0,0 +1,182 @@ +/* + * Samsung's Exynos4210 based SMDKV310 board device tree source + * + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2010-2011 Linaro Ltd. + * www.linaro.org + * + * Device tree source file for Samsung's SMDKV310 board which is based on + * Samsung's Exynos4210 SoC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/dts-v1/; +/include/ "exynos4210.dtsi" + +/ { + model = "Samsung smdkv310 evaluation board based on Exynos4210"; + compatible = "samsung,smdkv310", "samsung,exynos4210"; + + memory { + reg = <0x40000000 0x80000000>; + }; + + chosen { + bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc"; + }; + + sdhci@12530000 { + samsung,sdhci-bus-width = <4>; + linux,mmc_cap_4_bit_data; + samsung,sdhci-cd-internal; + gpio-cd = <&gpk2 2 2 3 3>; + gpios = <&gpk2 0 2 0 3>, + <&gpk2 1 2 0 3>, + <&gpk2 3 2 3 3>, + <&gpk2 4 2 3 3>, + <&gpk2 5 2 3 3>, + <&gpk2 6 2 3 3>; + }; + + keypad@100A0000 { + samsung,keypad-num-rows = <2>; + samsung,keypad-num-columns = <8>; + linux,keypad-no-autorepeat; + linux,keypad-wakeup; + + row-gpios = <&gpx2 0 3 3 0>, + <&gpx2 1 3 3 0>; + + col-gpios = <&gpx1 0 3 0 0>, + <&gpx1 1 3 0 0>, + <&gpx1 2 3 0 0>, + <&gpx1 3 3 0 0>, + <&gpx1 4 3 0 0>, + <&gpx1 5 3 0 0>, + <&gpx1 6 3 0 0>, + <&gpx1 7 3 0 0>; + + key_1 { + keypad,row = <0>; + keypad,column = <3>; + linux,code = <2>; + }; + + key_2 { + keypad,row = <0>; + keypad,column = <4>; + linux,code = <3>; + }; + + key_3 { + keypad,row = <0>; + keypad,column = <5>; + linux,code = <4>; + }; + + key_4 { + keypad,row = <0>; + keypad,column = <6>; + linux,code = <5>; + }; + + key_5 { + keypad,row = <0>; + keypad,column = <7>; + linux,code = <6>; + }; + + key_a { + keypad,row = <1>; + keypad,column = <3>; + linux,code = <30>; + }; + + key_b { + keypad,row = <1>; + keypad,column = <4>; + linux,code = <48>; + }; + + key_c { + keypad,row = <1>; + keypad,column = <5>; + linux,code = <46>; + }; + + key_d { + keypad,row = <1>; + keypad,column = <6>; + linux,code = <32>; + }; + + key_e { + keypad,row = <1>; + keypad,column = <7>; + linux,code = <18>; + }; + }; + + i2c@13860000 { + #address-cells = <1>; + #size-cells = <0>; + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <20000>; + gpios = <&gpd1 0 2 3 0>, + <&gpd1 1 2 3 0>; + + eeprom@50 { + compatible = "samsung,24ad0xd1"; + reg = <0x50>; + }; + + eeprom@52 { + compatible = "samsung,24ad0xd1"; + reg = <0x52>; + }; + }; + + sdhci@12510000 { + status = "disabled"; + }; + + sdhci@12520000 { + status = "disabled"; + }; + + sdhci@12540000 { + status = "disabled"; + }; + + i2c@13870000 { + status = "disabled"; + }; + + i2c@13880000 { + status = "disabled"; + }; + + i2c@13890000 { + status = "disabled"; + }; + + i2c@138A0000 { + status = "disabled"; + }; + + i2c@138B0000 { + status = "disabled"; + }; + + i2c@138C0000 { + status = "disabled"; + }; + + i2c@138D0000 { + status = "disabled"; + }; +}; diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi new file mode 100644 index 000000000000..63d7578856c1 --- /dev/null +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -0,0 +1,397 @@ +/* + * Samsung's Exynos4210 SoC device tree source + * + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2010-2011 Linaro Ltd. + * www.linaro.org + * + * Samsung's Exynos4210 SoC device nodes are listed in this file. Exynos4210 + * based board files can include this file and provide values for board specfic + * bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos4210 SoC. As device tree coverage for Exynos4210 increases, additional + * nodes can be added to this file. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/include/ "skeleton.dtsi" + +/ { + compatible = "samsung,exynos4210"; + interrupt-parent = <&gic>; + + gic:interrupt-controller@10490000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x10490000 0x1000>, <0x10480000 0x100>; + }; + + watchdog@10060000 { + compatible = "samsung,s3c2410-wdt"; + reg = <0x10060000 0x100>; + interrupts = <0 43 0>; + }; + + rtc@10070000 { + compatible = "samsung,s3c6410-rtc"; + reg = <0x10070000 0x100>; + interrupts = <0 44 0>, <0 45 0>; + }; + + keypad@100A0000 { + compatible = "samsung,s5pv210-keypad"; + reg = <0x100A0000 0x100>; + interrupts = <0 109 0>; + }; + + sdhci@12510000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12510000 0x100>; + interrupts = <0 73 0>; + }; + + sdhci@12520000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12520000 0x100>; + interrupts = <0 74 0>; + }; + + sdhci@12530000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12530000 0x100>; + interrupts = <0 75 0>; + }; + + sdhci@12540000 { + compatible = "samsung,exynos4210-sdhci"; + reg = <0x12540000 0x100>; + interrupts = <0 76 0>; + }; + + serial@13800000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13800000 0x100>; + interrupts = <0 52 0>; + }; + + serial@13810000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13810000 0x100>; + interrupts = <0 53 0>; + }; + + serial@13820000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13820000 0x100>; + interrupts = <0 54 0>; + }; + + serial@13830000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13830000 0x100>; + interrupts = <0 55 0>; + }; + + i2c@13860000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x13860000 0x100>; + interrupts = <0 58 0>; + }; + + i2c@13870000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x13870000 0x100>; + interrupts = <0 59 0>; + }; + + i2c@13880000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x13880000 0x100>; + interrupts = <0 60 0>; + }; + + i2c@13890000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x13890000 0x100>; + interrupts = <0 61 0>; + }; + + i2c@138A0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x138A0000 0x100>; + interrupts = <0 62 0>; + }; + + i2c@138B0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x138B0000 0x100>; + interrupts = <0 63 0>; + }; + + i2c@138C0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x138C0000 0x100>; + interrupts = <0 64 0>; + }; + + i2c@138D0000 { + compatible = "samsung,s3c2440-i2c"; + reg = <0x138D0000 0x100>; + interrupts = <0 65 0>; + }; + + amba { + #address-cells = <1>; + #size-cells = <1>; + compatible = "arm,amba-bus"; + interrupt-parent = <&gic>; + ranges; + + pdma0: pdma@12680000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x12680000 0x1000>; + interrupts = <0 35 0>; + }; + + pdma1: pdma@12690000 { + compatible = "arm,pl330", "arm,primecell"; + reg = <0x12690000 0x1000>; + interrupts = <0 36 0>; + }; + }; + + gpio-controllers { + #address-cells = <1>; + #size-cells = <1>; + gpio-controller; + ranges; + + gpa0: gpio-controller@11400000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400000 0x20>; + #gpio-cells = <4>; + }; + + gpa1: gpio-controller@11400020 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400020 0x20>; + #gpio-cells = <4>; + }; + + gpb: gpio-controller@11400040 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400040 0x20>; + #gpio-cells = <4>; + }; + + gpc0: gpio-controller@11400060 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400060 0x20>; + #gpio-cells = <4>; + }; + + gpc1: gpio-controller@11400080 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400080 0x20>; + #gpio-cells = <4>; + }; + + gpd0: gpio-controller@114000A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114000A0 0x20>; + #gpio-cells = <4>; + }; + + gpd1: gpio-controller@114000C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114000C0 0x20>; + #gpio-cells = <4>; + }; + + gpe0: gpio-controller@114000E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114000E0 0x20>; + #gpio-cells = <4>; + }; + + gpe1: gpio-controller@11400100 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400100 0x20>; + #gpio-cells = <4>; + }; + + gpe2: gpio-controller@11400120 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400120 0x20>; + #gpio-cells = <4>; + }; + + gpe3: gpio-controller@11400140 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400140 0x20>; + #gpio-cells = <4>; + }; + + gpe4: gpio-controller@11400160 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400160 0x20>; + #gpio-cells = <4>; + }; + + gpf0: gpio-controller@11400180 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11400180 0x20>; + #gpio-cells = <4>; + }; + + gpf1: gpio-controller@114001A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114001A0 0x20>; + #gpio-cells = <4>; + }; + + gpf2: gpio-controller@114001C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114001C0 0x20>; + #gpio-cells = <4>; + }; + + gpf3: gpio-controller@114001E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x114001E0 0x20>; + #gpio-cells = <4>; + }; + + gpj0: gpio-controller@11000000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000000 0x20>; + #gpio-cells = <4>; + }; + + gpj1: gpio-controller@11000020 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000020 0x20>; + #gpio-cells = <4>; + }; + + gpk0: gpio-controller@11000040 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000040 0x20>; + #gpio-cells = <4>; + }; + + gpk1: gpio-controller@11000060 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000060 0x20>; + #gpio-cells = <4>; + }; + + gpk2: gpio-controller@11000080 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000080 0x20>; + #gpio-cells = <4>; + }; + + gpk3: gpio-controller@110000A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x110000A0 0x20>; + #gpio-cells = <4>; + }; + + gpl0: gpio-controller@110000C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x110000C0 0x20>; + #gpio-cells = <4>; + }; + + gpl1: gpio-controller@110000E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x110000E0 0x20>; + #gpio-cells = <4>; + }; + + gpl2: gpio-controller@11000100 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000100 0x20>; + #gpio-cells = <4>; + }; + + gpy0: gpio-controller@11000120 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000120 0x20>; + #gpio-cells = <4>; + }; + + gpy1: gpio-controller@11000140 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000140 0x20>; + #gpio-cells = <4>; + }; + + gpy2: gpio-controller@11000160 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000160 0x20>; + #gpio-cells = <4>; + }; + + gpy3: gpio-controller@11000180 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000180 0x20>; + #gpio-cells = <4>; + }; + + gpy4: gpio-controller@110001A0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x110001A0 0x20>; + #gpio-cells = <4>; + }; + + gpy5: gpio-controller@110001C0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x110001C0 0x20>; + #gpio-cells = <4>; + }; + + gpy6: gpio-controller@110001E0 { + compatible = "samsung,exynos4-gpio"; + reg = <0x110001E0 0x20>; + #gpio-cells = <4>; + }; + + gpx0: gpio-controller@11000C00 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000C00 0x20>; + #gpio-cells = <4>; + }; + + gpx1: gpio-controller@11000C20 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000C20 0x20>; + #gpio-cells = <4>; + }; + + gpx2: gpio-controller@11000C40 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000C40 0x20>; + #gpio-cells = <4>; + }; + + gpx3: gpio-controller@11000C60 { + compatible = "samsung,exynos4-gpio"; + reg = <0x11000C60 0x20>; + #gpio-cells = <4>; + }; + + gpz: gpio-controller@03860000 { + compatible = "samsung,exynos4-gpio"; + reg = <0x03860000 0x20>; + #gpio-cells = <4>; + }; + }; +}; diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts index d66e2c00ac35..f04b535477f5 100644 --- a/arch/arm/boot/dts/usb_a9g20.dts +++ b/arch/arm/boot/dts/usb_a9g20.dts @@ -25,6 +25,11 @@ dbgu: serial@fffff200 { status = "okay"; }; + + macb0: ethernet@fffc4000 { + phy-mode = "rmii"; + status = "okay"; + }; }; }; }; diff --git a/arch/arm/include/asm/unwind.h b/arch/arm/include/asm/unwind.h index a5edf421005c..d1c3f3a71c94 100644 --- a/arch/arm/include/asm/unwind.h +++ b/arch/arm/include/asm/unwind.h @@ -30,14 +30,15 @@ enum unwind_reason_code { }; struct unwind_idx { - unsigned long addr; + unsigned long addr_offset; unsigned long insn; }; struct unwind_table { struct list_head list; - struct unwind_idx *start; - struct unwind_idx *stop; + const struct unwind_idx *start; + const struct unwind_idx *origin; + const struct unwind_idx *stop; unsigned long begin_addr; unsigned long end_addr; }; @@ -49,15 +50,6 @@ extern struct unwind_table *unwind_table_add(unsigned long start, extern void unwind_table_del(struct unwind_table *tab); extern void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk); -#ifdef CONFIG_ARM_UNWIND -extern int __init unwind_init(void); -#else -static inline int __init unwind_init(void) -{ - return 0; -} -#endif - #endif /* !__ASSEMBLY__ */ #ifdef CONFIG_ARM_UNWIND diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 8e9c98edc068..88b0941ce51e 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -640,6 +640,9 @@ static struct platform_device_id armpmu_plat_device_ids[] = { static int __devinit armpmu_device_probe(struct platform_device *pdev) { + if (!cpu_pmu) + return -ENODEV; + cpu_pmu->plat_device = pdev; return 0; } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 3448a3f9cc8c..8fc2c8fcbdc6 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -895,8 +895,6 @@ void __init setup_arch(char **cmdline_p) { struct machine_desc *mdesc; - unwind_init(); - setup_processor(); mdesc = setup_machine_fdt(__atags_pointer); if (!mdesc) @@ -904,6 +902,12 @@ void __init setup_arch(char **cmdline_p) machine_desc = mdesc; machine_name = mdesc->name; +#ifdef CONFIG_ZONE_DMA + if (mdesc->dma_zone_size) { + extern unsigned long arm_dma_zone_size; + arm_dma_zone_size = mdesc->dma_zone_size; + } +#endif if (mdesc->soft_reboot) reboot_setup("s"); @@ -934,12 +938,6 @@ void __init setup_arch(char **cmdline_p) tcm_init(); -#ifdef CONFIG_ZONE_DMA - if (mdesc->dma_zone_size) { - extern unsigned long arm_dma_zone_size; - arm_dma_zone_size = mdesc->dma_zone_size; - } -#endif #ifdef CONFIG_MULTI_IRQ_HANDLER handle_arch_irq = mdesc->handle_irq; #endif diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index e7e8365795c3..00df012c4678 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -67,7 +67,7 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); struct unwind_ctrl_block { unsigned long vrs[16]; /* virtual register set */ - unsigned long *insn; /* pointer to the current instructions word */ + const unsigned long *insn; /* pointer to the current instructions word */ int entries; /* number of entries left to interpret */ int byte; /* current byte number in the instructions word */ }; @@ -83,8 +83,9 @@ enum regs { PC = 15 }; -extern struct unwind_idx __start_unwind_idx[]; -extern struct unwind_idx __stop_unwind_idx[]; +extern const struct unwind_idx __start_unwind_idx[]; +static const struct unwind_idx *__origin_unwind_idx; +extern const struct unwind_idx __stop_unwind_idx[]; static DEFINE_SPINLOCK(unwind_lock); static LIST_HEAD(unwind_tables); @@ -98,45 +99,99 @@ static LIST_HEAD(unwind_tables); }) /* - * Binary search in the unwind index. The entries entries are + * Binary search in the unwind index. The entries are * guaranteed to be sorted in ascending order by the linker. + * + * start = first entry + * origin = first entry with positive offset (or stop if there is no such entry) + * stop - 1 = last entry */ -static struct unwind_idx *search_index(unsigned long addr, - struct unwind_idx *first, - struct unwind_idx *last) +static const struct unwind_idx *search_index(unsigned long addr, + const struct unwind_idx *start, + const struct unwind_idx *origin, + const struct unwind_idx *stop) { - pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last); + unsigned long addr_prel31; + + pr_debug("%s(%08lx, %p, %p, %p)\n", + __func__, addr, start, origin, stop); + + /* + * only search in the section with the matching sign. This way the + * prel31 numbers can be compared as unsigned longs. + */ + if (addr < (unsigned long)start) + /* negative offsets: [start; origin) */ + stop = origin; + else + /* positive offsets: [origin; stop) */ + start = origin; + + /* prel31 for address relavive to start */ + addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff; - if (addr < first->addr) { + while (start < stop - 1) { + const struct unwind_idx *mid = start + ((stop - start) >> 1); + + /* + * As addr_prel31 is relative to start an offset is needed to + * make it relative to mid. + */ + if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) < + mid->addr_offset) + stop = mid; + else { + /* keep addr_prel31 relative to start */ + addr_prel31 -= ((unsigned long)mid - + (unsigned long)start); + start = mid; + } + } + + if (likely(start->addr_offset <= addr_prel31)) + return start; + else { pr_warning("unwind: Unknown symbol address %08lx\n", addr); return NULL; - } else if (addr >= last->addr) - return last; + } +} - while (first < last - 1) { - struct unwind_idx *mid = first + ((last - first + 1) >> 1); +static const struct unwind_idx *unwind_find_origin( + const struct unwind_idx *start, const struct unwind_idx *stop) +{ + pr_debug("%s(%p, %p)\n", __func__, start, stop); + while (start < stop) { + const struct unwind_idx *mid = start + ((stop - start) >> 1); - if (addr < mid->addr) - last = mid; + if (mid->addr_offset >= 0x40000000) + /* negative offset */ + start = mid + 1; else - first = mid; + /* positive offset */ + stop = mid; } - - return first; + pr_debug("%s -> %p\n", __func__, stop); + return stop; } -static struct unwind_idx *unwind_find_idx(unsigned long addr) +static const struct unwind_idx *unwind_find_idx(unsigned long addr) { - struct unwind_idx *idx = NULL; + const struct unwind_idx *idx = NULL; unsigned long flags; pr_debug("%s(%08lx)\n", __func__, addr); - if (core_kernel_text(addr)) + if (core_kernel_text(addr)) { + if (unlikely(!__origin_unwind_idx)) + __origin_unwind_idx = + unwind_find_origin(__start_unwind_idx, + __stop_unwind_idx); + /* main unwind table */ idx = search_index(addr, __start_unwind_idx, - __stop_unwind_idx - 1); - else { + __origin_unwind_idx, + __stop_unwind_idx); + } else { /* module unwind tables */ struct unwind_table *table; @@ -145,7 +200,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr) if (addr >= table->begin_addr && addr < table->end_addr) { idx = search_index(addr, table->start, - table->stop - 1); + table->origin, + table->stop); /* Move-to-front to exploit common traces */ list_move(&table->list, &unwind_tables); break; @@ -274,7 +330,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) int unwind_frame(struct stackframe *frame) { unsigned long high, low; - struct unwind_idx *idx; + const struct unwind_idx *idx; struct unwind_ctrl_block ctrl; /* only go to a higher address on the stack */ @@ -399,7 +455,6 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, unsigned long text_size) { unsigned long flags; - struct unwind_idx *idx; struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, @@ -408,15 +463,12 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, if (!tab) return tab; - tab->start = (struct unwind_idx *)start; - tab->stop = (struct unwind_idx *)(start + size); + tab->start = (const struct unwind_idx *)start; + tab->stop = (const struct unwind_idx *)(start + size); + tab->origin = unwind_find_origin(tab->start, tab->stop); tab->begin_addr = text_addr; tab->end_addr = text_addr + text_size; - /* Convert the symbol addresses to absolute values */ - for (idx = tab->start; idx < tab->stop; idx++) - idx->addr = prel31_to_addr(&idx->addr); - spin_lock_irqsave(&unwind_lock, flags); list_add_tail(&tab->list, &unwind_tables); spin_unlock_irqrestore(&unwind_lock, flags); @@ -437,16 +489,3 @@ void unwind_table_del(struct unwind_table *tab) kfree(tab); } - -int __init unwind_init(void) -{ - struct unwind_idx *idx; - - /* Convert the symbol addresses to absolute values */ - for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++) - idx->addr = prel31_to_addr(&idx->addr); - - pr_debug("unwind: ARM stack unwinding initialised\n"); - - return 0; -} diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c index ecdd54dd68c6..17632b82dd76 100644 --- a/arch/arm/mach-at91/at91cap9.c +++ b/arch/arm/mach-at91/at91cap9.c @@ -137,7 +137,7 @@ static struct clk pwm_clk = { .type = CLK_TYPE_PERIPHERAL, }; static struct clk macb_clk = { - .name = "macb_clk", + .name = "pclk", .pmc_mask = 1 << AT91CAP9_ID_EMAC, .type = CLK_TYPE_PERIPHERAL, }; @@ -210,6 +210,8 @@ static struct clk *periph_clocks[] __initdata = { }; static struct clk_lookup periph_clocks_lookups[] = { + /* One additional fake clock for macb_hclk */ + CLKDEV_CON_ID("hclk", &macb_clk), CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk), CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk), CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk), diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c index adad70db70eb..695aecab0a67 100644 --- a/arch/arm/mach-at91/at91cap9_devices.c +++ b/arch/arm/mach-at91/at91cap9_devices.c @@ -200,7 +200,7 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {} #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) static u64 eth_dmamask = DMA_BIT_MASK(32); -static struct at91_eth_data eth_data; +static struct macb_platform_data eth_data; static struct resource eth_resources[] = { [0] = { @@ -227,7 +227,7 @@ static struct platform_device at91cap9_eth_device = { .num_resources = ARRAY_SIZE(eth_resources), }; -void __init at91_add_device_eth(struct at91_eth_data *data) +void __init at91_add_device_eth(struct macb_platform_data *data) { if (!data) return; @@ -264,7 +264,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data) platform_device_register(&at91cap9_eth_device); } #else -void __init at91_add_device_eth(struct at91_eth_data *data) {} +void __init at91_add_device_eth(struct macb_platform_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index ad930688358c..55d22911d0c2 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -135,7 +135,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} #if defined(CONFIG_ARM_AT91_ETHER) || defined(CONFIG_ARM_AT91_ETHER_MODULE) static u64 eth_dmamask = DMA_BIT_MASK(32); -static struct at91_eth_data eth_data; +static struct macb_platform_data eth_data; static struct resource eth_resources[] = { [0] = { @@ -162,7 +162,7 @@ static struct platform_device at91rm9200_eth_device = { .num_resources = ARRAY_SIZE(eth_resources), }; -void __init at91_add_device_eth(struct at91_eth_data *data) +void __init at91_add_device_eth(struct macb_platform_data *data) { if (!data) return; @@ -199,7 +199,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data) platform_device_register(&at91rm9200_eth_device); } #else -void __init at91_add_device_eth(struct at91_eth_data *data) {} +void __init at91_add_device_eth(struct macb_platform_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 0d20677fbef0..1c945e3ba57c 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -120,7 +120,7 @@ static struct clk ohci_clk = { .type = CLK_TYPE_PERIPHERAL, }; static struct clk macb_clk = { - .name = "macb_clk", + .name = "pclk", .pmc_mask = 1 << AT91SAM9260_ID_EMAC, .type = CLK_TYPE_PERIPHERAL, }; @@ -190,6 +190,8 @@ static struct clk *periph_clocks[] __initdata = { }; static struct clk_lookup periph_clocks_lookups[] = { + /* One additional fake clock for macb_hclk */ + CLKDEV_CON_ID("hclk", &macb_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk), diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 629fa9774972..b1a4812d9965 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -136,7 +136,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) static u64 eth_dmamask = DMA_BIT_MASK(32); -static struct at91_eth_data eth_data; +static struct macb_platform_data eth_data; static struct resource eth_resources[] = { [0] = { @@ -163,7 +163,7 @@ static struct platform_device at91sam9260_eth_device = { .num_resources = ARRAY_SIZE(eth_resources), }; -void __init at91_add_device_eth(struct at91_eth_data *data) +void __init at91_add_device_eth(struct macb_platform_data *data) { if (!data) return; @@ -200,7 +200,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data) platform_device_register(&at91sam9260_eth_device); } #else -void __init at91_add_device_eth(struct at91_eth_data *data) {} +void __init at91_add_device_eth(struct macb_platform_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index f83fbb0ee0c5..182d112dc59d 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -118,7 +118,7 @@ static struct clk pwm_clk = { .type = CLK_TYPE_PERIPHERAL, }; static struct clk macb_clk = { - .name = "macb_clk", + .name = "pclk", .pmc_mask = 1 << AT91SAM9263_ID_EMAC, .type = CLK_TYPE_PERIPHERAL, }; @@ -182,6 +182,8 @@ static struct clk *periph_clocks[] __initdata = { }; static struct clk_lookup periph_clocks_lookups[] = { + /* One additional fake clock for macb_hclk */ + CLKDEV_CON_ID("hclk", &macb_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk), diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index d5fbac9ff4fa..183b5f17f55e 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -144,7 +144,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) static u64 eth_dmamask = DMA_BIT_MASK(32); -static struct at91_eth_data eth_data; +static struct macb_platform_data eth_data; static struct resource eth_resources[] = { [0] = { @@ -171,7 +171,7 @@ static struct platform_device at91sam9263_eth_device = { .num_resources = ARRAY_SIZE(eth_resources), }; -void __init at91_add_device_eth(struct at91_eth_data *data) +void __init at91_add_device_eth(struct macb_platform_data *data) { if (!data) return; @@ -208,7 +208,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data) platform_device_register(&at91sam9263_eth_device); } #else -void __init at91_add_device_eth(struct at91_eth_data *data) {} +void __init at91_add_device_eth(struct macb_platform_data *data) {} #endif diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 318b0407ea04..5a0e522ffa94 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c @@ -150,7 +150,7 @@ static struct clk ac97_clk = { .type = CLK_TYPE_PERIPHERAL, }; static struct clk macb_clk = { - .name = "macb_clk", + .name = "pclk", .pmc_mask = 1 << AT91SAM9G45_ID_EMAC, .type = CLK_TYPE_PERIPHERAL, }; @@ -209,6 +209,8 @@ static struct clk *periph_clocks[] __initdata = { }; static struct clk_lookup periph_clocks_lookups[] = { + /* One additional fake clock for macb_hclk */ + CLKDEV_CON_ID("hclk", &macb_clk), /* One additional fake clock for ohci */ CLKDEV_CON_ID("ohci_clk", &uhphs_clk), CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk), diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 09a16d6bd5cd..e2cb835c4d7c 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -284,7 +284,7 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {} #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) static u64 eth_dmamask = DMA_BIT_MASK(32); -static struct at91_eth_data eth_data; +static struct macb_platform_data eth_data; static struct resource eth_resources[] = { [0] = { @@ -311,7 +311,7 @@ static struct platform_device at91sam9g45_eth_device = { .num_resources = ARRAY_SIZE(eth_resources), }; -void __init at91_add_device_eth(struct at91_eth_data *data) +void __init at91_add_device_eth(struct macb_platform_data *data) { if (!data) return; @@ -348,7 +348,7 @@ void __init at91_add_device_eth(struct at91_eth_data *data) platform_device_register(&at91sam9g45_eth_device); } #else -void __init at91_add_device_eth(struct at91_eth_data *data) {} +void __init at91_add_device_eth(struct macb_platform_data *data) {} #endif diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c index 367d5cd5e362..a60d98d7c3e2 100644 --- a/arch/arm/mach-at91/board-1arm.c +++ b/arch/arm/mach-at91/board-1arm.c @@ -63,7 +63,7 @@ static void __init onearm_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata onearm_eth_data = { +static struct macb_platform_data __initdata onearm_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c index 4282d96dffa8..17fc77925707 100644 --- a/arch/arm/mach-at91/board-afeb-9260v1.c +++ b/arch/arm/mach-at91/board-afeb-9260v1.c @@ -103,7 +103,7 @@ static struct spi_board_info afeb9260_spi_devices[] = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata afeb9260_macb_data = { +static struct macb_platform_data __initdata afeb9260_macb_data = { .phy_irq_pin = AT91_PIN_PA9, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c index f90cfb32bad2..2037d2c40eb4 100644 --- a/arch/arm/mach-at91/board-cam60.c +++ b/arch/arm/mach-at91/board-cam60.c @@ -115,7 +115,7 @@ static struct spi_board_info cam60_spi_devices[] __initdata = { /* * MACB Ethernet device */ -static struct __initdata at91_eth_data cam60_macb_data = { +static struct __initdata macb_platform_data cam60_macb_data = { .phy_irq_pin = AT91_PIN_PB5, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c index 5dffd3be62d2..af5520c366fe 100644 --- a/arch/arm/mach-at91/board-cap9adk.c +++ b/arch/arm/mach-at91/board-cap9adk.c @@ -153,7 +153,7 @@ static struct at91_mmc_data __initdata cap9adk_mmc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata cap9adk_macb_data = { +static struct macb_platform_data __initdata cap9adk_macb_data = { .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c index 774c87fcbd5b..529b356cdb7d 100644 --- a/arch/arm/mach-at91/board-carmeva.c +++ b/arch/arm/mach-at91/board-carmeva.c @@ -57,7 +57,7 @@ static void __init carmeva_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata carmeva_eth_data = { +static struct macb_platform_data __initdata carmeva_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c index fc885a4ce243..04d2b9b50464 100644 --- a/arch/arm/mach-at91/board-cpu9krea.c +++ b/arch/arm/mach-at91/board-cpu9krea.c @@ -99,7 +99,7 @@ static struct at91_udc_data __initdata cpu9krea_udc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata cpu9krea_macb_data = { +static struct macb_platform_data __initdata cpu9krea_macb_data = { .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c index d35e65b08ccd..7a4c82e8da51 100644 --- a/arch/arm/mach-at91/board-cpuat91.c +++ b/arch/arm/mach-at91/board-cpuat91.c @@ -82,7 +82,7 @@ static void __init cpuat91_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata cpuat91_eth_data = { +static struct macb_platform_data __initdata cpuat91_eth_data = { .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index c3936665e645..b004b20b8e42 100644 --- a/arch/arm/mach-at91/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c @@ -58,7 +58,7 @@ static void __init csb337_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata csb337_eth_data = { +static struct macb_platform_data __initdata csb337_eth_data = { .phy_irq_pin = AT91_PIN_PC2, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c index 586100e2acbb..e966de5219c7 100644 --- a/arch/arm/mach-at91/board-csb637.c +++ b/arch/arm/mach-at91/board-csb637.c @@ -52,7 +52,7 @@ static void __init csb637_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata csb637_eth_data = { +static struct macb_platform_data __initdata csb637_eth_data = { .phy_irq_pin = AT91_PIN_PC0, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c index 45db7a3dbef0..3788fa527121 100644 --- a/arch/arm/mach-at91/board-eb9200.c +++ b/arch/arm/mach-at91/board-eb9200.c @@ -60,7 +60,7 @@ static void __init eb9200_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata eb9200_eth_data = { +static struct macb_platform_data __initdata eb9200_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c index 2f9c16d29212..af7622eae1a9 100644 --- a/arch/arm/mach-at91/board-ecbat91.c +++ b/arch/arm/mach-at91/board-ecbat91.c @@ -64,7 +64,7 @@ static void __init ecb_at91init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata ecb_at91eth_data = { +static struct macb_platform_data __initdata ecb_at91eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c index 8252c722607b..8e75867d1d18 100644 --- a/arch/arm/mach-at91/board-eco920.c +++ b/arch/arm/mach-at91/board-eco920.c @@ -47,7 +47,7 @@ static void __init eco920_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata eco920_eth_data = { +static struct macb_platform_data __initdata eco920_eth_data = { .phy_irq_pin = AT91_PIN_PC2, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c index f27d1a780cfa..de8e09642f4e 100644 --- a/arch/arm/mach-at91/board-foxg20.c +++ b/arch/arm/mach-at91/board-foxg20.c @@ -135,7 +135,7 @@ static struct spi_board_info foxg20_spi_devices[] = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata foxg20_macb_data = { +static struct macb_platform_data __initdata foxg20_macb_data = { .phy_irq_pin = AT91_PIN_PA7, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c index 2e95949737e6..51c82f151119 100644 --- a/arch/arm/mach-at91/board-gsia18s.c +++ b/arch/arm/mach-at91/board-gsia18s.c @@ -93,7 +93,7 @@ static struct at91_udc_data __initdata udc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata macb_data = { +static struct macb_platform_data __initdata macb_data = { .phy_irq_pin = AT91_PIN_PA28, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c index 3bae73e63633..9628a3defcf4 100644 --- a/arch/arm/mach-at91/board-kafa.c +++ b/arch/arm/mach-at91/board-kafa.c @@ -61,7 +61,7 @@ static void __init kafa_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata kafa_eth_data = { +static struct macb_platform_data __initdata kafa_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index e61351ffad50..5ba5244cb632 100644 --- a/arch/arm/mach-at91/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c @@ -69,7 +69,7 @@ static void __init kb9202_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata kb9202_eth_data = { +static struct macb_platform_data __initdata kb9202_eth_data = { .phy_irq_pin = AT91_PIN_PB29, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index ef816c17dc61..56e7aee11b59 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -155,7 +155,7 @@ static struct at91_mmc_data __initdata neocore926_mmc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata neocore926_macb_data = { +static struct macb_platform_data __initdata neocore926_macb_data = { .phy_irq_pin = AT91_PIN_PE31, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c index 49e3f699b48e..c545a3e635a4 100644 --- a/arch/arm/mach-at91/board-pcontrol-g20.c +++ b/arch/arm/mach-at91/board-pcontrol-g20.c @@ -122,7 +122,7 @@ static struct at91_udc_data __initdata pcontrol_g20_udc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata macb_data = { +static struct macb_platform_data __initdata macb_data = { .phy_irq_pin = AT91_PIN_PA28, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c index 0a8fe6a1b7c8..dc18759a24b4 100644 --- a/arch/arm/mach-at91/board-picotux200.c +++ b/arch/arm/mach-at91/board-picotux200.c @@ -60,7 +60,7 @@ static void __init picotux200_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata picotux200_eth_data = { +static struct macb_platform_data __initdata picotux200_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c index 07421bdb88ea..5444d6ac514a 100644 --- a/arch/arm/mach-at91/board-qil-a9260.c +++ b/arch/arm/mach-at91/board-qil-a9260.c @@ -104,7 +104,7 @@ static struct spi_board_info ek_spi_devices[] = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PA31, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c index 80a8c9c6e922..022d0cebda9d 100644 --- a/arch/arm/mach-at91/board-rm9200dk.c +++ b/arch/arm/mach-at91/board-rm9200dk.c @@ -65,7 +65,7 @@ static void __init dk_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata dk_eth_data = { +static struct macb_platform_data __initdata dk_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c index 99fd7f8aee0e..ed275861adef 100644 --- a/arch/arm/mach-at91/board-rm9200ek.c +++ b/arch/arm/mach-at91/board-rm9200ek.c @@ -65,7 +65,7 @@ static void __init ek_init_early(void) at91_set_serial_console(0); } -static struct at91_eth_data __initdata ek_eth_data = { +static struct macb_platform_data __initdata ek_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c index e927df0175df..ed3b21f77674 100644 --- a/arch/arm/mach-at91/board-rsi-ews.c +++ b/arch/arm/mach-at91/board-rsi-ews.c @@ -60,7 +60,7 @@ static void __init rsi_ews_init_early(void) /* * Ethernet */ -static struct at91_eth_data rsi_ews_eth_data __initdata = { +static struct macb_platform_data rsi_ews_eth_data __initdata = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c index 072d53af98d9..3e4b50e6f6ab 100644 --- a/arch/arm/mach-at91/board-sam9-l9260.c +++ b/arch/arm/mach-at91/board-sam9-l9260.c @@ -109,7 +109,7 @@ static struct spi_board_info ek_spi_devices[] = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PA7, .is_rmii = 0, }; diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index 4f10181a0782..13478e14a543 100644 --- a/arch/arm/mach-at91/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c @@ -151,7 +151,7 @@ static struct spi_board_info ek_spi_devices[] = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PA7, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index bccdcf23caa1..fcf194e6e4fe 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -158,7 +158,7 @@ static struct at91_mmc_data __initdata ek_mmc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PE31, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c index 64fc75c9d0ac..78d27cc3cc09 100644 --- a/arch/arm/mach-at91/board-sam9g20ek.c +++ b/arch/arm/mach-at91/board-sam9g20ek.c @@ -123,7 +123,7 @@ static struct spi_board_info ek_spi_devices[] = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PA7, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c index 92de9127923a..4e1ee9d87096 100644 --- a/arch/arm/mach-at91/board-sam9m10g45ek.c +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c @@ -115,7 +115,7 @@ static struct mci_platform_data __initdata mci1_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PD5, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c index 0df01c6e2d0c..fbec934a7ce9 100644 --- a/arch/arm/mach-at91/board-snapper9260.c +++ b/arch/arm/mach-at91/board-snapper9260.c @@ -65,7 +65,7 @@ static struct at91_udc_data __initdata snapper9260_udc_data = { .vbus_polled = 1, }; -static struct at91_eth_data snapper9260_macb_data = { +static struct macb_platform_data snapper9260_macb_data = { .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c index 936e5fd7f406..7c06c07d872b 100644 --- a/arch/arm/mach-at91/board-stamp9g20.c +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -157,7 +157,7 @@ static struct at91_udc_data __initdata stamp9g20evb_udc_data = { /* * MACB Ethernet device */ -static struct at91_eth_data __initdata macb_data = { +static struct macb_platform_data __initdata macb_data = { .phy_irq_pin = AT91_PIN_PA28, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c index 0a20bab21f99..3d84233f78eb 100644 --- a/arch/arm/mach-at91/board-usb-a926x.c +++ b/arch/arm/mach-at91/board-usb-a926x.c @@ -146,7 +146,7 @@ static void __init ek_add_device_spi(void) /* * MACB Ethernet device */ -static struct at91_eth_data __initdata ek_macb_data = { +static struct macb_platform_data __initdata ek_macb_data = { .phy_irq_pin = AT91_PIN_PE31, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c index 12a3f955162b..2c40a21b2794 100644 --- a/arch/arm/mach-at91/board-yl-9200.c +++ b/arch/arm/mach-at91/board-yl-9200.c @@ -110,7 +110,7 @@ static struct gpio_led yl9200_leds[] = { /* * Ethernet */ -static struct at91_eth_data __initdata yl9200_eth_data = { +static struct macb_platform_data __initdata yl9200_eth_data = { .phy_irq_pin = AT91_PIN_PB28, .is_rmii = 1, }; diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index eac92e995bb5..e209a2992245 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -40,6 +40,7 @@ #include <linux/atmel-mci.h> #include <sound/atmel-ac97c.h> #include <linux/serial.h> +#include <linux/platform_data/macb.h> /* USB Device */ struct at91_udc_data { @@ -81,18 +82,7 @@ extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) /* atmel-mci platform config */ extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data); - /* Ethernet (EMAC & MACB) */ -struct at91_eth_data { - u32 phy_mask; - u8 phy_irq_pin; /* PHY IRQ */ - u8 is_rmii; /* using RMII interface? */ -}; -extern void __init at91_add_device_eth(struct at91_eth_data *data); - -#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91CAP9) \ - || defined(CONFIG_ARCH_AT91SAM9G45) -#define eth_platform_data at91_eth_data -#endif +extern void __init at91_add_device_eth(struct macb_platform_data *data); /* USB Host */ struct at91_usbh_data { diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 724ec0f3560d..4e36e8f4e157 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -57,6 +57,11 @@ config EXYNOS4_MCT help Use MCT (Multi Core Timer) as kernel timers +config EXYNOS4_DEV_DMA + bool + help + Compile in amba device definitions for DMA controller + config EXYNOS4_DEV_AHCI bool help @@ -82,6 +87,11 @@ config EXYNOS4_DEV_DWMCI help Compile in platform device definitions for DWMCI +config EXYNOS4_DEV_USB_OHCI + bool + help + Compile in platform device definition for USB OHCI + config EXYNOS4_SETUP_I2C1 bool help @@ -143,6 +153,11 @@ config EXYNOS4_SETUP_USB_PHY help Common setup code for USB PHY controller +config EXYNOS4_SETUP_SPI + bool + help + Common setup code for SPI GPIO configurations. + # machine support if ARCH_EXYNOS4 @@ -177,8 +192,10 @@ 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 select EXYNOS4_DEV_SYSMMU select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_I2C1 @@ -197,6 +214,7 @@ config MACH_ARMLEX4210 select S3C_DEV_HSMMC2 select S3C_DEV_HSMMC3 select EXYNOS4_DEV_AHCI + select EXYNOS4_DEV_DMA select EXYNOS4_DEV_SYSMMU select EXYNOS4_SETUP_SDHCI help @@ -222,6 +240,7 @@ config MACH_UNIVERSAL_C210 select S5P_DEV_MFC select S5P_DEV_ONENAND select S5P_DEV_TV + select EXYNOS4_DEV_DMA select EXYNOS4_DEV_PD select EXYNOS4_SETUP_FIMD0 select EXYNOS4_SETUP_I2C1 @@ -255,6 +274,7 @@ config MACH_NURI select S5P_DEV_MFC select S5P_DEV_USB_EHCI select S5P_SETUP_MIPIPHY + select EXYNOS4_DEV_DMA select EXYNOS4_DEV_PD select EXYNOS4_SETUP_FIMC select EXYNOS4_SETUP_FIMD0 @@ -287,7 +307,9 @@ 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 select EXYNOS4_SETUP_SDHCI select EXYNOS4_SETUP_USB_PHY @@ -327,6 +349,20 @@ config MACH_SMDK4412 Machine support for Samsung SMDK4412 endif +comment "Flattened Device Tree based board for Exynos4 based SoC" + +config MACH_EXYNOS4_DT + bool "Samsung Exynos4 Machine using device tree" + select CPU_EXYNOS4210 + select USE_OF + select ARM_AMBA + select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD + help + Machine support for Samsung Exynos4 machine with device tree enabled. + Select this if a fdt blob is available for the Exynos4 SoC based board. + Note: This is under development and not all peripherals can be supported + with this machine file. + if ARCH_EXYNOS4 comment "Configuration for HSMMC 8-bit bus width" diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index 59069a35e40b..db527ab4759c 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -13,7 +13,7 @@ obj- := # Core support for EXYNOS4 system obj-$(CONFIG_ARCH_EXYNOS4) += cpu.o init.o clock.o irq-combiner.o setup-i2c0.o -obj-$(CONFIG_ARCH_EXYNOS4) += irq-eint.o dma.o pmu.o +obj-$(CONFIG_ARCH_EXYNOS4) += irq-eint.o pmu.o obj-$(CONFIG_CPU_EXYNOS4210) += clock-exynos4210.o obj-$(CONFIG_SOC_EXYNOS4212) += clock-exynos4212.o obj-$(CONFIG_PM) += pm.o @@ -37,6 +37,8 @@ obj-$(CONFIG_MACH_ORIGEN) += mach-origen.o obj-$(CONFIG_MACH_SMDK4212) += mach-smdk4x12.o obj-$(CONFIG_MACH_SMDK4412) += mach-smdk4x12.o +obj-$(CONFIG_MACH_EXYNOS4_DT) += mach-exynos4-dt.o + # device support obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o @@ -44,6 +46,8 @@ 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 obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o @@ -55,6 +59,6 @@ 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 +obj-$(CONFIG_EXYNOS4_SETUP_SPI) += setup-spi.o diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c index 2894f0adef5c..da50b1af7568 100644 --- a/arch/arm/mach-exynos/clock.c +++ b/arch/arm/mach-exynos/clock.c @@ -553,16 +553,6 @@ static struct clk init_clocks_off[] = { .enable = exynos4_clk_dac_ctrl, .ctrlbit = (1 << 0), }, { - .name = "dma", - .devname = "dma-pl330.0", - .enable = exynos4_clk_ip_fsys_ctrl, - .ctrlbit = (1 << 0), - }, { - .name = "dma", - .devname = "dma-pl330.1", - .enable = exynos4_clk_ip_fsys_ctrl, - .ctrlbit = (1 << 1), - }, { .name = "adc", .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 15), @@ -778,6 +768,20 @@ static struct clk init_clocks[] = { } }; +static struct clk clk_pdma0 = { + .name = "dma", + .devname = "dma-pl330.0", + .enable = exynos4_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 0), +}; + +static struct clk clk_pdma1 = { + .name = "dma", + .devname = "dma-pl330.1", + .enable = exynos4_clk_ip_fsys_ctrl, + .ctrlbit = (1 << 1), +}; + struct clk *clkset_group_list[] = { [0] = &clk_ext_xtal_mux, [1] = &clk_xusbxti, @@ -1009,46 +1013,6 @@ static struct clksrc_clk clk_dout_mmc4 = { static struct clksrc_clk clksrcs[] = { { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.0", - .enable = exynos4_clksrc_mask_peril0_ctrl, - .ctrlbit = (1 << 0), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.1", - .enable = exynos4_clksrc_mask_peril0_ctrl, - .ctrlbit = (1 << 4), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.2", - .enable = exynos4_clksrc_mask_peril0_ctrl, - .ctrlbit = (1 << 8), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.3", - .enable = exynos4_clksrc_mask_peril0_ctrl, - .ctrlbit = (1 << 12), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 }, - }, { .clk = { .name = "sclk_pwm", .enable = exynos4_clksrc_mask_peril0_ctrl, @@ -1147,36 +1111,6 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 }, }, { .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.0", - .enable = exynos4_clksrc_mask_peril1_ctrl, - .ctrlbit = (1 << 16), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.1", - .enable = exynos4_clksrc_mask_peril1_ctrl, - .ctrlbit = (1 << 20), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "sclk_spi", - .devname = "s3c64xx-spi.2", - .enable = exynos4_clksrc_mask_peril1_ctrl, - .ctrlbit = (1 << 24), - }, - .sources = &clkset_group, - .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 }, - .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 }, - }, { - .clk = { .name = "sclk_fimg2d", }, .sources = &clkset_mout_g2d, @@ -1192,42 +1126,6 @@ static struct clksrc_clk clksrcs[] = { .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", .parent = &clk_dout_mmc4.clk, .enable = exynos4_clksrc_mask_fsys_ctrl, @@ -1237,6 +1135,134 @@ 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 }, +}; + +static struct clksrc_clk clk_sclk_spi0 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.0", + .enable = exynos4_clksrc_mask_peril1_ctrl, + .ctrlbit = (1 << 16), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi1 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.1", + .enable = exynos4_clksrc_mask_peril1_ctrl, + .ctrlbit = (1 << 20), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_spi2 = { + .clk = { + .name = "sclk_spi", + .devname = "s3c64xx-spi.2", + .enable = exynos4_clksrc_mask_peril1_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_group, + .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 }, + .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 }, +}; + /* Clock initialization code */ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, @@ -1271,6 +1297,42 @@ 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, + &clk_sclk_spi0, + &clk_sclk_spi1, + &clk_sclk_spi2, + +}; + +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), + CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &clk_sclk_spi0.clk), + CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &clk_sclk_spi1.clk), + CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &clk_sclk_spi2.clk), +}; + static int xtal_rate; static unsigned long exynos4_fout_apll_get_rate(struct clk *clk) @@ -1478,11 +1540,19 @@ void __init exynos4_register_clocks(void) for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++) s3c_register_clksrc(sclk_tv[ptr], 1); + for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++) + s3c_register_clksrc(clksrc_cdev[ptr], 1); + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev)); + for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++) + s3c_disable_clocks(clk_cdev[ptr], 1); + s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup)); register_syscore_ops(&exynos4_clock_syscore_ops); s3c24xx_register_clock(&dummy_apb_pclk); diff --git a/arch/arm/mach-exynos/cpu.c b/arch/arm/mach-exynos/cpu.c index 90ec247f3b37..0eb7b6a6903d 100644 --- a/arch/arm/mach-exynos/cpu.c +++ b/arch/arm/mach-exynos/cpu.c @@ -10,6 +10,8 @@ #include <linux/sched.h> #include <linux/sysdev.h> +#include <linux/of.h> +#include <linux/of_irq.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> @@ -218,13 +220,26 @@ static void exynos4_gic_irq_fix_base(struct irq_data *d) (gic_bank_offset * smp_processor_id()); } +#ifdef CONFIG_OF +static const struct of_device_id exynos4_dt_irq_match[] = { + { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, + {}, +}; +#endif + void __init exynos4_init_irq(void) { int irq; gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000; - gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); + if (!of_have_populated_dt()) + gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); +#ifdef CONFIG_OF + else + of_irq_init(exynos4_dt_irq_match); +#endif + gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base; gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base; gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base; diff --git a/arch/arm/mach-exynos/dev-ohci.c b/arch/arm/mach-exynos/dev-ohci.c new file mode 100644 index 000000000000..b8e75300c77d --- /dev/null +++ b/arch/arm/mach-exynos/dev-ohci.c @@ -0,0 +1,52 @@ +/* linux/arch/arm/mach-exynos/dev-ohci.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * EXYNOS - OHCI support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> + +#include <mach/irqs.h> +#include <mach/map.h> +#include <mach/ohci.h> + +#include <plat/devs.h> +#include <plat/usb-phy.h> + +static struct resource exynos4_ohci_resource[] = { + [0] = DEFINE_RES_MEM(EXYNOS4_PA_OHCI, SZ_256), + [1] = DEFINE_RES_IRQ(IRQ_USB_HOST), +}; + +static u64 exynos4_ohci_dma_mask = DMA_BIT_MASK(32); + +struct platform_device exynos4_device_ohci = { + .name = "exynos-ohci", + .id = -1, + .num_resources = ARRAY_SIZE(exynos4_ohci_resource), + .resource = exynos4_ohci_resource, + .dev = { + .dma_mask = &exynos4_ohci_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + } +}; + +void __init exynos4_ohci_set_platdata(struct exynos4_ohci_platdata *pd) +{ + struct exynos4_ohci_platdata *npd; + + npd = s3c_set_platdata(pd, sizeof(struct exynos4_ohci_platdata), + &exynos4_device_ohci); + + if (!npd->phy_init) + npd->phy_init = s5p_usb_phy_init; + if (!npd->phy_exit) + npd->phy_exit = s5p_usb_phy_exit; +} diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c index 9667c61e64fb..b10fcd270f07 100644 --- a/arch/arm/mach-exynos/dma.c +++ b/arch/arm/mach-exynos/dma.c @@ -24,6 +24,7 @@ #include <linux/dma-mapping.h> #include <linux/amba/bus.h> #include <linux/amba/pl330.h> +#include <linux/of.h> #include <asm/irq.h> #include <plat/devs.h> @@ -35,95 +36,42 @@ static u64 dma_dmamask = DMA_BIT_MASK(32); -struct dma_pl330_peri pdma0_peri[28] = { - { - .peri_id = (u8)DMACH_PCM0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MSM_REQ0, - }, { - .peri_id = (u8)DMACH_MSM_REQ2, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0S_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART4_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART4_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SLIMBUS0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SLIMBUS0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SLIMBUS2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SLIMBUS2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SLIMBUS4_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SLIMBUS4_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_AC97_MICIN, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_AC97_PCMIN, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_AC97_PCMOUT, - .rqtype = MEMTODEV, - }, +u8 pdma0_peri[] = { + DMACH_PCM0_RX, + DMACH_PCM0_TX, + DMACH_PCM2_RX, + DMACH_PCM2_TX, + DMACH_MSM_REQ0, + DMACH_MSM_REQ2, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI2_RX, + DMACH_SPI2_TX, + DMACH_I2S0S_TX, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S2_RX, + DMACH_I2S2_TX, + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART4_RX, + DMACH_UART4_TX, + DMACH_SLIMBUS0_RX, + DMACH_SLIMBUS0_TX, + DMACH_SLIMBUS2_RX, + DMACH_SLIMBUS2_TX, + DMACH_SLIMBUS4_RX, + DMACH_SLIMBUS4_TX, + DMACH_AC97_MICIN, + DMACH_AC97_PCMIN, + DMACH_AC97_PCMOUT, }; struct dma_pl330_platdata exynos4_pdma0_pdata = { .nr_valid_peri = ARRAY_SIZE(pdma0_peri), - .peri = pdma0_peri, + .peri_id = pdma0_peri, }; struct amba_device exynos4_device_pdma0 = { @@ -142,86 +90,37 @@ struct amba_device exynos4_device_pdma0 = { .periphid = 0x00041330, }; -struct dma_pl330_peri pdma1_peri[25] = { - { - .peri_id = (u8)DMACH_PCM0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MSM_REQ1, - }, { - .peri_id = (u8)DMACH_MSM_REQ3, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0S_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SLIMBUS1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SLIMBUS1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SLIMBUS3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SLIMBUS3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SLIMBUS5_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SLIMBUS5_TX, - .rqtype = MEMTODEV, - }, +u8 pdma1_peri[] = { + DMACH_PCM0_RX, + DMACH_PCM0_TX, + DMACH_PCM1_RX, + DMACH_PCM1_TX, + DMACH_MSM_REQ1, + DMACH_MSM_REQ3, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_I2S0S_TX, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_SLIMBUS1_RX, + DMACH_SLIMBUS1_TX, + DMACH_SLIMBUS3_RX, + DMACH_SLIMBUS3_TX, + DMACH_SLIMBUS5_RX, + DMACH_SLIMBUS5_TX, }; struct dma_pl330_platdata exynos4_pdma1_pdata = { .nr_valid_peri = ARRAY_SIZE(pdma1_peri), - .peri = pdma1_peri, + .peri_id = pdma1_peri, }; struct amba_device exynos4_device_pdma1 = { @@ -242,7 +141,15 @@ struct amba_device exynos4_device_pdma1 = { static int __init exynos4_dma_init(void) { + if (of_have_populated_dt()) + return 0; + + dma_cap_set(DMA_SLAVE, exynos4_pdma0_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, exynos4_pdma0_pdata.cap_mask); amba_device_register(&exynos4_device_pdma0, &iomem_resource); + + dma_cap_set(DMA_SLAVE, exynos4_pdma1_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, exynos4_pdma1_pdata.cap_mask); amba_device_register(&exynos4_device_pdma1, &iomem_resource); return 0; diff --git a/arch/arm/mach-exynos/include/mach/entry-macro.S b/arch/arm/mach-exynos/include/mach/entry-macro.S index f5e9fd8e37b4..d7dfcd7eb921 100644 --- a/arch/arm/mach-exynos/include/mach/entry-macro.S +++ b/arch/arm/mach-exynos/include/mach/entry-macro.S @@ -72,7 +72,6 @@ cmpcc \irqnr, \irqnr cmpne \irqnr, \tmp cmpcs \irqnr, \irqnr - addne \irqnr, \irqnr, #32 .endm diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index dfd4b7eecb90..f77bce04789a 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -17,13 +17,13 @@ /* PPI: Private Peripheral Interrupt */ -#define IRQ_PPI(x) S5P_IRQ(x+16) +#define IRQ_PPI(x) (x+16) #define IRQ_MCT_LOCALTIMER IRQ_PPI(12) /* SPI: Shared Peripheral Interrupt */ -#define IRQ_SPI(x) S5P_IRQ(x+32) +#define IRQ_SPI(x) (x+32) #define IRQ_EINT0 IRQ_SPI(16) #define IRQ_EINT1 IRQ_SPI(17) @@ -72,6 +72,9 @@ #define IRQ_IIC5 IRQ_SPI(63) #define IRQ_IIC6 IRQ_SPI(64) #define IRQ_IIC7 IRQ_SPI(65) +#define IRQ_SPI0 IRQ_SPI(66) +#define IRQ_SPI1 IRQ_SPI(67) +#define IRQ_SPI2 IRQ_SPI(68) #define IRQ_USB_HOST IRQ_SPI(70) #define IRQ_USB_HSOTG IRQ_SPI(71) @@ -163,7 +166,9 @@ #define IRQ_GPIO2_NR_GROUPS 9 #define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT) +#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64) + /* Set the default NR_IRQS */ -#define NR_IRQS (IRQ_GPIO_END + 64) +#define NR_IRQS (IRQ_TIMER_BASE + IRQ_TIMER_COUNT) #endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 058541d45af0..05ff18706776 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -87,6 +87,10 @@ #define EXYNOS4_PA_SYSMMU_TV 0x12E20000 #define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000 #define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000 +#define EXYNOS4_PA_SPI0 0x13920000 +#define EXYNOS4_PA_SPI1 0x13930000 +#define EXYNOS4_PA_SPI2 0x13940000 + #define EXYNOS4_PA_GPIO1 0x11400000 #define EXYNOS4_PA_GPIO2 0x11000000 @@ -107,6 +111,7 @@ #define EXYNOS4_PA_SROMC 0x12570000 #define EXYNOS4_PA_EHCI 0x12580000 +#define EXYNOS4_PA_OHCI 0x12590000 #define EXYNOS4_PA_HSPHY 0x125B0000 #define EXYNOS4_PA_MFC 0x13400000 @@ -148,6 +153,9 @@ #define S3C_PA_RTC EXYNOS4_PA_RTC #define S3C_PA_WDT EXYNOS4_PA_WATCHDOG #define S3C_PA_UART EXYNOS4_PA_UART +#define S3C_PA_SPI0 EXYNOS4_PA_SPI0 +#define S3C_PA_SPI1 EXYNOS4_PA_SPI1 +#define S3C_PA_SPI2 EXYNOS4_PA_SPI2 #define S5P_PA_CHIPID EXYNOS4_PA_CHIPID #define S5P_PA_EHCI EXYNOS4_PA_EHCI diff --git a/arch/arm/mach-exynos/include/mach/ohci.h b/arch/arm/mach-exynos/include/mach/ohci.h new file mode 100644 index 000000000000..c256c595be5e --- /dev/null +++ b/arch/arm/mach-exynos/include/mach/ohci.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2011 Samsung Electronics Co.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 as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __MACH_EXYNOS_OHCI_H +#define __MACH_EXYNOS_OHCI_H + +struct exynos4_ohci_platdata { + int (*phy_init)(struct platform_device *pdev, int type); + int (*phy_exit)(struct platform_device *pdev, int type); +}; + +extern void exynos4_ohci_set_platdata(struct exynos4_ohci_platdata *pd); + +#endif /* __MACH_EXYNOS_OHCI_H */ diff --git a/arch/arm/mach-exynos/include/mach/spi-clocks.h b/arch/arm/mach-exynos/include/mach/spi-clocks.h new file mode 100644 index 000000000000..576efdf6d091 --- /dev/null +++ b/arch/arm/mach-exynos/include/mach/spi-clocks.h @@ -0,0 +1,16 @@ +/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h + * + * Copyright (C) 2011 Samsung Electronics Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_SPI_CLKS_H +#define __ASM_ARCH_SPI_CLKS_H __FILE__ + +/* Must source from SCLK_SPI */ +#define EXYNOS4_SPI_SRCCLK_SCLK 0 + +#endif /* __ASM_ARCH_SPI_CLKS_H */ diff --git a/arch/arm/mach-exynos/init.c b/arch/arm/mach-exynos/init.c index a8a83e3881a4..5b35978029be 100644 --- a/arch/arm/mach-exynos/init.c +++ b/arch/arm/mach-exynos/init.c @@ -14,29 +14,14 @@ #include <plat/devs.h> #include <plat/regs-serial.h> -static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = { - [0] = { - .name = "uclk1", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, -}; - /* uart registration process */ void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) { struct s3c2410_uartcfg *tcfg = cfg; u32 ucnt; - for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { - if (!tcfg->clocks) { - tcfg->has_fracval = 1; - tcfg->clocks = exynos4_serial_clocks; - tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks); - } - tcfg->flags |= NO_NEED_CHECK_CLKSRC; - } + for (ucnt = 0; ucnt < no; ucnt++, tcfg++) + tcfg->has_fracval = 1; - s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no); + s3c24xx_init_uartdevs("exynos4210-uart", s5p_uart_resources, cfg, no); } diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c new file mode 100644 index 000000000000..85fa02767d67 --- /dev/null +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -0,0 +1,85 @@ +/* + * Samsung's Exynos4210 flattened device tree enabled machine + * + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2010-2011 Linaro Ltd. + * www.linaro.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/of_platform.h> +#include <linux/serial_core.h> + +#include <asm/mach/arch.h> +#include <mach/map.h> + +#include <plat/cpu.h> +#include <plat/regs-serial.h> +#include <plat/exynos4.h> + +/* + * The following lookup table is used to override device names when devices + * are registered from device tree. This is temporarily added to enable + * device tree support addition for the Exynos4 architecture. + * + * For drivers that require platform data to be provided from the machine + * file, a platform data pointer can also be supplied along with the + * devices names. Usually, the platform data elements that cannot be parsed + * from the device tree by the drivers (example: function pointers) are + * supplied. But it should be noted that this is a temporary mechanism and + * at some point, the drivers should be capable of parsing all the platform + * data from the device tree. + */ +static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART0, + "exynos4210-uart.0", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART1, + "exynos4210-uart.1", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART2, + "exynos4210-uart.2", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-uart", S5P_PA_UART3, + "exynos4210-uart.3", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(0), + "exynos4-sdhci.0", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(1), + "exynos4-sdhci.1", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(2), + "exynos4-sdhci.2", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(3), + "exynos4-sdhci.3", NULL), + OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0), + "s3c2440-i2c.0", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL), + OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL), + {}, +}; + +static void __init exynos4210_dt_map_io(void) +{ + s5p_init_io(NULL, 0, S5P_VA_CHIPID); + s3c24xx_init_clocks(24000000); +} + +static void __init exynos4210_dt_machine_init(void) +{ + of_platform_populate(NULL, of_default_bus_match_table, + exynos4210_auxdata_lookup, NULL); +} + +static char const *exynos4210_dt_compat[] __initdata = { + "samsung,exynos4210", + NULL +}; + +DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") + /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */ + .init_irq = exynos4_init_irq, + .map_io = exynos4210_dt_map_io, + .init_machine = exynos4210_dt_machine_init, + .timer = &exynos4_timer, + .dt_compat = exynos4210_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index f80b563f2be7..b805e595cc35 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -41,6 +41,7 @@ #include <plat/fb.h> #include <plat/mfc.h> +#include <mach/ohci.h> #include <mach/map.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ @@ -483,6 +484,16 @@ static void __init origen_ehci_init(void) s5p_ehci_set_platdata(pdata); } +/* USB OHCI */ +static struct exynos4_ohci_platdata origen_ohci_pdata; + +static void __init origen_ohci_init(void) +{ + struct exynos4_ohci_platdata *pdata = &origen_ohci_pdata; + + exynos4_ohci_set_platdata(pdata); +} + static struct gpio_keys_button origen_gpio_keys_table[] = { { .code = KEY_MENU, @@ -606,6 +617,7 @@ static struct platform_device *origen_devices[] __initdata = { &s5p_device_mfc_l, &s5p_device_mfc_r, &s5p_device_mixer, + &exynos4_device_ohci, &exynos4_device_pd[PD_LCD0], &exynos4_device_pd[PD_TV], &exynos4_device_pd[PD_G3D], @@ -670,6 +682,7 @@ static void __init origen_machine_init(void) s3c_sdhci0_set_platdata(&origen_hsmmc0_pdata); origen_ehci_init(); + origen_ohci_init(); clk_xusbxti.rate = 24000000; s5p_tv_setup(); diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c index cec2afabe7b4..25a5a405c4bf 100644 --- a/arch/arm/mach-exynos/mach-smdkv310.c +++ b/arch/arm/mach-exynos/mach-smdkv310.c @@ -42,6 +42,7 @@ #include <plat/clock.h> #include <mach/map.h> +#include <mach/ohci.h> /* Following are default values for UCON, ULCON and UFCON UART registers */ #define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ @@ -245,6 +246,16 @@ static void __init smdkv310_ehci_init(void) s5p_ehci_set_platdata(pdata); } +/* USB OHCI */ +static struct exynos4_ohci_platdata smdkv310_ohci_pdata; + +static void __init smdkv310_ohci_init(void) +{ + struct exynos4_ohci_platdata *pdata = &smdkv310_ohci_pdata; + + exynos4_ohci_set_platdata(pdata); +} + static struct platform_device *smdkv310_devices[] __initdata = { &s3c_device_hsmmc0, &s3c_device_hsmmc1, @@ -261,6 +272,7 @@ static struct platform_device *smdkv310_devices[] __initdata = { &s5p_device_fimc3, &exynos4_device_ac97, &exynos4_device_i2s0, + &exynos4_device_ohci, &samsung_device_keypad, &s5p_device_mfc, &s5p_device_mfc_l, @@ -363,6 +375,7 @@ static void __init smdkv310_machine_init(void) s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata); smdkv310_ehci_init(); + smdkv310_ohci_init(); clk_xusbxti.rate = 24000000; platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices)); diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 97343df8f132..85b5527d0918 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -44,8 +44,6 @@ struct mct_clock_event_device { char name[10]; }; -static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); - static void exynos4_mct_write(unsigned int value, void *addr) { void __iomem *stat_addr; @@ -264,6 +262,9 @@ static void exynos4_clockevent_init(void) } #ifdef CONFIG_LOCAL_TIMERS + +static DEFINE_PER_CPU(struct mct_clock_event_device, percpu_mct_tick); + /* Clock event handling */ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt) { @@ -428,9 +429,13 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt) void local_timer_stop(struct clock_event_device *evt) { + unsigned int cpu = smp_processor_id(); evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); if (mct_int_type == MCT_INT_SPI) - disable_irq(evt->irq); + if (cpu == 0) + remove_irq(evt->irq, &mct_tick0_event_irq); + else + remove_irq(evt->irq, &mct_tick1_event_irq); else disable_percpu_irq(IRQ_MCT_LOCALTIMER); } @@ -443,6 +448,7 @@ static void __init exynos4_timer_resources(void) clk_rate = clk_get_rate(mct_clk); +#ifdef CONFIG_LOCAL_TIMERS if (mct_int_type == MCT_INT_PPI) { int err; @@ -452,6 +458,7 @@ static void __init exynos4_timer_resources(void) WARN(err, "MCT: can't request IRQ %d (%d)\n", IRQ_MCT_LOCALTIMER, err); } +#endif /* CONFIG_LOCAL_TIMERS */ } static void __init exynos4_timer_init(void) diff --git a/arch/arm/mach-exynos/setup-sdhci.c b/arch/arm/mach-exynos/setup-sdhci.c deleted file mode 100644 index 92937b410906..000000000000 --- a/arch/arm/mach-exynos/setup-sdhci.c +++ /dev/null @@ -1,22 +0,0 @@ -/* 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, -}; diff --git a/arch/arm/mach-exynos/setup-spi.c b/arch/arm/mach-exynos/setup-spi.c new file mode 100644 index 000000000000..833ff40ee0e8 --- /dev/null +++ b/arch/arm/mach-exynos/setup-spi.c @@ -0,0 +1,72 @@ +/* linux/arch/arm/mach-exynos4/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 = 0x1ff, + .rx_lvl_offset = 15, + .high_speed = 1, + .clk_from_cmu = true, + .tx_st_done = 25, +}; + +int s3c64xx_spi0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(EXYNOS4_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 __initdata = { + .fifo_lvl_mask = 0x7f, + .rx_lvl_offset = 15, + .high_speed = 1, + .clk_from_cmu = true, + .tx_st_done = 25, +}; + +int s3c64xx_spi1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2, + 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 = 15, + .high_speed = 1, + .clk_from_cmu = true, + .tx_st_done = 25, +}; + +int s3c64xx_spi2_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5)); + s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP); + s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2, + S3C_GPIO_SFN(5), S3C_GPIO_PULL_UP); + return 0; +} +#endif diff --git a/arch/arm/mach-exynos/setup-usb-phy.c b/arch/arm/mach-exynos/setup-usb-phy.c index 39aca045f660..41743d21e8c6 100644 --- a/arch/arm/mach-exynos/setup-usb-phy.c +++ b/arch/arm/mach-exynos/setup-usb-phy.c @@ -19,6 +19,13 @@ #include <plat/cpu.h> #include <plat/usb-phy.h> +static atomic_t host_usage; + +static int exynos4_usb_host_phy_is_on(void) +{ + return (readl(EXYNOS4_PHYPWR) & PHY1_STD_ANALOG_POWERDOWN) ? 0 : 1; +} + static int exynos4_usb_phy1_init(struct platform_device *pdev) { struct clk *otg_clk; @@ -27,6 +34,8 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev) u32 rstcon; int err; + atomic_inc(&host_usage); + otg_clk = clk_get(&pdev->dev, "otg"); if (IS_ERR(otg_clk)) { dev_err(&pdev->dev, "Failed to get otg clock\n"); @@ -39,6 +48,9 @@ static int exynos4_usb_phy1_init(struct platform_device *pdev) return err; } + if (exynos4_usb_host_phy_is_on()) + return 0; + writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE, S5P_USBHOST_PHY_CONTROL); @@ -95,6 +107,9 @@ static int exynos4_usb_phy1_exit(struct platform_device *pdev) struct clk *otg_clk; int err; + if (atomic_dec_return(&host_usage) > 0) + return 0; + otg_clk = clk_get(&pdev->dev, "otg"); if (IS_ERR(otg_clk)) { dev_err(&pdev->dev, "Failed to get otg clock\n"); diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 7a60bbbce7a4..f0d236dfb02b 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -120,8 +120,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(27), - .end = gpio_to_irq(27), + .start = MMP_GPIO_TO_IRQ(27), + .end = MMP_GPIO_TO_IRQ(27), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; @@ -232,6 +232,7 @@ static void __init common_init(void) pxa168_add_nand(&aspenite_nand_info); pxa168_add_fb(&aspenite_lcd_info); pxa168_add_keypad(&aspenite_keypad_info); + platform_device_register(&pxa168_device_gpio); /* off-chip devices */ platform_device_register(&smc91x_device); diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c index 39f0878d64a0..c5d53e0742e9 100644 --- a/arch/arm/mach-mmp/avengers_lite.c +++ b/arch/arm/mach-mmp/avengers_lite.c @@ -38,6 +38,7 @@ static void __init avengers_lite_init(void) /* on-chip devices */ pxa168_add_uart(2); + platform_device_register(&pxa168_device_gpio); } MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform") diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index 983cfb15fbde..eb07565a06a3 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -202,6 +202,7 @@ static void __init brownstone_init(void) /* on-chip devices */ mmp2_add_uart(1); mmp2_add_uart(3); + platform_device_register(&mmp2_device_gpio); mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info)); mmp2_add_sdhost(0, &mmp2_sdh_platdata_mmc0); /* SD/MMC */ mmp2_add_sdhost(2, &mmp2_sdh_platdata_mmc2); /* eMMC */ diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c index c4fd806b15b4..c1f0aa88dd8a 100644 --- a/arch/arm/mach-mmp/flint.c +++ b/arch/arm/mach-mmp/flint.c @@ -87,8 +87,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(155), - .end = gpio_to_irq(155), + .start = MMP_GPIO_TO_IRQ(155), + .end = MMP_GPIO_TO_IRQ(155), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; @@ -110,6 +110,7 @@ static void __init flint_init(void) /* on-chip devices */ mmp2_add_uart(1); mmp2_add_uart(2); + platform_device_register(&mmp2_device_gpio); /* off-chip devices */ platform_device_register(&smc91x_device); diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c index 4665767a4f79..e266f66a4670 100644 --- a/arch/arm/mach-mmp/gplugd.c +++ b/arch/arm/mach-mmp/gplugd.c @@ -184,6 +184,7 @@ static void __init gplugd_init(void) pxa168_add_uart(3); pxa168_add_ssp(1); pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info)); + platform_device_register(&pxa168_device_gpio); pxa168_add_eth(&gplugd_eth_platform_data); } diff --git a/arch/arm/mach-mmp/include/mach/gpio-pxa.h b/arch/arm/mach-mmp/include/mach/gpio-pxa.h index 99b4ce1b6562..0e135a599f3e 100644 --- a/arch/arm/mach-mmp/include/mach/gpio-pxa.h +++ b/arch/arm/mach-mmp/include/mach/gpio-pxa.h @@ -2,6 +2,7 @@ #define __ASM_MACH_GPIO_PXA_H #include <mach/addr-map.h> +#include <mach/cputype.h> #include <mach/irqs.h> #define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000) @@ -9,8 +10,6 @@ #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) #define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) -#define NR_BUILTIN_GPIO IRQ_GPIO_NUM - #define gpio_to_bank(gpio) ((gpio) >> 5) /* NOTE: these macros are defined here to make optimization of diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h index 681262359d1c..13219ebf5128 100644 --- a/arch/arm/mach-mmp/include/mach/gpio.h +++ b/arch/arm/mach-mmp/include/mach/gpio.h @@ -3,11 +3,6 @@ #include <asm-generic/gpio.h> -#define gpio_to_irq(gpio) (IRQ_GPIO_START + (gpio)) -#define irq_to_gpio(irq) ((irq) - IRQ_GPIO_START) +#include <mach/cputype.h> -#define __gpio_is_inverted(gpio) (0) -#define __gpio_is_occupied(gpio) (0) - -#include <plat/gpio.h> #endif /* __ASM_MACH_GPIO_H */ diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h index a09d328e2ddd..34635a0bbb59 100644 --- a/arch/arm/mach-mmp/include/mach/irqs.h +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -219,10 +219,10 @@ #define IRQ_MMP2_MUX_END (IRQ_MMP2_SSP_BASE + 2) #define IRQ_GPIO_START 128 -#define IRQ_GPIO_NUM 192 -#define IRQ_GPIO(x) (IRQ_GPIO_START + (x)) +#define MMP_NR_BUILTIN_GPIO 192 +#define MMP_GPIO_TO_IRQ(gpio) (IRQ_GPIO_START + (gpio)) -#define IRQ_BOARD_START (IRQ_GPIO_START + IRQ_GPIO_NUM) +#define IRQ_BOARD_START (IRQ_GPIO_START + MMP_NR_BUILTIN_GPIO) #define NR_IRQS (IRQ_BOARD_START) diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h index 2f7b2d3c2b18..cba22fed2265 100644 --- a/arch/arm/mach-mmp/include/mach/mmp2.h +++ b/arch/arm/mach-mmp/include/mach/mmp2.h @@ -32,6 +32,8 @@ extern struct pxa_device_desc mmp2_device_sdh3; extern struct pxa_device_desc mmp2_device_asram; extern struct pxa_device_desc mmp2_device_isram; +extern struct platform_device mmp2_device_gpio; + static inline int mmp2_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 7fb568d2845b..f9286089da3a 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -42,6 +42,8 @@ struct pxa168_usb_pdata { /* pdata can be NULL */ int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata); +extern struct platform_device pxa168_device_gpio; + static inline int pxa168_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h index 91be75591398..4de13abef7bb 100644 --- a/arch/arm/mach-mmp/include/mach/pxa910.h +++ b/arch/arm/mach-mmp/include/mach/pxa910.h @@ -21,6 +21,8 @@ extern struct pxa_device_desc pxa910_device_pwm3; extern struct pxa_device_desc pxa910_device_pwm4; extern struct pxa_device_desc pxa910_device_nand; +extern struct platform_device pxa910_device_gpio; + static inline int pxa910_add_uart(int id) { struct pxa_device_desc *d = NULL; diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index 5dd1d4a6aeb9..617c60a170a4 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <asm/hardware/cache-tauros2.h> @@ -24,7 +25,6 @@ #include <mach/irqs.h> #include <mach/dma.h> #include <mach/mfp.h> -#include <mach/gpio-pxa.h> #include <mach/devices.h> #include <mach/mmp2.h> @@ -33,8 +33,6 @@ #define MFPR_VIRT_BASE (APB_VIRT_BASE + 0x1e000) -#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x9c) - static struct mfp_addr_map mmp2_addr_map[] __initdata = { MFP_ADDR_X(GPIO0, GPIO58, 0x54), @@ -95,24 +93,9 @@ void mmp2_clear_pmic_int(void) __raw_writel(data, mfpr_pmic); } -static void __init mmp2_init_gpio(void) -{ - int i; - - /* enable GPIO clock */ - __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_MMP2_GPIO); - - /* unmask GPIO edge detection for all 6 banks -- APMASKx */ - for (i = 0; i < 6; i++) - __raw_writel(0xffffffff, APMASK(i)); - - pxa_init_gpio(IRQ_MMP2_GPIO, 0, 167, NULL); -} - void __init mmp2_init_irq(void) { mmp2_init_icu(); - mmp2_init_gpio(); } static void sdhc_clk_enable(struct clk *clk) @@ -149,6 +132,7 @@ static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000); static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000); static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000); static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000); +static APBC_CLK(gpio, MMP2_GPIO, 0, 26000000); static APMU_CLK(nand, NAND, 0xbf, 100000000); static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops); @@ -168,6 +152,7 @@ static struct clk_lookup mmp2_clkregs[] = { INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL), INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), + INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"), INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"), INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"), @@ -230,3 +215,21 @@ MMP2_DEVICE(asram, "asram", -1, NONE, 0xe0000000, 0x4000); /* 0xd1000000 ~ 0xd101ffff is reserved for secure processor */ MMP2_DEVICE(isram, "isram", -1, NONE, 0xd1020000, 0x18000); +struct resource mmp2_resource_gpio[] = { + { + .start = 0xd4019000, + .end = 0xd4019fff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_MMP2_GPIO, + .end = IRQ_MMP2_GPIO, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mmp2_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(mmp2_resource_gpio), + .resource = mmp2_resource_gpio, +}; diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 76ca15c00e45..84245035f351 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -13,6 +13,7 @@ #include <linux/list.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/platform_device.h> #include <asm/mach/time.h> #include <mach/addr-map.h> @@ -20,7 +21,6 @@ #include <mach/regs-apbc.h> #include <mach/regs-apmu.h> #include <mach/irqs.h> -#include <mach/gpio-pxa.h> #include <mach/dma.h> #include <mach/devices.h> #include <mach/mfp.h> @@ -43,26 +43,9 @@ static struct mfp_addr_map pxa168_mfp_addr_map[] __initdata = MFP_ADDR_END, }; -#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) - -static void __init pxa168_init_gpio(void) -{ - int i; - - /* enable GPIO clock */ - __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA168_GPIO); - - /* unmask GPIO edge detection for all 4 banks - APMASKx */ - for (i = 0; i < 4; i++) - __raw_writel(0xffffffff, APMASK(i)); - - pxa_init_gpio(IRQ_PXA168_GPIOX, 0, 127, NULL); -} - void __init pxa168_init_irq(void) { icu_init_irq(); - pxa168_init_gpio(); } /* APB peripheral clocks */ @@ -80,6 +63,7 @@ static APBC_CLK(ssp2, PXA168_SSP2, 4, 0); static APBC_CLK(ssp3, PXA168_SSP3, 4, 0); static APBC_CLK(ssp4, PXA168_SSP4, 4, 0); static APBC_CLK(ssp5, PXA168_SSP5, 4, 0); +static APBC_CLK(gpio, PXA168_GPIO, 0, 13000000); static APBC_CLK(keypad, PXA168_KPC, 0, 32000); static APMU_CLK(nand, NAND, 0x19b, 156000000); @@ -105,6 +89,7 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL), + INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL), INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"), INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"), @@ -174,6 +159,25 @@ PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8); PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c); PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff); +struct resource pxa168_resource_gpio[] = { + { + .start = 0xd4019000, + .end = 0xd4019fff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PXA168_GPIOX, + .end = IRQ_PXA168_GPIOX, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa168_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(pxa168_resource_gpio), + .resource = pxa168_resource_gpio, +}; + struct resource pxa168_usb_host_resources[] = { /* USB Host conroller register base */ [0] = { diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c index 4ebbfbba39fc..3241a25784d0 100644 --- a/arch/arm/mach-mmp/pxa910.c +++ b/arch/arm/mach-mmp/pxa910.c @@ -12,6 +12,7 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <asm/mach/time.h> #include <mach/addr-map.h> @@ -19,7 +20,6 @@ #include <mach/regs-apmu.h> #include <mach/cputype.h> #include <mach/irqs.h> -#include <mach/gpio-pxa.h> #include <mach/dma.h> #include <mach/mfp.h> #include <mach/devices.h> @@ -77,26 +77,9 @@ static struct mfp_addr_map pxa910_mfp_addr_map[] __initdata = MFP_ADDR_END, }; -#define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x09c) - -static void __init pxa910_init_gpio(void) -{ - int i; - - /* enable GPIO clock */ - __raw_writel(APBC_APBCLK | APBC_FNCLK, APBC_PXA910_GPIO); - - /* unmask GPIO edge detection for all 4 banks - APMASKx */ - for (i = 0; i < 4; i++) - __raw_writel(0xffffffff, APMASK(i)); - - pxa_init_gpio(IRQ_PXA910_AP_GPIO, 0, 127, NULL); -} - void __init pxa910_init_irq(void) { icu_init_irq(); - pxa910_init_gpio(); } /* APB peripheral clocks */ @@ -108,6 +91,7 @@ static APBC_CLK(pwm1, PXA910_PWM1, 1, 13000000); static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000); static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000); static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000); +static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000); static APMU_CLK(nand, NAND, 0x19b, 156000000); static APMU_CLK(u2o, USB, 0x1b, 480000000); @@ -123,6 +107,7 @@ static struct clk_lookup pxa910_clkregs[] = { INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL), INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), + INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL), INIT_CLKREG(&clk_u2o, "pxa-u2o", "U2OCLK"), }; @@ -179,3 +164,22 @@ PXA910_DEVICE(pwm2, "pxa910-pwm", 1, NONE, 0xd401a400, 0x10); PXA910_DEVICE(pwm3, "pxa910-pwm", 2, NONE, 0xd401a800, 0x10); PXA910_DEVICE(pwm4, "pxa910-pwm", 3, NONE, 0xd401ac00, 0x10); PXA910_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x80, 97, 99); + +struct resource pxa910_resource_gpio[] = { + { + .start = 0xd4019000, + .end = 0xd4019fff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PXA910_AP_GPIO, + .end = IRQ_PXA910_AP_GPIO, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa910_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(pxa910_resource_gpio), + .resource = pxa910_resource_gpio, +}; diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c index eb5be879fd8c..bb2ddb72bca2 100644 --- a/arch/arm/mach-mmp/tavorevb.c +++ b/arch/arm/mach-mmp/tavorevb.c @@ -19,6 +19,7 @@ #include <mach/addr-map.h> #include <mach/mfp-pxa910.h> #include <mach/pxa910.h> +#include <mach/irqs.h> #include "common.h" @@ -71,8 +72,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(80), - .end = gpio_to_irq(80), + .start = MMP_GPIO_TO_IRQ(80), + .end = MMP_GPIO_TO_IRQ(80), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; @@ -93,6 +94,7 @@ static void __init tavorevb_init(void) /* on-chip devices */ pxa910_add_uart(1); + platform_device_register(&pxa910_device_gpio); /* off-chip devices */ platform_device_register(&smc91x_device); diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c index bbe4727b96cc..703de85b571c 100644 --- a/arch/arm/mach-mmp/teton_bga.c +++ b/arch/arm/mach-mmp/teton_bga.c @@ -66,7 +66,7 @@ static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = { static struct i2c_board_info teton_bga_i2c_info[] __initdata = { { I2C_BOARD_INFO("ds1337", 0x68), - .irq = gpio_to_irq(RTC_INT_GPIO) + .irq = MMP_GPIO_TO_IRQ(RTC_INT_GPIO) }, }; @@ -78,6 +78,7 @@ static void __init teton_bga_init(void) pxa168_add_uart(1); pxa168_add_keypad(&teton_bga_keypad_info); pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(teton_bga_i2c_info)); + platform_device_register(&pxa168_device_gpio); } MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform") diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index 176515a76989..a80ed262df1c 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -24,12 +24,13 @@ #include <mach/addr-map.h> #include <mach/mfp-pxa910.h> #include <mach/pxa910.h> +#include <mach/irqs.h> #include "common.h" -#define TTCDKB_GPIO_EXT0(x) (NR_BUILTIN_GPIO + ((x < 0) ? 0 : \ +#define TTCDKB_GPIO_EXT0(x) (MMP_NR_BUILTIN_GPIO + ((x < 0) ? 0 : \ ((x < 16) ? x : 15))) -#define TTCDKB_GPIO_EXT1(x) (NR_BUILTIN_GPIO + 16 + ((x < 0) ? 0 : \ +#define TTCDKB_GPIO_EXT1(x) (MMP_NR_BUILTIN_GPIO + 16 + ((x < 0) ? 0 : \ ((x < 16) ? x : 15))) /* @@ -122,6 +123,7 @@ static struct platform_device ttc_dkb_device_onenand = { }; static struct platform_device *ttc_dkb_devices[] = { + &pxa910_device_gpio, &ttc_dkb_device_onenand, }; @@ -136,7 +138,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = { { .type = "max7312", .addr = 0x23, - .irq = IRQ_GPIO(80), + .irq = MMP_GPIO_TO_IRQ(80), .platform_data = &max7312_data, }, }; diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c index 5c837603ff0f..24994bb52147 100644 --- a/arch/arm/mach-mx5/board-mx51_babbage.c +++ b/arch/arm/mach-mx5/board-mx51_babbage.c @@ -362,7 +362,7 @@ static void __init mx51_babbage_init(void) { iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP; iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21, - PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | PAD_CTL_PUS_100K_UP); + PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH); imx51_soc_init(); diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c index 6bea31ab8f85..64bbfcea6f35 100644 --- a/arch/arm/mach-mx5/board-mx53_evk.c +++ b/arch/arm/mach-mx5/board-mx53_evk.c @@ -106,7 +106,7 @@ static inline void mx53_evk_fec_reset(void) gpio_set_value(MX53_EVK_FEC_PHY_RST, 1); } -static struct fec_platform_data mx53_evk_fec_pdata = { +static const struct fec_platform_data mx53_evk_fec_pdata __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c index 7678f7734db6..237bdecd9331 100644 --- a/arch/arm/mach-mx5/board-mx53_loco.c +++ b/arch/arm/mach-mx5/board-mx53_loco.c @@ -242,7 +242,7 @@ static inline void mx53_loco_fec_reset(void) gpio_set_value(LOCO_FEC_PHY_RST, 1); } -static struct fec_platform_data mx53_loco_fec_data = { +static const struct fec_platform_data mx53_loco_fec_data __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c index 59c0845eb4a6..d42132a80e8f 100644 --- a/arch/arm/mach-mx5/board-mx53_smd.c +++ b/arch/arm/mach-mx5/board-mx53_smd.c @@ -104,7 +104,7 @@ static inline void mx53_smd_fec_reset(void) gpio_set_value(SMD_FEC_PHY_RST, 1); } -static struct fec_platform_data mx53_smd_fec_data = { +static const struct fec_platform_data mx53_smd_fec_data __initconst = { .phy = PHY_INTERFACE_MODE_RMII, }; diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index da6e4aad177c..df0ad3ce234b 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -22,6 +22,7 @@ #include <linux/io.h> #include <linux/jiffies.h> #include <linux/clkdev.h> +#include <linux/spinlock.h> #include <asm/clkdev.h> #include <asm/div64.h> @@ -29,6 +30,7 @@ #include <mach/mx28.h> #include <mach/common.h> #include <mach/clock.h> +#include <mach/digctl.h> #include "regs-clkctrl-mx28.h" @@ -43,6 +45,33 @@ static struct clk emi_clk; static struct clk saif0_clk; static struct clk saif1_clk; static struct clk clk32k_clk; +static DEFINE_SPINLOCK(clkmux_lock); + +/* + * HW_SAIF_CLKMUX_SEL: + * DIRECT(0x0): SAIF0 clock pins selected for SAIF0 input clocks, and SAIF1 + * clock pins selected for SAIF1 input clocks. + * CROSSINPUT(0x1): SAIF1 clock inputs selected for SAIF0 input clocks, and + * SAIF0 clock inputs selected for SAIF1 input clocks. + * EXTMSTR0(0x2): SAIF0 clock pin selected for both SAIF0 and SAIF1 input + * clocks. + * EXTMSTR1(0x3): SAIF1 clock pin selected for both SAIF0 and SAIF1 input + * clocks. + */ +int mxs_saif_clkmux_select(unsigned int clkmux) +{ + if (clkmux > 0x3) + return -EINVAL; + + spin_lock(&clkmux_lock); + __raw_writel(BM_DIGCTL_CTRL_SAIF_CLKMUX, + DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_CLR_ADDR); + __raw_writel(clkmux << BP_DIGCTL_CTRL_SAIF_CLKMUX, + DIGCTRL_BASE_ADDR + HW_DIGCTL_CTRL + MXS_SET_ADDR); + spin_unlock(&clkmux_lock); + + return 0; +} static int _raw_clk_enable(struct clk *clk) { @@ -785,6 +814,15 @@ int __init mx28_clocks_init(void) clk_set_parent(&saif0_clk, &pll0_clk); clk_set_parent(&saif1_clk, &pll0_clk); + /* + * Set an initial clock rate for the saif internal logic to work + * properly. This is important when working in EXTMASTER mode that + * uses the other saif's BITCLK&LRCLK but it still needs a basic + * clock which should be fast enough for the internal logic. + */ + clk_set_rate(&saif0_clk, 24000000); + clk_set_rate(&saif1_clk, 24000000); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0); diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h index c8887103f0e3..4f50094e293d 100644 --- a/arch/arm/mach-mxs/devices-mx28.h +++ b/arch/arm/mach-mxs/devices-mx28.h @@ -47,6 +47,7 @@ struct platform_device *__init mx28_add_mxsfb( const struct mxsfb_platform_data *pdata); extern const struct mxs_saif_data mx28_saif_data[] __initconst; -#define mx28_add_saif(id) mxs_add_saif(&mx28_saif_data[id]) +#define mx28_add_saif(id, pdata) \ + mxs_add_saif(&mx28_saif_data[id], pdata) struct platform_device *__init mx28_add_rtc_stmp3xxx(void); diff --git a/arch/arm/mach-mxs/devices/platform-mxs-saif.c b/arch/arm/mach-mxs/devices/platform-mxs-saif.c index 1ec965e9fe92..f6e3a60b4201 100644 --- a/arch/arm/mach-mxs/devices/platform-mxs-saif.c +++ b/arch/arm/mach-mxs/devices/platform-mxs-saif.c @@ -32,7 +32,8 @@ const struct mxs_saif_data mx28_saif_data[] __initconst = { }; #endif -struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data) +struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data, + const struct mxs_saif_platform_data *pdata) { struct resource res[] = { { @@ -56,5 +57,5 @@ struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data) }; return mxs_add_platform_device("mxs-saif", data->id, res, - ARRAY_SIZE(res), NULL, 0); + ARRAY_SIZE(res), pdata, sizeof(*pdata)); } diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h index 635bb5d9a20a..3bbb94f4bbe1 100644 --- a/arch/arm/mach-mxs/include/mach/common.h +++ b/arch/arm/mach-mxs/include/mach/common.h @@ -16,6 +16,7 @@ struct clk; extern const u32 *mxs_get_ocotp(void); extern int mxs_reset_block(void __iomem *); extern void mxs_timer_init(struct clk *, int); +extern int mxs_saif_clkmux_select(unsigned int clkmux); extern int mx23_register_gpios(void); extern int mx23_clocks_init(void); diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h index a8080f44c03d..dc369c1239fc 100644 --- a/arch/arm/mach-mxs/include/mach/devices-common.h +++ b/arch/arm/mach-mxs/include/mach/devices-common.h @@ -94,6 +94,7 @@ struct platform_device *__init mxs_add_mxs_pwm( resource_size_t iobase, int id); /* saif */ +#include <sound/saif.h> struct mxs_saif_data { int id; resource_size_t iobase; @@ -103,4 +104,5 @@ struct mxs_saif_data { }; struct platform_device *__init mxs_add_saif( - const struct mxs_saif_data *data); + const struct mxs_saif_data *data, + const struct mxs_saif_platform_data *pdata); diff --git a/arch/arm/mach-mxs/include/mach/digctl.h b/arch/arm/mach-mxs/include/mach/digctl.h new file mode 100644 index 000000000000..49a888c65d6d --- /dev/null +++ b/arch/arm/mach-mxs/include/mach/digctl.h @@ -0,0 +1,21 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_DIGCTL_H__ +#define __MACH_DIGCTL_H__ + +/* MXS DIGCTL SAIF CLKMUX */ +#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT 0x0 +#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT 0x1 +#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 +#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 + +#define HW_DIGCTL_CTRL 0x0 +#define BP_DIGCTL_CTRL_SAIF_CLKMUX 10 +#define BM_DIGCTL_CTRL_SAIF_CLKMUX (0x3 << 10) +#endif diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c index 064ec5abaa55..ac84a10baa14 100644 --- a/arch/arm/mach-mxs/mach-mx28evk.c +++ b/arch/arm/mach-mxs/mach-mx28evk.c @@ -27,6 +27,7 @@ #include <mach/common.h> #include <mach/iomux-mx28.h> +#include <mach/digctl.h> #include "devices-mx28.h" @@ -421,6 +422,18 @@ static struct gpio mx28evk_lcd_gpios[] = { { MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" }, }; +static const struct mxs_saif_platform_data + mx28evk_mxs_saif_pdata[] __initconst = { + /* working on EXTMSTR0 mode (saif0 master, saif1 slave) */ + { + .master_mode = 1, + .master_id = 0, + }, { + .master_mode = 0, + .master_id = 0, + }, +}; + static void __init mx28evk_init(void) { int ret; @@ -454,8 +467,9 @@ static void __init mx28evk_init(void) else mx28_add_mxsfb(&mx28evk_mxsfb_pdata); - mx28_add_saif(0); - mx28_add_saif(1); + mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); + mx28_add_saif(0, &mx28evk_mxs_saif_pdata[0]); + mx28_add_saif(1, &mx28evk_mxs_saif_pdata[1]); mx28_add_mxs_i2c(0); i2c_register_board_info(0, mxs_i2c0_board_info, diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 515646886b59..ba23224963d0 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -404,6 +404,7 @@ static struct omap2_hsmmc_info mmc[] = { { .mmc = 5, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, + .pm_caps = MMC_PM_KEEP_POWER, .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, .ocr_mask = MMC_VDD_165_195, diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index d314f033c9df..f7df8d35ee90 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -24,6 +24,7 @@ #include <linux/i2c/pca953x.h> #include <linux/can/platform/ti_hecc.h> #include <linux/davinci_emac.h> +#include <linux/mmc/host.h> #include <mach/hardware.h> #include <mach/am35xx.h> @@ -40,6 +41,7 @@ #include "mux.h" #include "control.h" +#include "hsmmc.h" #define AM35XX_EVM_MDIO_FREQUENCY (1000000) @@ -455,6 +457,23 @@ static void am3517_evm_hecc_init(struct ti_hecc_platform_data *pdata) static struct omap_board_config_kernel am3517_evm_config[] __initdata = { }; +static struct omap2_hsmmc_info mmc[] = { + { + .mmc = 1, + .caps = MMC_CAP_4_BIT_DATA, + .gpio_cd = 127, + .gpio_wp = 126, + }, + { + .mmc = 2, + .caps = MMC_CAP_4_BIT_DATA, + .gpio_cd = 128, + .gpio_wp = 129, + }, + {} /* Terminator */ +}; + + static void __init am3517_evm_init(void) { omap_board_config = am3517_evm_config; @@ -483,6 +502,9 @@ static void __init am3517_evm_init(void) /* MUSB */ am3517_evm_musb_init(); + + /* MMC init function */ + omap2_hsmmc_init(mmc); } MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM") diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ba1aa07bdb29..c15c5c9c9085 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -193,7 +193,7 @@ static struct platform_device rx51_charger_device = { static void __init rx51_charger_init(void) { WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO, - GPIOF_OUT_INIT_LOW, "isp1704_reset")); + GPIOF_OUT_INIT_HIGH, "isp1704_reset")); platform_device_register(&rx51_charger_device); } diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c index 5d0064a4fb5a..9d59451446d9 100644 --- a/arch/arm/mach-omap2/clock3xxx_data.c +++ b/arch/arm/mach-omap2/clock3xxx_data.c @@ -2480,6 +2480,16 @@ static struct clk uart4_fck = { .recalc = &followparent_recalc, }; +static struct clk uart4_fck_am35xx = { + .name = "uart4_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &per_48m_fck, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_UART4_SHIFT, + .clkdm_name = "core_l4_clkdm", + .recalc = &followparent_recalc, +}; + static struct clk gpt2_fck = { .name = "gpt2_fck", .ops = &clkops_omap2_dflt_wait, @@ -3287,7 +3297,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX), CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX), CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX), @@ -3323,7 +3333,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX), CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX), CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX), CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX), @@ -3369,20 +3379,18 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX), CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX), CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), - CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), - CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX), + CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX), + CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX), CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), @@ -3403,6 +3411,7 @@ static struct omap_clk omap3xxx_clks[] = { CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX), CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX), CLK(NULL, "uart4_fck", &uart4_fck, CK_36XX), + CLK(NULL, "uart4_fck", &uart4_fck_am35xx, CK_3505 | CK_3517), CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX), CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX), CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX), diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 0798a802497a..c8a1b2740778 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3295,7 +3295,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "uart2_fck", &uart2_fck, CK_443X), CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), - CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X), + CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X), CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X), CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X), CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X), @@ -3306,7 +3306,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X), CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X), CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X), - CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X), + CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X), CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X), CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X), CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X), @@ -3314,7 +3314,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "usb_tll_hs_usb_ch2_clk", &usb_tll_hs_usb_ch2_clk, CK_443X), CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X), CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X), - CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X), + CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X), CLK(NULL, "usim_ck", &usim_ck, CK_443X), CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), CLK(NULL, "usim_fck", &usim_fck, CK_443X), @@ -3374,8 +3374,8 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "uart2_ick", &dummy_ck, CK_443X), CLK(NULL, "uart3_ick", &dummy_ck, CK_443X), CLK(NULL, "uart4_ick", &dummy_ck, CK_443X), - CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X), - CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X), + CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X), + CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X), CLK("omap_wdt", "ick", &dummy_ck, CK_443X), CLK("omap_timer.1", "32k_ck", &sys_32k_ck, CK_443X), CLK("omap_timer.2", "32k_ck", &sys_32k_ck, CK_443X), diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index f4a1020559a7..bd844af13af5 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -171,6 +171,17 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, } } +static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +{ + u32 reg; + + if (mmc->slots[0].internal_clock) { + reg = omap_ctrl_readl(control_devconf1_offset); + reg |= OMAP2_MMCSDIO2ADPCLKISEL; + omap_ctrl_writel(reg, control_devconf1_offset); + } +} + static void hsmmc23_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { @@ -179,16 +190,19 @@ static void hsmmc23_before_set_reg(struct device *dev, int slot, if (mmc->slots[0].remux) mmc->slots[0].remux(dev, slot, power_on); - if (power_on) { - /* Only MMC2 supports a CLKIN */ - if (mmc->slots[0].internal_clock) { - u32 reg; + if (power_on) + hsmmc2_select_input_clk_src(mmc); +} - reg = omap_ctrl_readl(control_devconf1_offset); - reg |= OMAP2_MMCSDIO2ADPCLKISEL; - omap_ctrl_writel(reg, control_devconf1_offset); - } - } +static int am35x_hsmmc2_set_power(struct device *dev, int slot, + int power_on, int vdd) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + if (power_on) + hsmmc2_select_input_clk_src(mmc); + + return 0; } static int nop_mmc_set_power(struct device *dev, int slot, int power_on, @@ -200,10 +214,12 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, int controller_nr) { - if (gpio_is_valid(mmc_controller->slots[0].switch_pin)) + if (gpio_is_valid(mmc_controller->slots[0].switch_pin) && + (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES)) omap_mux_init_gpio(mmc_controller->slots[0].switch_pin, OMAP_PIN_INPUT_PULLUP); - if (gpio_is_valid(mmc_controller->slots[0].gpio_wp)) + if (gpio_is_valid(mmc_controller->slots[0].gpio_wp) && + (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES)) omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp, OMAP_PIN_INPUT_PULLUP); if (cpu_is_omap34xx()) { @@ -296,6 +312,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->slots[0].name = hc_name; mmc->nr_slots = 1; mmc->slots[0].caps = c->caps; + mmc->slots[0].pm_caps = c->pm_caps; mmc->slots[0].internal_clock = !c->ext_clock; mmc->dma_mask = 0xffffffff; if (cpu_is_omap44xx()) @@ -336,11 +353,17 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, * * temporary HACK: ocr_mask instead of fixed supply */ - mmc->slots[0].ocr_mask = c->ocr_mask; - - if (cpu_is_omap3517() || cpu_is_omap3505()) - mmc->slots[0].set_power = nop_mmc_set_power; + if (cpu_is_omap3505() || cpu_is_omap3517()) + mmc->slots[0].ocr_mask = MMC_VDD_165_195 | + MMC_VDD_26_27 | + MMC_VDD_27_28 | + MMC_VDD_29_30 | + MMC_VDD_30_31 | + MMC_VDD_31_32; else + mmc->slots[0].ocr_mask = c->ocr_mask; + + if (!cpu_is_omap3517() && !cpu_is_omap3505()) mmc->slots[0].features |= HSMMC_HAS_PBIAS; if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0)) @@ -363,6 +386,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, } } + if (cpu_is_omap3517() || cpu_is_omap3505()) + mmc->slots[0].set_power = nop_mmc_set_power; + /* OMAP3630 HSMMC1 supports only 4-bit */ if (cpu_is_omap3630() && (c->caps & MMC_CAP_8_BIT_DATA)) { @@ -372,6 +398,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, } break; case 2: + if (cpu_is_omap3517() || cpu_is_omap3505()) + mmc->slots[0].set_power = am35x_hsmmc2_set_power; + if (c->ext_clock) c->transceiver = 1; if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) { diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index f757e78d4d4f..c4409730c4bb 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,6 +12,7 @@ struct omap2_hsmmc_info { u8 mmc; /* controller 1/2/3 */ u32 caps; /* 4/8 wires and any additional host * capabilities OR'd (ref. linux/mmc/host.h) */ + u32 pm_caps; /* PM capabilities */ bool transceiver; /* MMC-2 option */ bool ext_clock; /* use external pin for input clock */ bool cover_only; /* No card detect - just cover switch */ diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 292eee3be15f..28fcb27005d2 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -145,6 +145,9 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) pdata->reg_size = 4; pdata->has_ccr = true; } + pdata->set_clk_src = omap2_mcbsp_set_clk_src; + if (id == 1) + pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; if (oh->class->rev == MCBSP_CONFIG_TYPE3) { if (id == 2) @@ -174,9 +177,6 @@ static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused) name, oh->name); return PTR_ERR(pdev); } - pdata->set_clk_src = omap2_mcbsp_set_clk_src; - if (id == 1) - pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; omap_mcbsp_count++; return 0; } diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 7f8915ad5099..5324e8d93bc0 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -84,6 +84,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod; static struct omap_hwmod omap3xxx_mcbsp5_hwmod; static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod; static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod; +static struct omap_hwmod omap3xxx_usb_host_hs_hwmod; +static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod; /* L3 -> L4_CORE interface */ static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = { @@ -164,6 +166,7 @@ static struct omap_hwmod omap3xxx_uart1_hwmod; static struct omap_hwmod omap3xxx_uart2_hwmod; static struct omap_hwmod omap3xxx_uart3_hwmod; static struct omap_hwmod omap3xxx_uart4_hwmod; +static struct omap_hwmod am35xx_uart4_hwmod; static struct omap_hwmod omap3xxx_usbhsotg_hwmod; /* l3_core -> usbhsotg interface */ @@ -299,6 +302,23 @@ static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = { .user = OCP_USER_MPU | OCP_USER_SDMA, }; +/* AM35xx: L4 CORE -> UART4 interface */ +static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = { + { + .pa_start = OMAP3_UART4_AM35XX_BASE, + .pa_end = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1, + .flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT, + }, +}; + +static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &am35xx_uart4_hwmod, + .clk = "uart4_ick", + .addr = am35xx_uart4_addr_space, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + /* L4 CORE -> I2C1 interface */ static struct omap_hwmod_ocp_if omap3_l4_core__i2c1 = { .master = &omap3xxx_l4_core_hwmod, @@ -1162,6 +1182,7 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = { SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -1309,6 +1330,39 @@ static struct omap_hwmod omap3xxx_uart4_hwmod = { .class = &omap2_uart_class, }; +static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = { + { .irq = INT_35XX_UART4_IRQ, }, +}; + +static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = { + { .name = "rx", .dma_req = AM35XX_DMA_UART4_RX, }, + { .name = "tx", .dma_req = AM35XX_DMA_UART4_TX, }, +}; + +static struct omap_hwmod_ocp_if *am35xx_uart4_slaves[] = { + &am35xx_l4_core__uart4, +}; + +static struct omap_hwmod am35xx_uart4_hwmod = { + .name = "uart4", + .mpu_irqs = am35xx_uart4_mpu_irqs, + .sdma_reqs = am35xx_uart4_sdma_reqs, + .main_clk = "uart4_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_UART4_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430_EN_UART4_SHIFT, + }, + }, + .slaves = am35xx_uart4_slaves, + .slaves_cnt = ARRAY_SIZE(am35xx_uart4_slaves), + .class = &omap2_uart_class, +}; + + static struct omap_hwmod_class i2c_class = { .name = "i2c", .sysc = &i2c_sysc, @@ -1636,7 +1690,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = { static struct omap_hwmod omap3xxx_i2c1_hwmod = { .name = "i2c1", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap2_i2c1_mpu_irqs, .sdma_reqs = omap2_i2c1_sdma_reqs, .main_clk = "i2c1_fck", @@ -1670,7 +1724,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = { static struct omap_hwmod omap3xxx_i2c2_hwmod = { .name = "i2c2", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap2_i2c2_mpu_irqs, .sdma_reqs = omap2_i2c2_sdma_reqs, .main_clk = "i2c2_fck", @@ -1715,7 +1769,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = { static struct omap_hwmod omap3xxx_i2c3_hwmod = { .name = "i2c3", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = i2c3_mpu_irqs, .sdma_reqs = i2c3_sdma_reqs, .main_clk = "i2c3_fck", @@ -3072,7 +3126,35 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = { .flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT, }; -static struct omap_hwmod omap3xxx_mmc1_hwmod = { +/* See 35xx errata 2.1.1.128 in SPRZ278F */ +static struct omap_mmc_dev_attr mmc1_pre_es3_dev_attr = { + .flags = (OMAP_HSMMC_SUPPORTS_DUAL_VOLT | + OMAP_HSMMC_BROKEN_MULTIBLOCK_READ), +}; + +static struct omap_hwmod omap3xxx_pre_es3_mmc1_hwmod = { + .name = "mmc1", + .mpu_irqs = omap34xx_mmc1_mpu_irqs, + .sdma_reqs = omap34xx_mmc1_sdma_reqs, + .opt_clks = omap34xx_mmc1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc1_opt_clks), + .main_clk = "mmchs1_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_MMC1_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430_ST_MMC1_SHIFT, + }, + }, + .dev_attr = &mmc1_pre_es3_dev_attr, + .slaves = omap3xxx_mmc1_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc1_slaves), + .class = &omap34xx_mmc_class, +}; + +static struct omap_hwmod omap3xxx_es3plus_mmc1_hwmod = { .name = "mmc1", .mpu_irqs = omap34xx_mmc1_mpu_irqs, .sdma_reqs = omap34xx_mmc1_sdma_reqs, @@ -3115,7 +3197,34 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = { &omap3xxx_l4_core__mmc2, }; -static struct omap_hwmod omap3xxx_mmc2_hwmod = { +/* See 35xx errata 2.1.1.128 in SPRZ278F */ +static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = { + .flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ, +}; + +static struct omap_hwmod omap3xxx_pre_es3_mmc2_hwmod = { + .name = "mmc2", + .mpu_irqs = omap34xx_mmc2_mpu_irqs, + .sdma_reqs = omap34xx_mmc2_sdma_reqs, + .opt_clks = omap34xx_mmc2_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(omap34xx_mmc2_opt_clks), + .main_clk = "mmchs2_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430_EN_MMC2_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430_ST_MMC2_SHIFT, + }, + }, + .dev_attr = &mmc2_pre_es3_dev_attr, + .slaves = omap3xxx_mmc2_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_mmc2_slaves), + .class = &omap34xx_mmc_class, +}; + +static struct omap_hwmod omap3xxx_es3plus_mmc2_hwmod = { .name = "mmc2", .mpu_irqs = omap34xx_mmc2_mpu_irqs, .sdma_reqs = omap34xx_mmc2_sdma_reqs, @@ -3177,13 +3286,223 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = { .class = &omap34xx_mmc_class, }; +/* + * 'usb_host_hs' class + * high-speed multi-port usb host controller + */ +static struct omap_hwmod_ocp_if omap3xxx_usb_host_hs__l3_main_2 = { + .master = &omap3xxx_usb_host_hs_hwmod, + .slave = &omap3xxx_l3_main_hwmod, + .clk = "core_l3_ick", + .user = OCP_USER_MPU, +}; + +static struct omap_hwmod_class_sysconfig omap3xxx_usb_host_hs_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | + SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_usb_host_hs_hwmod_class = { + .name = "usb_host_hs", + .sysc = &omap3xxx_usb_host_hs_sysc, +}; + +static struct omap_hwmod_ocp_if *omap3xxx_usb_host_hs_masters[] = { + &omap3xxx_usb_host_hs__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap3xxx_usb_host_hs_addrs[] = { + { + .name = "uhh", + .pa_start = 0x48064000, + .pa_end = 0x480643ff, + .flags = ADDR_TYPE_RT + }, + { + .name = "ohci", + .pa_start = 0x48064400, + .pa_end = 0x480647ff, + }, + { + .name = "ehci", + .pa_start = 0x48064800, + .pa_end = 0x48064cff, + }, + {} +}; + +static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_host_hs = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_usb_host_hs_hwmod, + .clk = "usbhost_ick", + .addr = omap3xxx_usb_host_hs_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +static struct omap_hwmod_ocp_if *omap3xxx_usb_host_hs_slaves[] = { + &omap3xxx_l4_core__usb_host_hs, +}; + +static struct omap_hwmod_opt_clk omap3xxx_usb_host_hs_opt_clks[] = { + { .role = "ehci_logic_fck", .clk = "usbhost_120m_fck", }, +}; + +static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = { + { .name = "ohci-irq", .irq = 76 }, + { .name = "ehci-irq", .irq = 77 }, + { .irq = -1 } +}; + +static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = { + .name = "usb_host_hs", + .class = &omap3xxx_usb_host_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .mpu_irqs = omap3xxx_usb_host_hs_irqs, + .main_clk = "usbhost_48m_fck", + .prcm = { + .omap2 = { + .module_offs = OMAP3430ES2_USBHOST_MOD, + .prcm_reg_id = 1, + .module_bit = OMAP3430ES2_EN_USBHOST1_SHIFT, + .idlest_reg_id = 1, + .idlest_idle_bit = OMAP3430ES2_ST_USBHOST_IDLE_SHIFT, + .idlest_stdby_bit = OMAP3430ES2_ST_USBHOST_STDBY_SHIFT, + }, + }, + .opt_clks = omap3xxx_usb_host_hs_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_opt_clks), + .slaves = omap3xxx_usb_host_hs_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_slaves), + .masters = omap3xxx_usb_host_hs_masters, + .masters_cnt = ARRAY_SIZE(omap3xxx_usb_host_hs_masters), + + /* + * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock + * id: i660 + * + * Description: + * In the following configuration : + * - USBHOST module is set to smart-idle mode + * - PRCM asserts idle_req to the USBHOST module ( This typically + * happens when the system is going to a low power mode : all ports + * have been suspended, the master part of the USBHOST module has + * entered the standby state, and SW has cut the functional clocks) + * - an USBHOST interrupt occurs before the module is able to answer + * idle_ack, typically a remote wakeup IRQ. + * Then the USB HOST module will enter a deadlock situation where it + * is no more accessible nor functional. + * + * Workaround: + * Don't use smart idle; use only force idle, hence HWMOD_SWSUP_SIDLE + */ + + /* + * Errata: USB host EHCI may stall when entering smart-standby mode + * Id: i571 + * + * Description: + * When the USBHOST module is set to smart-standby mode, and when it is + * ready to enter the standby state (i.e. all ports are suspended and + * all attached devices are in suspend mode), then it can wrongly assert + * the Mstandby signal too early while there are still some residual OCP + * transactions ongoing. If this condition occurs, the internal state + * machine may go to an undefined state and the USB link may be stuck + * upon the next resume. + * + * Workaround: + * Don't use smart standby; use only force standby, + * hence HWMOD_SWSUP_MSTANDBY + */ + + /* + * During system boot; If the hwmod framework resets the module + * the module will have smart idle settings; which can lead to deadlock + * (above Errata Id:i660); so, dont reset the module during boot; + * Use HWMOD_INIT_NO_RESET. + */ + + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | + HWMOD_INIT_NO_RESET, +}; + +/* + * 'usb_tll_hs' class + * usb_tll_hs module is the adapter on the usb_host_hs ports + */ +static struct omap_hwmod_class_sysconfig omap3xxx_usb_tll_hs_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3xxx_usb_tll_hs_hwmod_class = { + .name = "usb_tll_hs", + .sysc = &omap3xxx_usb_tll_hs_sysc, +}; + +static struct omap_hwmod_irq_info omap3xxx_usb_tll_hs_irqs[] = { + { .name = "tll-irq", .irq = 78 }, + { .irq = -1 } +}; + +static struct omap_hwmod_addr_space omap3xxx_usb_tll_hs_addrs[] = { + { + .name = "tll", + .pa_start = 0x48062000, + .pa_end = 0x48062fff, + .flags = ADDR_TYPE_RT + }, + {} +}; + +static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = { + .master = &omap3xxx_l4_core_hwmod, + .slave = &omap3xxx_usb_tll_hs_hwmod, + .clk = "usbtll_ick", + .addr = omap3xxx_usb_tll_hs_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +static struct omap_hwmod_ocp_if *omap3xxx_usb_tll_hs_slaves[] = { + &omap3xxx_l4_core__usb_tll_hs, +}; + +static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = { + .name = "usb_tll_hs", + .class = &omap3xxx_usb_tll_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .mpu_irqs = omap3xxx_usb_tll_hs_irqs, + .main_clk = "usbtll_fck", + .prcm = { + .omap2 = { + .module_offs = CORE_MOD, + .prcm_reg_id = 3, + .module_bit = OMAP3430ES2_EN_USBTLL_SHIFT, + .idlest_reg_id = 3, + .idlest_idle_bit = OMAP3430ES2_ST_USBTLL_SHIFT, + }, + }, + .slaves = omap3xxx_usb_tll_hs_slaves, + .slaves_cnt = ARRAY_SIZE(omap3xxx_usb_tll_hs_slaves), +}; + static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_l3_main_hwmod, &omap3xxx_l4_core_hwmod, &omap3xxx_l4_per_hwmod, &omap3xxx_l4_wkup_hwmod, - &omap3xxx_mmc1_hwmod, - &omap3xxx_mmc2_hwmod, &omap3xxx_mmc3_hwmod, &omap3xxx_mpu_hwmod, @@ -3198,12 +3517,12 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { &omap3xxx_timer9_hwmod, &omap3xxx_timer10_hwmod, &omap3xxx_timer11_hwmod, - &omap3xxx_timer12_hwmod, &omap3xxx_wd_timer2_hwmod, &omap3xxx_uart1_hwmod, &omap3xxx_uart2_hwmod, &omap3xxx_uart3_hwmod, + /* dss class */ &omap3xxx_dss_dispc_hwmod, &omap3xxx_dss_dsi1_hwmod, @@ -3245,20 +3564,38 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = { NULL, }; +/* GP-only hwmods */ +static __initdata struct omap_hwmod *omap3xxx_gp_hwmods[] = { + &omap3xxx_timer12_hwmod, + NULL +}; + /* 3430ES1-only hwmods */ static __initdata struct omap_hwmod *omap3430es1_hwmods[] = { - &omap3xxx_iva_hwmod, &omap3430es1_dss_core_hwmod, - &omap3xxx_mailbox_hwmod, NULL }; /* 3430ES2+-only hwmods */ static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = { - &omap3xxx_iva_hwmod, &omap3xxx_dss_core_hwmod, &omap3xxx_usbhsotg_hwmod, - &omap3xxx_mailbox_hwmod, + &omap3xxx_usb_host_hs_hwmod, + &omap3xxx_usb_tll_hs_hwmod, + NULL +}; + +/* <= 3430ES3-only hwmods */ +static struct omap_hwmod *omap3430_pre_es3_hwmods[] __initdata = { + &omap3xxx_pre_es3_mmc1_hwmod, + &omap3xxx_pre_es3_mmc2_hwmod, + NULL +}; + +/* 3430ES3+-only hwmods */ +static struct omap_hwmod *omap3430_es3plus_hwmods[] __initdata = { + &omap3xxx_es3plus_mmc1_hwmod, + &omap3xxx_es3plus_mmc2_hwmod, NULL }; @@ -3280,12 +3617,21 @@ static __initdata struct omap_hwmod *omap36xx_hwmods[] = { &omap36xx_sr2_hwmod, &omap3xxx_usbhsotg_hwmod, &omap3xxx_mailbox_hwmod, + &omap3xxx_usb_host_hs_hwmod, + &omap3xxx_usb_tll_hs_hwmod, + &omap3xxx_es3plus_mmc1_hwmod, + &omap3xxx_es3plus_mmc2_hwmod, NULL }; static __initdata struct omap_hwmod *am35xx_hwmods[] = { &omap3xxx_dss_core_hwmod, /* XXX ??? */ &am35xx_usbhsotg_hwmod, + &am35xx_uart4_hwmod, + &omap3xxx_usb_host_hs_hwmod, + &omap3xxx_usb_tll_hs_hwmod, + &omap3xxx_es3plus_mmc1_hwmod, + &omap3xxx_es3plus_mmc2_hwmod, NULL }; @@ -3300,6 +3646,13 @@ int __init omap3xxx_hwmod_init(void) if (r < 0) return r; + /* Register GP-only hwmods. */ + if (omap_type() == OMAP2_DEVICE_TYPE_GP) { + r = omap_hwmod_register(omap3xxx_gp_hwmods); + if (r < 0) + return r; + } + rev = omap_rev(); /* @@ -3338,6 +3691,21 @@ int __init omap3xxx_hwmod_init(void) h = omap3430es2plus_hwmods; }; + if (h) { + r = omap_hwmod_register(h); + if (r < 0) + return r; + } + + h = NULL; + if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 || + rev == OMAP3430_REV_ES2_1) { + h = omap3430_pre_es3_hwmods; + } else if (rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 || + rev == OMAP3430_REV_ES3_1_2) { + h = omap3430_es3plus_hwmods; + }; + if (h) r = omap_hwmod_register(h); diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index daaf165af696..f9f151081760 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -70,6 +70,8 @@ static struct omap_hwmod omap44xx_mmc2_hwmod; static struct omap_hwmod omap44xx_mpu_hwmod; static struct omap_hwmod omap44xx_mpu_private_hwmod; static struct omap_hwmod omap44xx_usb_otg_hs_hwmod; +static struct omap_hwmod omap44xx_usb_host_hs_hwmod; +static struct omap_hwmod omap44xx_usb_tll_hs_hwmod; /* * Interconnects omap_hwmod structures @@ -2246,6 +2248,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = { SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | SIDLE_SMART_WKUP), + .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -2300,7 +2303,7 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = { .name = "i2c1", .class = &omap44xx_i2c_hwmod_class, .clkdm_name = "l4_per_clkdm", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c1_irqs, .sdma_reqs = omap44xx_i2c1_sdma_reqs, .main_clk = "i2c1_fck", @@ -2356,7 +2359,7 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = { .name = "i2c2", .class = &omap44xx_i2c_hwmod_class, .clkdm_name = "l4_per_clkdm", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c2_irqs, .sdma_reqs = omap44xx_i2c2_sdma_reqs, .main_clk = "i2c2_fck", @@ -2412,7 +2415,7 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = { .name = "i2c3", .class = &omap44xx_i2c_hwmod_class, .clkdm_name = "l4_per_clkdm", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c3_irqs, .sdma_reqs = omap44xx_i2c3_sdma_reqs, .main_clk = "i2c3_fck", @@ -2468,7 +2471,7 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = { .name = "i2c4", .class = &omap44xx_i2c_hwmod_class, .clkdm_name = "l4_per_clkdm", - .flags = HWMOD_16BIT_REG, + .flags = HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT, .mpu_irqs = omap44xx_i2c4_irqs, .sdma_reqs = omap44xx_i2c4_sdma_reqs, .main_clk = "i2c4_fck", @@ -5276,6 +5279,207 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = { .slaves_cnt = ARRAY_SIZE(omap44xx_wd_timer3_slaves), }; +/* + * 'usb_host_hs' class + * high-speed multi-port usb host controller + */ +static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = { + .master = &omap44xx_usb_host_hs_hwmod, + .slave = &omap44xx_l3_main_2_hwmod, + .clk = "l3_div_ck", + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE | + SYSC_HAS_SOFTRESET), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO | + MSTANDBY_SMART | MSTANDBY_SMART_WKUP), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = { + .name = "usb_host_hs", + .sysc = &omap44xx_usb_host_hs_sysc, +}; + +static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = { + &omap44xx_usb_host_hs__l3_main_2, +}; + +static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = { + { + .name = "uhh", + .pa_start = 0x4a064000, + .pa_end = 0x4a0647ff, + .flags = ADDR_TYPE_RT + }, + { + .name = "ohci", + .pa_start = 0x4a064800, + .pa_end = 0x4a064bff, + }, + { + .name = "ehci", + .pa_start = 0x4a064c00, + .pa_end = 0x4a064fff, + }, + {} +}; + +static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = { + { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START }, + { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_usb_host_hs_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_usb_host_hs_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = { + &omap44xx_l4_cfg__usb_host_hs, +}; + +static struct omap_hwmod omap44xx_usb_host_hs_hwmod = { + .name = "usb_host_hs", + .class = &omap44xx_usb_host_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .main_clk = "usb_host_hs_fck", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET, + .context_offs = OMAP4_RM_L3INIT_USB_HOST_CONTEXT_OFFSET, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .mpu_irqs = omap44xx_usb_host_hs_irqs, + .slaves = omap44xx_usb_host_hs_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves), + .masters = omap44xx_usb_host_hs_masters, + .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters), + + /* + * Errata: USBHOST Configured In Smart-Idle Can Lead To a Deadlock + * id: i660 + * + * Description: + * In the following configuration : + * - USBHOST module is set to smart-idle mode + * - PRCM asserts idle_req to the USBHOST module ( This typically + * happens when the system is going to a low power mode : all ports + * have been suspended, the master part of the USBHOST module has + * entered the standby state, and SW has cut the functional clocks) + * - an USBHOST interrupt occurs before the module is able to answer + * idle_ack, typically a remote wakeup IRQ. + * Then the USB HOST module will enter a deadlock situation where it + * is no more accessible nor functional. + * + * Workaround: + * Don't use smart idle; use only force idle, hence HWMOD_SWSUP_SIDLE + */ + + /* + * Errata: USB host EHCI may stall when entering smart-standby mode + * Id: i571 + * + * Description: + * When the USBHOST module is set to smart-standby mode, and when it is + * ready to enter the standby state (i.e. all ports are suspended and + * all attached devices are in suspend mode), then it can wrongly assert + * the Mstandby signal too early while there are still some residual OCP + * transactions ongoing. If this condition occurs, the internal state + * machine may go to an undefined state and the USB link may be stuck + * upon the next resume. + * + * Workaround: + * Don't use smart standby; use only force standby, + * hence HWMOD_SWSUP_MSTANDBY + */ + + /* + * During system boot; If the hwmod framework resets the module + * the module will have smart idle settings; which can lead to deadlock + * (above Errata Id:i660); so, dont reset the module during boot; + * Use HWMOD_INIT_NO_RESET. + */ + + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | + HWMOD_INIT_NO_RESET, +}; + +/* + * 'usb_tll_hs' class + * usb_tll_hs module is the adapter on the usb_host_hs ports + */ +static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .syss_offs = 0x0014, + .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | + SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | + SYSC_HAS_AUTOIDLE), + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), + .sysc_fields = &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = { + .name = "usb_tll_hs", + .sysc = &omap44xx_usb_tll_hs_sysc, +}; + +static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = { + { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START }, + { .irq = -1 } +}; + +static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = { + { + .name = "tll", + .pa_start = 0x4a062000, + .pa_end = 0x4a063fff, + .flags = ADDR_TYPE_RT + }, + {} +}; + +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_usb_tll_hs_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_usb_tll_hs_addrs, + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = { + &omap44xx_l4_cfg__usb_tll_hs, +}; + +static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = { + .name = "usb_tll_hs", + .class = &omap44xx_usb_tll_hs_hwmod_class, + .clkdm_name = "l3_init_clkdm", + .main_clk = "usb_tll_hs_ick", + .prcm = { + .omap4 = { + .clkctrl_offs = OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET, + .context_offs = OMAP4_RM_L3INIT_USB_TLL_CONTEXT_OFFSET, + .modulemode = MODULEMODE_HWCTRL, + }, + }, + .mpu_irqs = omap44xx_usb_tll_hs_irqs, + .slaves = omap44xx_usb_tll_hs_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves), +}; + static __initdata struct omap_hwmod *omap44xx_hwmods[] = { /* dmm class */ @@ -5415,13 +5619,16 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_uart3_hwmod, &omap44xx_uart4_hwmod, + /* usb host class */ + &omap44xx_usb_host_hs_hwmod, + &omap44xx_usb_tll_hs_hwmod, + /* usb_otg_hs class */ &omap44xx_usb_otg_hs_hwmod, /* wd_timer class */ &omap44xx_wd_timer2_hwmod, &omap44xx_wd_timer3_hwmod, - NULL, }; diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 0363dcb0ef93..da2d80f5fcbd 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -201,6 +201,8 @@ #define OMAP3430_EN_MMC2_SHIFT 25 #define OMAP3430_EN_MMC1_MASK (1 << 24) #define OMAP3430_EN_MMC1_SHIFT 24 +#define OMAP3430_EN_UART4_MASK (1 << 23) +#define OMAP3430_EN_UART4_SHIFT 23 #define OMAP3430_EN_MCSPI4_MASK (1 << 21) #define OMAP3430_EN_MCSPI4_SHIFT 21 #define OMAP3430_EN_MCSPI3_MASK (1 << 20) diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c index 89ae29847c59..771dc781b746 100644 --- a/arch/arm/mach-omap2/usb-host.c +++ b/arch/arm/mach-omap2/usb-host.c @@ -28,51 +28,28 @@ #include <mach/hardware.h> #include <mach/irqs.h> #include <plat/usb.h> +#include <plat/omap_device.h> #include "mux.h" #ifdef CONFIG_MFD_OMAP_USB_HOST -#define OMAP_USBHS_DEVICE "usbhs-omap" - -static struct resource usbhs_resources[] = { - { - .name = "uhh", - .flags = IORESOURCE_MEM, - }, - { - .name = "tll", - .flags = IORESOURCE_MEM, - }, - { - .name = "ehci", - .flags = IORESOURCE_MEM, - }, - { - .name = "ehci-irq", - .flags = IORESOURCE_IRQ, - }, - { - .name = "ohci", - .flags = IORESOURCE_MEM, - }, - { - .name = "ohci-irq", - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device usbhs_device = { - .name = OMAP_USBHS_DEVICE, - .id = 0, - .num_resources = ARRAY_SIZE(usbhs_resources), - .resource = usbhs_resources, -}; +#define OMAP_USBHS_DEVICE "usbhs_omap" +#define USBHS_UHH_HWMODNAME "usb_host_hs" +#define USBHS_TLL_HWMODNAME "usb_tll_hs" static struct usbhs_omap_platform_data usbhs_data; static struct ehci_hcd_omap_platform_data ehci_data; static struct ohci_hcd_omap_platform_data ohci_data; +static struct omap_device_pm_latency omap_uhhtll_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + /* MUX settings for EHCI pins */ /* * setup_ehci_io_mux - initialize IO pad mux for USBHOST @@ -508,7 +485,10 @@ static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode) void __init usbhs_init(const struct usbhs_omap_board_data *pdata) { - int i; + struct omap_hwmod *oh[2]; + struct omap_device *od; + int bus_id = -1; + int i; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { usbhs_data.port_mode[i] = pdata->port_mode[i]; @@ -523,44 +503,34 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata) usbhs_data.ohci_data = &ohci_data; if (cpu_is_omap34xx()) { - usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE; - usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1; - usbhs_resources[1].start = OMAP34XX_USBTLL_BASE; - usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1; - usbhs_resources[2].start = OMAP34XX_EHCI_BASE; - usbhs_resources[2].end = OMAP34XX_EHCI_BASE + SZ_1K - 1; - usbhs_resources[3].start = INT_34XX_EHCI_IRQ; - usbhs_resources[4].start = OMAP34XX_OHCI_BASE; - usbhs_resources[4].end = OMAP34XX_OHCI_BASE + SZ_1K - 1; - usbhs_resources[5].start = INT_34XX_OHCI_IRQ; setup_ehci_io_mux(pdata->port_mode); setup_ohci_io_mux(pdata->port_mode); } else if (cpu_is_omap44xx()) { - usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE; - usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1; - usbhs_resources[1].start = OMAP44XX_USBTLL_BASE; - usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1; - usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE; - usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1; - usbhs_resources[3].start = OMAP44XX_IRQ_EHCI; - usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE; - usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1; - usbhs_resources[5].start = OMAP44XX_IRQ_OHCI; setup_4430ehci_io_mux(pdata->port_mode); setup_4430ohci_io_mux(pdata->port_mode); } - if (platform_device_add_data(&usbhs_device, - &usbhs_data, sizeof(usbhs_data)) < 0) { - printk(KERN_ERR "USBHS platform_device_add_data failed\n"); - goto init_end; + oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); + if (!oh[0]) { + pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); + return; } - if (platform_device_register(&usbhs_device) < 0) - printk(KERN_ERR "USBHS platform_device_register failed\n"); + oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); + if (!oh[1]) { + pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); + return; + } -init_end: - return; + od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2, + (void *)&usbhs_data, sizeof(usbhs_data), + omap_uhhtll_latency, + ARRAY_SIZE(omap_uhhtll_latency), false); + if (IS_ERR(od)) { + pr_err("Could not build hwmod devices %s,%s\n", + USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME); + return; + } } #else @@ -570,5 +540,3 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata) } #endif - - diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c index 4cb069fd9af2..ccdac4b6a469 100644 --- a/arch/arm/mach-pxa/am200epd.c +++ b/arch/arm/mach-pxa/am200epd.c @@ -138,7 +138,7 @@ static void am200_cleanup(struct metronomefb_par *par) { int i; - free_irq(IRQ_GPIO(RDY_GPIO_PIN), par); + free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par); for (i = 0; i < ARRAY_SIZE(gpios); i++) gpio_free(gpios[i]); @@ -292,7 +292,7 @@ static int am200_setup_irq(struct fb_info *info) { int ret; - ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am200_handle_irq, + ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am200_handle_irq, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "AM200", info->par); if (ret) diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c index fa8bad235d9f..76c4b9494031 100644 --- a/arch/arm/mach-pxa/am300epd.c +++ b/arch/arm/mach-pxa/am300epd.c @@ -176,7 +176,7 @@ static void am300_cleanup(struct broadsheetfb_par *par) { int i; - free_irq(IRQ_GPIO(RDY_GPIO_PIN), par); + free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par); for (i = 0; i < ARRAY_SIZE(gpios); i++) gpio_free(gpios[i]); @@ -240,7 +240,7 @@ static int am300_setup_irq(struct fb_info *info) int ret; struct broadsheetfb_par *par = info->par; - ret = request_irq(IRQ_GPIO(RDY_GPIO_PIN), am300_handle_irq, + ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq, IRQF_DISABLED|IRQF_TRIGGER_RISING, "AM300", par); if (ret) diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index 4b81f59a4cba..11f2223da576 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -179,7 +179,7 @@ static unsigned long balloon3_ac97_pin_config[] __initdata = { }; static struct ucb1400_pdata vpac270_ucb1400_pdata = { - .irq = IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ), + .irq = PXA_GPIO_TO_IRQ(BALLOON3_GPIO_CODEC_IRQ), }; diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c index 4efc16d39c79..5516317b9e64 100644 --- a/arch/arm/mach-pxa/capc7117.c +++ b/arch/arm/mach-pxa/capc7117.c @@ -50,8 +50,8 @@ static struct resource capc7117_ide_resources[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO76)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO76)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO76)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO76)), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING } }; @@ -80,7 +80,7 @@ static void __init capc7117_ide_init(void) static struct plat_serial8250_port ti16c752_platform_data[] = { [0] = { .mapbase = 0x14000000, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO78)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO78)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, @@ -89,7 +89,7 @@ static struct plat_serial8250_port ti16c752_platform_data[] = { }, [1] = { .mapbase = 0x14000040, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO79)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO79)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, @@ -98,7 +98,7 @@ static struct plat_serial8250_port ti16c752_platform_data[] = { }, [2] = { .mapbase = 0x14000080, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO80)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO80)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, @@ -107,7 +107,7 @@ static struct plat_serial8250_port ti16c752_platform_data[] = { }, [3] = { .mapbase = 0x140000c0, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO81)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO81)), .irqflags = IRQF_TRIGGER_RISING, .flags = TI16C752_FLAGS, .iotype = UPIO_MEM, diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index 13518a705399..431ef56700c4 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -33,7 +33,7 @@ /* GPIO IRQ usage */ #define GPIO83_MMC_IRQ (83) -#define CMX270_MMC_IRQ IRQ_GPIO(GPIO83_MMC_IRQ) +#define CMX270_MMC_IRQ PXA_GPIO_TO_IRQ(GPIO83_MMC_IRQ) /* MMC power enable */ #define GPIO105_MMC_POWER (105) @@ -380,7 +380,7 @@ static struct spi_board_info cm_x270_spi_devices[] __initdata = { .modalias = "libertas_spi", .max_speed_hz = 13000000, .bus_num = 2, - .irq = gpio_to_irq(95), + .irq = PXA_GPIO_TO_IRQ(95), .chip_select = 0, .controller_data = &cm_x270_libertas_chip, .platform_data = &cm_x270_libertas_pdata, diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c index f2e4190080cb..9344a0e3ba8a 100644 --- a/arch/arm/mach-pxa/cm-x2xx.c +++ b/arch/arm/mach-pxa/cm-x2xx.c @@ -58,8 +58,8 @@ extern void cmx270_init(void); #define CMX255_GPIO_IT8152_IRQ (0) #define CMX270_GPIO_IT8152_IRQ (22) -#define CMX255_ETHIRQ IRQ_GPIO(GPIO22_ETHIRQ) -#define CMX270_ETHIRQ IRQ_GPIO(GPIO10_ETHIRQ) +#define CMX255_ETHIRQ PXA_GPIO_TO_IRQ(GPIO22_ETHIRQ) +#define CMX270_ETHIRQ PXA_GPIO_TO_IRQ(GPIO10_ETHIRQ) #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) static struct resource cmx255_dm9000_resource[] = { diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index e096bba8fd57..684acf6ed3d5 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -64,7 +64,7 @@ #define GPIO82_MMC_IRQ (82) #define GPIO85_MMC_WP (85) -#define CM_X300_MMC_IRQ IRQ_GPIO(GPIO82_MMC_IRQ) +#define CM_X300_MMC_IRQ PXA_GPIO_TO_IRQ(GPIO82_MMC_IRQ) #define GPIO95_RTC_CS (95) #define GPIO96_RTC_WR (96) @@ -229,8 +229,8 @@ static struct resource dm9000_resources[] = { .flags = IORESOURCE_MEM, }, [2] = { - .start = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO99)), - .end = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO99)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO99)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO99)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c index 05bfa1b1c001..f0fe9a51dfcc 100644 --- a/arch/arm/mach-pxa/colibri-pxa270.c +++ b/arch/arm/mach-pxa/colibri-pxa270.c @@ -218,8 +218,8 @@ static struct resource colibri_pxa270_dm9000_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = gpio_to_irq(GPIO114_COLIBRI_PXA270_ETH_IRQ), - .end = gpio_to_irq(GPIO114_COLIBRI_PXA270_ETH_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING, }, }; @@ -249,7 +249,7 @@ static pxa2xx_audio_ops_t colibri_pxa270_ac97_pdata = { }; static struct ucb1400_pdata colibri_pxa270_ucb1400_pdata = { - .irq = gpio_to_irq(GPIO113_COLIBRI_PXA270_TS_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO113_COLIBRI_PXA270_TS_IRQ), }; static struct platform_device colibri_pxa270_ucb1400_device = { diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index c825e8bf2db1..0a6222e20f9b 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -78,8 +78,8 @@ static struct resource colibri_asix_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), - .end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .start = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), + .end = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c index d23b92b80488..56ab7a634bca 100644 --- a/arch/arm/mach-pxa/colibri-pxa320.c +++ b/arch/arm/mach-pxa/colibri-pxa320.c @@ -115,8 +115,8 @@ static struct resource colibri_asix_resource[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), - .end = gpio_to_irq(COLIBRI_ETH_IRQ_GPIO), + .start = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), + .end = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 549468d088b9..3812ba0ff50c 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -531,7 +531,7 @@ static struct spi_board_info corgi_spi_devices[] = { .chip_select = 0, .platform_data = &corgi_ads7846_info, .controller_data= &corgi_ads7846_chip, - .irq = gpio_to_irq(CORGI_GPIO_TP_INT), + .irq = PXA_GPIO_TO_IRQ(CORGI_GPIO_TP_INT), }, { .modalias = "corgi-lcd", .max_speed_hz = 50000, diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index 29034778bfda..39e265cfc86d 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/apm-emulation.h> @@ -40,7 +41,9 @@ static struct gpio charger_gpios[] = { { CORGI_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" }, { CORGI_GPIO_CHRG_ON, GPIOF_OUT_INIT_LOW, "Charger On" }, { CORGI_GPIO_CHRG_UKN, GPIOF_OUT_INIT_LOW, "Charger Unknown" }, + { CORGI_GPIO_AC_IN, GPIOF_IN, "Charger Detection" }, { CORGI_GPIO_KEY_INT, GPIOF_IN, "Key Interrupt" }, + { CORGI_GPIO_WAKEUP, GPIOF_IN, "System wakeup notification" }, }; static void corgi_charger_init(void) @@ -90,7 +93,12 @@ static int corgi_should_wakeup(unsigned int resume_on_alarm) { int is_resume = 0; - dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR); + dev_dbg(sharpsl_pm.dev, "PEDR = %x, GPIO_AC_IN = %d, " + "GPIO_CHRG_FULL = %d, GPIO_KEY_INT = %d, GPIO_WAKEUP = %d\n", + PEDR, gpio_get_value(CORGI_GPIO_AC_IN), + gpio_get_value(CORGI_GPIO_CHRG_FULL), + gpio_get_value(CORGI_GPIO_KEY_INT), + gpio_get_value(CORGI_GPIO_WAKEUP)); if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) { if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { @@ -124,14 +132,21 @@ static int corgi_should_wakeup(unsigned int resume_on_alarm) static unsigned long corgi_charger_wakeup(void) { - return ~GPLR0 & ( GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) ); + unsigned long ret; + + ret = (!gpio_get_value(CORGI_GPIO_AC_IN) << GPIO_bit(CORGI_GPIO_AC_IN)) + | (!gpio_get_value(CORGI_GPIO_KEY_INT) + << GPIO_bit(CORGI_GPIO_KEY_INT)) + | (!gpio_get_value(CORGI_GPIO_WAKEUP) + << GPIO_bit(CORGI_GPIO_WAKEUP)); + return ret; } unsigned long corgipm_read_devdata(int type) { switch(type) { case SHARPSL_STATUS_ACIN: - return ((GPLR(CORGI_GPIO_AC_IN) & GPIO_bit(CORGI_GPIO_AC_IN)) != 0); + return !gpio_get_value(CORGI_GPIO_AC_IN); case SHARPSL_STATUS_LOCK: return gpio_get_value(sharpsl_pm.machinfo->gpio_batlock); case SHARPSL_STATUS_CHRGFULL: diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 8b134c3b457f..18fd177073f4 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -1071,6 +1071,36 @@ struct platform_device pxa3xx_device_ssp4 = { }; #endif /* CONFIG_PXA3xx || CONFIG_PXA95x */ +struct resource pxa_resource_gpio[] = { + { + .start = 0x40e00000, + .end = 0x40e0ffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_GPIO0, + .end = IRQ_GPIO0, + .name = "gpio0", + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_GPIO1, + .end = IRQ_GPIO1, + .name = "gpio1", + .flags = IORESOURCE_IRQ, + }, { + .start = IRQ_GPIO_2_x, + .end = IRQ_GPIO_2_x, + .name = "gpio_mux", + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device pxa_device_gpio = { + .name = "pxa-gpio", + .id = -1, + .num_resources = ARRAY_SIZE(pxa_resource_gpio), + .resource = pxa_resource_gpio, +}; + /* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1. * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */ void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info) diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h index 2fd5a8b35757..1475db107254 100644 --- a/arch/arm/mach-pxa/devices.h +++ b/arch/arm/mach-pxa/devices.h @@ -16,6 +16,7 @@ extern struct platform_device pxa_device_ficp; extern struct platform_device sa1100_device_rtc; extern struct platform_device pxa_device_rtc; extern struct platform_device pxa_device_ac97; +extern struct platform_device pxa_device_gpio; extern struct platform_device pxa27x_device_i2c_power; extern struct platform_device pxa27x_device_ohci; diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index 94acc0b01dd6..3358f4da2ec9 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -70,7 +70,7 @@ /* common GPIOs */ #define GPIO11_NAND_CS (11) #define GPIO41_ETHIRQ (41) -#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) +#define EM_X270_ETHIRQ PXA_GPIO_TO_IRQ(GPIO41_ETHIRQ) #define GPIO115_WLAN_PWEN (115) #define GPIO19_WLAN_STRAP (19) #define GPIO9_USB_VBUS_EN (9) @@ -805,7 +805,7 @@ static struct spi_board_info em_x270_spi_devices[] __initdata = { .modalias = "libertas_spi", .max_speed_hz = 13000000, .bus_num = 2, - .irq = IRQ_GPIO(116), + .irq = PXA_GPIO_TO_IRQ(116), .chip_select = 0, .controller_data = &em_x270_libertas_chip, .platform_data = &em_x270_libertas_pdata, @@ -1203,7 +1203,7 @@ static struct da903x_platform_data em_x270_da9030_info = { static struct i2c_board_info em_x270_i2c_pmic_info = { I2C_BOARD_INFO("da9030", 0x49), - .irq = IRQ_GPIO(0), + .irq = PXA_GPIO_TO_IRQ(0), .platform_data = &em_x270_da9030_info, }; diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c index d82b7aa3c096..e556a1e3ff0f 100644 --- a/arch/arm/mach-pxa/eseries.c +++ b/arch/arm/mach-pxa/eseries.c @@ -119,8 +119,8 @@ struct resource eseries_tmio_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_GPIO(GPIO_ESERIES_TMIO_IRQ), - .end = IRQ_GPIO(GPIO_ESERIES_TMIO_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO_ESERIES_TMIO_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO_ESERIES_TMIO_IRQ), .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 6f6368ece9bd..82e9976e5657 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -252,8 +252,8 @@ static struct resource asic3_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ), - .end = gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO12_HX4700_ASIC3_IRQ), .flags = IORESOURCE_IRQ, }, /* SD part */ @@ -263,8 +263,8 @@ static struct resource asic3_resources[] = { .flags = IORESOURCE_MEM, }, [3] = { - .start = gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ), - .end = gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO66_HX4700_ASIC3_nSDIO_IRQ), .flags = IORESOURCE_IRQ, }, }; @@ -587,7 +587,7 @@ static struct spi_board_info tsc2046_board_info[] __initdata = { .modalias = "ads7846", .bus_num = 2, .max_speed_hz = 2600000, /* 100 kHz sample rate */ - .irq = gpio_to_irq(GPIO58_HX4700_TSC2046_nPENIRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO58_HX4700_TSC2046_nPENIRQ), .platform_data = &tsc2046_info, .controller_data = &tsc2046_chip, }, @@ -635,15 +635,15 @@ static struct resource power_supply_resources[] = { .name = "ac", .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, - .start = gpio_to_irq(GPIOD9_nAC_IN), - .end = gpio_to_irq(GPIOD9_nAC_IN), + .start = PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), + .end = PXA_GPIO_TO_IRQ(GPIOD9_nAC_IN), }, [1] = { .name = "usb", .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, - .start = gpio_to_irq(GPIOD14_nUSBC_DETECT), - .end = gpio_to_irq(GPIOD14_nUSBC_DETECT), + .start = PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), + .end = PXA_GPIO_TO_IRQ(GPIOD14_nUSBC_DETECT), }, }; diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c index f78d5db758da..33e81e87a9da 100644 --- a/arch/arm/mach-pxa/icontrol.c +++ b/arch/arm/mach-pxa/icontrol.c @@ -86,7 +86,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 0, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info1, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ1) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ1) }, { .modalias = "mcp2515", @@ -95,7 +95,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 1, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info2, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ2) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ2) }, { .modalias = "mcp2515", @@ -104,7 +104,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 0, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info3, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ3) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ3) }, { .modalias = "mcp2515", @@ -113,7 +113,7 @@ static struct spi_board_info mcp251x_board_info[] = { .chip_select = 1, .platform_data = &mcp251x_info, .controller_data = &mcp251x_chip_info4, - .irq = gpio_to_irq(ICONTROL_MCP251x_nIRQ4) + .irq = PXA_GPIO_TO_IRQ(ICONTROL_MCP251x_nIRQ4) } }; diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index ddf20e5c376e..bb98ff57b71f 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -75,8 +75,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_GPIO(4), - .end = IRQ_GPIO(4), + .start = PXA_GPIO_TO_IRQ(4), + .end = PXA_GPIO_TO_IRQ(4), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-pxa/include/mach/balloon3.h b/arch/arm/mach-pxa/include/mach/balloon3.h index 6d7eab3d0867..f02fa1e6ba86 100644 --- a/arch/arm/mach-pxa/include/mach/balloon3.h +++ b/arch/arm/mach-pxa/include/mach/balloon3.h @@ -172,9 +172,9 @@ enum balloon3_features { /* Balloon3 Interrupts */ #define BALLOON3_IRQ(x) (IRQ_BOARD_START + (x)) -#define BALLOON3_AUX_NIRQ IRQ_GPIO(BALLOON3_GPIO_AUX_NIRQ) -#define BALLOON3_CODEC_IRQ IRQ_GPIO(BALLOON3_GPIO_CODEC_IRQ) -#define BALLOON3_S0_CD_IRQ IRQ_GPIO(BALLOON3_GPIO_S0_CD) +#define BALLOON3_AUX_NIRQ PXA_GPIO_TO_IRQ(BALLOON3_GPIO_AUX_NIRQ) +#define BALLOON3_CODEC_IRQ PXA_GPIO_TO_IRQ(BALLOON3_GPIO_CODEC_IRQ) +#define BALLOON3_S0_CD_IRQ PXA_GPIO_TO_IRQ(BALLOON3_GPIO_S0_CD) #define BALLOON3_NR_IRQS (IRQ_BOARD_START + 16) diff --git a/arch/arm/mach-pxa/include/mach/corgi.h b/arch/arm/mach-pxa/include/mach/corgi.h index 5dfd1195a5a7..f3c3493b468d 100644 --- a/arch/arm/mach-pxa/include/mach/corgi.h +++ b/arch/arm/mach-pxa/include/mach/corgi.h @@ -66,18 +66,18 @@ /* * Corgi Interrupts */ -#define CORGI_IRQ_GPIO_KEY_INT IRQ_GPIO(0) -#define CORGI_IRQ_GPIO_AC_IN IRQ_GPIO(1) -#define CORGI_IRQ_GPIO_WAKEUP IRQ_GPIO(3) -#define CORGI_IRQ_GPIO_AK_INT IRQ_GPIO(4) -#define CORGI_IRQ_GPIO_TP_INT IRQ_GPIO(5) -#define CORGI_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9) -#define CORGI_IRQ_GPIO_nSD_INT IRQ_GPIO(10) -#define CORGI_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(11) -#define CORGI_IRQ_GPIO_CF_CD IRQ_GPIO(14) -#define CORGI_IRQ_GPIO_CHRG_FULL IRQ_GPIO(16) /* Battery fully charged */ -#define CORGI_IRQ_GPIO_CF_IRQ IRQ_GPIO(17) -#define CORGI_IRQ_GPIO_KEY_SENSE(a) IRQ_GPIO(58+(a)) /* Keyboard Sense lines */ +#define CORGI_IRQ_GPIO_KEY_INT PXA_GPIO_TO_IRQ(0) +#define CORGI_IRQ_GPIO_AC_IN PXA_GPIO_TO_IRQ(1) +#define CORGI_IRQ_GPIO_WAKEUP PXA_GPIO_TO_IRQ(3) +#define CORGI_IRQ_GPIO_AK_INT PXA_GPIO_TO_IRQ(4) +#define CORGI_IRQ_GPIO_TP_INT PXA_GPIO_TO_IRQ(5) +#define CORGI_IRQ_GPIO_nSD_DETECT PXA_GPIO_TO_IRQ(9) +#define CORGI_IRQ_GPIO_nSD_INT PXA_GPIO_TO_IRQ(10) +#define CORGI_IRQ_GPIO_MAIN_BAT_LOW PXA_GPIO_TO_IRQ(11) +#define CORGI_IRQ_GPIO_CF_CD PXA_GPIO_TO_IRQ(14) +#define CORGI_IRQ_GPIO_CHRG_FULL PXA_GPIO_TO_IRQ(16) /* Battery fully charged */ +#define CORGI_IRQ_GPIO_CF_IRQ PXA_GPIO_TO_IRQ(17) +#define CORGI_IRQ_GPIO_KEY_SENSE(a) PXA_GPIO_TO_IRQ(58+(a)) /* Keyboard Sense lines */ /* @@ -98,7 +98,7 @@ CORGI_SCP_MIC_BIAS ) #define CORGI_SCOOP_IO_OUT ( CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R ) -#define CORGI_SCOOP_GPIO_BASE (NR_BUILTIN_GPIO) +#define CORGI_SCOOP_GPIO_BASE (PXA_NR_BUILTIN_GPIO) #define CORGI_GPIO_LED_GREEN (CORGI_SCOOP_GPIO_BASE + 0) #define CORGI_GPIO_SWA (CORGI_SCOOP_GPIO_BASE + 1) /* Hinge Switch A */ #define CORGI_GPIO_SWB (CORGI_SCOOP_GPIO_BASE + 2) /* Hinge Switch B */ diff --git a/arch/arm/mach-pxa/include/mach/csb726.h b/arch/arm/mach-pxa/include/mach/csb726.h index 747ab1a71f2f..2628e7b72116 100644 --- a/arch/arm/mach-pxa/include/mach/csb726.h +++ b/arch/arm/mach-pxa/include/mach/csb726.h @@ -19,8 +19,8 @@ #define CSB726_FLASH_SIZE (64 * 1024 * 1024) #define CSB726_FLASH_uMON (8 * 1024 * 1024) -#define CSB726_IRQ_LAN gpio_to_irq(CSB726_GPIO_IRQ_LAN) -#define CSB726_IRQ_SM501 gpio_to_irq(CSB726_GPIO_IRQ_SM501) +#define CSB726_IRQ_LAN PXA_GPIO_TO_IRQ(CSB726_GPIO_IRQ_LAN) +#define CSB726_IRQ_SM501 PXA_GPIO_TO_IRQ(CSB726_GPIO_IRQ_SM501) #endif diff --git a/arch/arm/mach-pxa/include/mach/gpio-pxa.h b/arch/arm/mach-pxa/include/mach/gpio-pxa.h deleted file mode 100644 index 41b4c93a96c2..000000000000 --- a/arch/arm/mach-pxa/include/mach/gpio-pxa.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Written by Philipp Zabel <philipp.zabel@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#ifndef __MACH_PXA_GPIO_PXA_H -#define __MACH_PXA_GPIO_PXA_H - -#include <mach/irqs.h> -#include <mach/hardware.h> - -#define GPIO_REGS_VIRT io_p2v(0x40E00000) - -#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) -#define GPIO_REG(x) (*(volatile u32 *)(GPIO_REGS_VIRT + (x))) - -/* GPIO Pin Level Registers */ -#define GPLR0 GPIO_REG(BANK_OFF(0) + 0x00) -#define GPLR1 GPIO_REG(BANK_OFF(1) + 0x00) -#define GPLR2 GPIO_REG(BANK_OFF(2) + 0x00) -#define GPLR3 GPIO_REG(BANK_OFF(3) + 0x00) - -/* GPIO Pin Direction Registers */ -#define GPDR0 GPIO_REG(BANK_OFF(0) + 0x0c) -#define GPDR1 GPIO_REG(BANK_OFF(1) + 0x0c) -#define GPDR2 GPIO_REG(BANK_OFF(2) + 0x0c) -#define GPDR3 GPIO_REG(BANK_OFF(3) + 0x0c) - -/* GPIO Pin Output Set Registers */ -#define GPSR0 GPIO_REG(BANK_OFF(0) + 0x18) -#define GPSR1 GPIO_REG(BANK_OFF(1) + 0x18) -#define GPSR2 GPIO_REG(BANK_OFF(2) + 0x18) -#define GPSR3 GPIO_REG(BANK_OFF(3) + 0x18) - -/* GPIO Pin Output Clear Registers */ -#define GPCR0 GPIO_REG(BANK_OFF(0) + 0x24) -#define GPCR1 GPIO_REG(BANK_OFF(1) + 0x24) -#define GPCR2 GPIO_REG(BANK_OFF(2) + 0x24) -#define GPCR3 GPIO_REG(BANK_OFF(3) + 0x24) - -/* GPIO Rising Edge Detect Registers */ -#define GRER0 GPIO_REG(BANK_OFF(0) + 0x30) -#define GRER1 GPIO_REG(BANK_OFF(1) + 0x30) -#define GRER2 GPIO_REG(BANK_OFF(2) + 0x30) -#define GRER3 GPIO_REG(BANK_OFF(3) + 0x30) - -/* GPIO Falling Edge Detect Registers */ -#define GFER0 GPIO_REG(BANK_OFF(0) + 0x3c) -#define GFER1 GPIO_REG(BANK_OFF(1) + 0x3c) -#define GFER2 GPIO_REG(BANK_OFF(2) + 0x3c) -#define GFER3 GPIO_REG(BANK_OFF(3) + 0x3c) - -/* GPIO Edge Detect Status Registers */ -#define GEDR0 GPIO_REG(BANK_OFF(0) + 0x48) -#define GEDR1 GPIO_REG(BANK_OFF(1) + 0x48) -#define GEDR2 GPIO_REG(BANK_OFF(2) + 0x48) -#define GEDR3 GPIO_REG(BANK_OFF(3) + 0x48) - -/* GPIO Alternate Function Select Registers */ -#define GAFR0_L GPIO_REG(0x0054) -#define GAFR0_U GPIO_REG(0x0058) -#define GAFR1_L GPIO_REG(0x005C) -#define GAFR1_U GPIO_REG(0x0060) -#define GAFR2_L GPIO_REG(0x0064) -#define GAFR2_U GPIO_REG(0x0068) -#define GAFR3_L GPIO_REG(0x006C) -#define GAFR3_U GPIO_REG(0x0070) - -/* More handy macros. The argument is a literal GPIO number. */ - -#define GPIO_bit(x) (1 << ((x) & 0x1f)) - -#define GPLR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x00) -#define GPDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x0c) -#define GPSR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x18) -#define GPCR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x24) -#define GRER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x30) -#define GFER(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x3c) -#define GEDR(x) GPIO_REG(BANK_OFF((x) >> 5) + 0x48) -#define GAFR(x) GPIO_REG(0x54 + (((x) & 0x70) >> 2)) - - -#define NR_BUILTIN_GPIO PXA_GPIO_IRQ_NUM - -#define gpio_to_bank(gpio) ((gpio) >> 5) - -#ifdef CONFIG_CPU_PXA26x -/* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted, - * as well as their Alternate Function value being '1' for GPIO in GAFRx. - */ -static inline int __gpio_is_inverted(unsigned gpio) -{ - return cpu_is_pxa25x() && gpio > 85; -} -#else -static inline int __gpio_is_inverted(unsigned gpio) { return 0; } -#endif - -/* - * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate - * function of a GPIO, and GPDRx cannot be altered once configured. It - * is attributed as "occupied" here (I know this terminology isn't - * accurate, you are welcome to propose a better one :-) - */ -static inline int __gpio_is_occupied(unsigned gpio) -{ - if (cpu_is_pxa27x() || cpu_is_pxa25x()) { - int af = (GAFR(gpio) >> ((gpio & 0xf) * 2)) & 0x3; - int dir = GPDR(gpio) & GPIO_bit(gpio); - - if (__gpio_is_inverted(gpio)) - return af != 1 || dir == 0; - else - return af != 0 || dir != 0; - } else - return GPDR(gpio) & GPIO_bit(gpio); -} - -#include <plat/gpio-pxa.h> -#endif /* __MACH_PXA_GPIO_PXA_H */ diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h index 004cade7bb13..0248e433bc98 100644 --- a/arch/arm/mach-pxa/include/mach/gpio.h +++ b/arch/arm/mach-pxa/include/mach/gpio.h @@ -25,24 +25,8 @@ #define __ASM_ARCH_PXA_GPIO_H #include <asm-generic/gpio.h> -/* The defines for the driver are needed for the accelerated accessors */ -#include "gpio-pxa.h" -#define gpio_to_irq(gpio) IRQ_GPIO(gpio) +#include <mach/irqs.h> +#include <mach/hardware.h> -static inline int irq_to_gpio(unsigned int irq) -{ - int gpio; - - if (irq == IRQ_GPIO0 || irq == IRQ_GPIO1) - return irq - IRQ_GPIO0; - - gpio = irq - PXA_GPIO_IRQ_BASE; - if (gpio >= 2 && gpio < NR_BUILTIN_GPIO) - return gpio; - - return -1; -} - -#include <plat/gpio.h> #endif diff --git a/arch/arm/mach-pxa/include/mach/gumstix.h b/arch/arm/mach-pxa/include/mach/gumstix.h index 9b898680b206..dba14b6503ad 100644 --- a/arch/arm/mach-pxa/include/mach/gumstix.h +++ b/arch/arm/mach-pxa/include/mach/gumstix.h @@ -24,7 +24,7 @@ has detected a cable insertion; driven low otherwise. */ #define GPIO_GUMSTIX_USB_GPIOx 41 /* usb state change */ -#define GUMSTIX_USB_INTR_IRQ IRQ_GPIO(GPIO_GUMSTIX_USB_GPIOn) +#define GUMSTIX_USB_INTR_IRQ PXA_GPIO_TO_IRQ(GPIO_GUMSTIX_USB_GPIOn) #define GPIO_GUMSTIX_USB_GPIOn_MD (GPIO_GUMSTIX_USB_GPIOn | GPIO_IN) #define GPIO_GUMSTIX_USB_GPIOx_CON_MD (GPIO_GUMSTIX_USB_GPIOx | GPIO_OUT) @@ -35,7 +35,7 @@ has detected a cable insertion; driven low otherwise. */ */ #define GUMSTIX_GPIO_nSD_WP 22 /* SD Write Protect */ #define GUMSTIX_GPIO_nSD_DETECT 11 /* MMC/SD Card Detect */ -#define GUMSTIX_IRQ_GPIO_nSD_DETECT IRQ_GPIO(GUMSTIX_GPIO_nSD_DETECT) +#define GUMSTIX_IRQ_GPIO_nSD_DETECT PXA_GPIO_TO_IRQ(GUMSTIX_GPIO_nSD_DETECT) /* * SMC Ethernet definitions @@ -49,10 +49,10 @@ has detected a cable insertion; driven low otherwise. */ #define GPIO_GUMSTIX_ETH0 36 #define GPIO_GUMSTIX_ETH0_MD (GPIO_GUMSTIX_ETH0 | GPIO_IN) -#define GUMSTIX_ETH0_IRQ IRQ_GPIO(GPIO_GUMSTIX_ETH0) +#define GUMSTIX_ETH0_IRQ PXA_GPIO_TO_IRQ(GPIO_GUMSTIX_ETH0) #define GPIO_GUMSTIX_ETH1 27 #define GPIO_GUMSTIX_ETH1_MD (GPIO_GUMSTIX_ETH1 | GPIO_IN) -#define GUMSTIX_ETH1_IRQ IRQ_GPIO(GPIO_GUMSTIX_ETH1) +#define GUMSTIX_ETH1_IRQ PXA_GPIO_TO_IRQ(GPIO_GUMSTIX_ETH1) /* CF reset line */ @@ -63,18 +63,18 @@ has detected a cable insertion; driven low otherwise. */ #define GPIO4_nSTSCHG GPIO4_nBVD1 #define GPIO11_nCD 11 #define GPIO26_PRDY_nBSY 26 -#define GUMSTIX_S0_nSTSCHG_IRQ IRQ_GPIO(GPIO4_nSTSCHG) -#define GUMSTIX_S0_nCD_IRQ IRQ_GPIO(GPIO11_nCD) -#define GUMSTIX_S0_PRDY_nBSY_IRQ IRQ_GPIO(GPIO26_PRDY_nBSY) +#define GUMSTIX_S0_nSTSCHG_IRQ PXA_GPIO_TO_IRQ(GPIO4_nSTSCHG) +#define GUMSTIX_S0_nCD_IRQ PXA_GPIO_TO_IRQ(GPIO11_nCD) +#define GUMSTIX_S0_PRDY_nBSY_IRQ PXA_GPIO_TO_IRQ(GPIO26_PRDY_nBSY) /* CF slot 1 */ #define GPIO18_nBVD1 18 #define GPIO18_nSTSCHG GPIO18_nBVD1 #define GPIO36_nCD 36 #define GPIO27_PRDY_nBSY 27 -#define GUMSTIX_S1_nSTSCHG_IRQ IRQ_GPIO(GPIO18_nSTSCHG) -#define GUMSTIX_S1_nCD_IRQ IRQ_GPIO(GPIO36_nCD) -#define GUMSTIX_S1_PRDY_nBSY_IRQ IRQ_GPIO(GPIO27_PRDY_nBSY) +#define GUMSTIX_S1_nSTSCHG_IRQ PXA_GPIO_TO_IRQ(GPIO18_nSTSCHG) +#define GUMSTIX_S1_nCD_IRQ PXA_GPIO_TO_IRQ(GPIO36_nCD) +#define GUMSTIX_S1_PRDY_nBSY_IRQ PXA_GPIO_TO_IRQ(GPIO27_PRDY_nBSY) /* CF GPIO line modes */ #define GPIO4_nSTSCHG_MD (GPIO4_nSTSCHG | GPIO_IN) diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h index 37408449ec25..8bc02913517c 100644 --- a/arch/arm/mach-pxa/include/mach/hx4700.h +++ b/arch/arm/mach-pxa/include/mach/hx4700.h @@ -15,7 +15,7 @@ #include <linux/gpio.h> #include <linux/mfd/asic3.h> -#define HX4700_ASIC3_GPIO_BASE NR_BUILTIN_GPIO +#define HX4700_ASIC3_GPIO_BASE PXA_NR_BUILTIN_GPIO #define HX4700_EGPIO_BASE (HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS) #define HX4700_NR_IRQS (IRQ_BOARD_START + 70) diff --git a/arch/arm/mach-pxa/include/mach/idp.h b/arch/arm/mach-pxa/include/mach/idp.h index 5eff96fcc944..22a96f87232b 100644 --- a/arch/arm/mach-pxa/include/mach/idp.h +++ b/arch/arm/mach-pxa/include/mach/idp.h @@ -131,28 +131,26 @@ #define PCC_VS2 (1 << 1) #define PCC_VS1 (1 << 0) -#define PCC_DETECT(x) (GPLR(7 + (x)) & GPIO_bit(7 + (x))) - /* A listing of interrupts used by external hardware devices */ -#define TOUCH_PANEL_IRQ IRQ_GPIO(5) -#define IDE_IRQ IRQ_GPIO(21) +#define TOUCH_PANEL_IRQ PXA_GPIO_TO_IRQ(5) +#define IDE_IRQ PXA_GPIO_TO_IRQ(21) #define TOUCH_PANEL_IRQ_EDGE IRQ_TYPE_EDGE_FALLING -#define ETHERNET_IRQ IRQ_GPIO(4) +#define ETHERNET_IRQ PXA_GPIO_TO_IRQ(4) #define ETHERNET_IRQ_EDGE IRQ_TYPE_EDGE_RISING #define IDE_IRQ_EDGE IRQ_TYPE_EDGE_RISING -#define PCMCIA_S0_CD_VALID IRQ_GPIO(7) +#define PCMCIA_S0_CD_VALID PXA_GPIO_TO_IRQ(7) #define PCMCIA_S0_CD_VALID_EDGE IRQ_TYPE_EDGE_BOTH -#define PCMCIA_S1_CD_VALID IRQ_GPIO(8) +#define PCMCIA_S1_CD_VALID PXA_GPIO_TO_IRQ(8) #define PCMCIA_S1_CD_VALID_EDGE IRQ_TYPE_EDGE_BOTH -#define PCMCIA_S0_RDYINT IRQ_GPIO(19) -#define PCMCIA_S1_RDYINT IRQ_GPIO(22) +#define PCMCIA_S0_RDYINT PXA_GPIO_TO_IRQ(19) +#define PCMCIA_S1_RDYINT PXA_GPIO_TO_IRQ(22) /* diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h index 7cc5a781e99e..32975adf3ca4 100644 --- a/arch/arm/mach-pxa/include/mach/irqs.h +++ b/arch/arm/mach-pxa/include/mach/irqs.h @@ -88,10 +88,8 @@ #define IRQ_U2P PXA_IRQ(93) /* USB PHY D+/D- Lines (PXA935) */ #define PXA_GPIO_IRQ_BASE PXA_IRQ(96) -#define PXA_GPIO_IRQ_NUM (192) - -#define GPIO_2_x_TO_IRQ(x) (PXA_GPIO_IRQ_BASE + (x)) -#define IRQ_GPIO(x) (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x)) +#define PXA_NR_BUILTIN_GPIO (192) +#define PXA_GPIO_TO_IRQ(x) (PXA_GPIO_IRQ_BASE + (x)) /* * The following interrupts are for board specific purposes. Since @@ -100,7 +98,7 @@ * By default, no board IRQ is reserved. It should be finished in * custom board since sparse IRQ is already enabled. */ -#define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM) +#define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_NR_BUILTIN_GPIO) #define NR_IRQS (IRQ_BOARD_START) diff --git a/arch/arm/mach-pxa/include/mach/littleton.h b/arch/arm/mach-pxa/include/mach/littleton.h index b6238cbd8aea..8066be54e9f5 100644 --- a/arch/arm/mach-pxa/include/mach/littleton.h +++ b/arch/arm/mach-pxa/include/mach/littleton.h @@ -1,13 +1,11 @@ #ifndef __ASM_ARCH_LITTLETON_H #define __ASM_ARCH_LITTLETON_H -#include <mach/gpio-pxa.h> - #define LITTLETON_ETH_PHYS 0x30000000 #define LITTLETON_GPIO_LCD_CS (17) -#define EXT0_GPIO_BASE (NR_BUILTIN_GPIO) +#define EXT0_GPIO_BASE (PXA_NR_BUILTIN_GPIO) #define EXT0_GPIO(x) (EXT0_GPIO_BASE + (x)) #define LITTLETON_NR_IRQS (IRQ_BOARD_START + 8) diff --git a/arch/arm/mach-pxa/include/mach/magician.h b/arch/arm/mach-pxa/include/mach/magician.h index 7cbfc5d3f9df..ba6a6e1d29e9 100644 --- a/arch/arm/mach-pxa/include/mach/magician.h +++ b/arch/arm/mach-pxa/include/mach/magician.h @@ -78,7 +78,7 @@ * CPLD EGPIOs */ -#define MAGICIAN_EGPIO_BASE NR_BUILTIN_GPIO +#define MAGICIAN_EGPIO_BASE PXA_NR_BUILTIN_GPIO #define MAGICIAN_EGPIO(reg,bit) \ (MAGICIAN_EGPIO_BASE + 8*reg + bit) diff --git a/arch/arm/mach-pxa/include/mach/palmld.h b/arch/arm/mach-pxa/include/mach/palmld.h index ae536e86d8e8..2c4471336570 100644 --- a/arch/arm/mach-pxa/include/mach/palmld.h +++ b/arch/arm/mach-pxa/include/mach/palmld.h @@ -68,10 +68,10 @@ /* 20, 53 and 86 are usb related too */ /* INTERRUPTS */ -#define IRQ_GPIO_PALMLD_GPIO_RESET IRQ_GPIO(GPIO_NR_PALMLD_GPIO_RESET) -#define IRQ_GPIO_PALMLD_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMLD_SD_DETECT_N) -#define IRQ_GPIO_PALMLD_WM9712_IRQ IRQ_GPIO(GPIO_NR_PALMLD_WM9712_IRQ) -#define IRQ_GPIO_PALMLD_IDE_IRQ IRQ_GPIO(GPIO_NR_PALMLD_IDE_IRQ) +#define IRQ_GPIO_PALMLD_GPIO_RESET PXA_GPIO_TO_IRQ(GPIO_NR_PALMLD_GPIO_RESET) +#define IRQ_GPIO_PALMLD_SD_DETECT_N PXA_GPIO_TO_IRQ(GPIO_NR_PALMLD_SD_DETECT_N) +#define IRQ_GPIO_PALMLD_WM9712_IRQ PXA_GPIO_TO_IRQ(GPIO_NR_PALMLD_WM9712_IRQ) +#define IRQ_GPIO_PALMLD_IDE_IRQ PXA_GPIO_TO_IRQ(GPIO_NR_PALMLD_IDE_IRQ) /** HERE ARE INIT VALUES **/ diff --git a/arch/arm/mach-pxa/include/mach/palmt5.h b/arch/arm/mach-pxa/include/mach/palmt5.h index 6baf7469d4ec..0bd4f036c72f 100644 --- a/arch/arm/mach-pxa/include/mach/palmt5.h +++ b/arch/arm/mach-pxa/include/mach/palmt5.h @@ -48,10 +48,10 @@ #define GPIO_NR_PALMT5_BT_RESET 83 /* INTERRUPTS */ -#define IRQ_GPIO_PALMT5_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMT5_SD_DETECT_N) -#define IRQ_GPIO_PALMT5_WM9712_IRQ IRQ_GPIO(GPIO_NR_PALMT5_WM9712_IRQ) -#define IRQ_GPIO_PALMT5_USB_DETECT IRQ_GPIO(GPIO_NR_PALMT5_USB_DETECT) -#define IRQ_GPIO_PALMT5_GPIO_RESET IRQ_GPIO(GPIO_NR_PALMT5_GPIO_RESET) +#define IRQ_GPIO_PALMT5_SD_DETECT_N PXA_GPIO_TO_IRQ(GPIO_NR_PALMT5_SD_DETECT_N) +#define IRQ_GPIO_PALMT5_WM9712_IRQ PXA_GPIO_TO_IRQ(GPIO_NR_PALMT5_WM9712_IRQ) +#define IRQ_GPIO_PALMT5_USB_DETECT PXA_GPIO_TO_IRQ(GPIO_NR_PALMT5_USB_DETECT) +#define IRQ_GPIO_PALMT5_GPIO_RESET PXA_GPIO_TO_IRQ(GPIO_NR_PALMT5_GPIO_RESET) /** HERE ARE INIT VALUES **/ diff --git a/arch/arm/mach-pxa/include/mach/palmtc.h b/arch/arm/mach-pxa/include/mach/palmtc.h index 3f9dd3fd4638..c383a21680b6 100644 --- a/arch/arm/mach-pxa/include/mach/palmtc.h +++ b/arch/arm/mach-pxa/include/mach/palmtc.h @@ -52,8 +52,8 @@ #define GPIO_NR_PALMTC_IR_DISABLE 45 /* IRQs */ -#define IRQ_GPIO_PALMTC_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMTC_SD_DETECT_N) -#define IRQ_GPIO_PALMTC_WLAN_READY IRQ_GPIO(GPIO_NR_PALMTC_WLAN_READY) +#define IRQ_GPIO_PALMTC_SD_DETECT_N PXA_GPIO_TO_IRQ(GPIO_NR_PALMTC_SD_DETECT_N) +#define IRQ_GPIO_PALMTC_WLAN_READY PXA_GPIO_TO_IRQ(GPIO_NR_PALMTC_WLAN_READY) /* UCB1400 GPIOs */ #define GPIO_NR_PALMTC_POWER_DETECT (0x80 | 0x00) diff --git a/arch/arm/mach-pxa/include/mach/palmtx.h b/arch/arm/mach-pxa/include/mach/palmtx.h index 7074a6ed46c6..f2e530380253 100644 --- a/arch/arm/mach-pxa/include/mach/palmtx.h +++ b/arch/arm/mach-pxa/include/mach/palmtx.h @@ -62,10 +62,10 @@ #define GPIO_NR_PALMTX_NAND_BUFFER_DIR 79 /* INTERRUPTS */ -#define IRQ_GPIO_PALMTX_SD_DETECT_N IRQ_GPIO(GPIO_NR_PALMTX_SD_DETECT_N) -#define IRQ_GPIO_PALMTX_WM9712_IRQ IRQ_GPIO(GPIO_NR_PALMTX_WM9712_IRQ) -#define IRQ_GPIO_PALMTX_USB_DETECT IRQ_GPIO(GPIO_NR_PALMTX_USB_DETECT) -#define IRQ_GPIO_PALMTX_GPIO_RESET IRQ_GPIO(GPIO_NR_PALMTX_GPIO_RESET) +#define IRQ_GPIO_PALMTX_SD_DETECT_N PXA_GPIO_TO_IRQ(GPIO_NR_PALMTX_SD_DETECT_N) +#define IRQ_GPIO_PALMTX_WM9712_IRQ PXA_GPIO_TO_IRQ(GPIO_NR_PALMTX_WM9712_IRQ) +#define IRQ_GPIO_PALMTX_USB_DETECT PXA_GPIO_TO_IRQ(GPIO_NR_PALMTX_USB_DETECT) +#define IRQ_GPIO_PALMTX_GPIO_RESET PXA_GPIO_TO_IRQ(GPIO_NR_PALMTX_GPIO_RESET) /** HERE ARE INIT VALUES **/ diff --git a/arch/arm/mach-pxa/include/mach/pcm027.h b/arch/arm/mach-pxa/include/mach/pcm027.h index 4bac588478a8..6bf28de228bd 100644 --- a/arch/arm/mach-pxa/include/mach/pcm027.h +++ b/arch/arm/mach-pxa/include/mach/pcm027.h @@ -34,7 +34,7 @@ /* I2C RTC */ #define PCM027_RTC_IRQ_GPIO 0 -#define PCM027_RTC_IRQ IRQ_GPIO(PCM027_RTC_IRQ_GPIO) +#define PCM027_RTC_IRQ PXA_GPIO_TO_IRQ(PCM027_RTC_IRQ_GPIO) #define PCM027_RTC_IRQ_EDGE IRQ_TYPE_EDGE_FALLING #define ADR_PCM027_RTC 0x51 /* I2C address */ @@ -43,21 +43,21 @@ /* Ethernet chip (SMSC91C111) */ #define PCM027_ETH_IRQ_GPIO 52 -#define PCM027_ETH_IRQ IRQ_GPIO(PCM027_ETH_IRQ_GPIO) +#define PCM027_ETH_IRQ PXA_GPIO_TO_IRQ(PCM027_ETH_IRQ_GPIO) #define PCM027_ETH_IRQ_EDGE IRQ_TYPE_EDGE_RISING #define PCM027_ETH_PHYS PXA_CS5_PHYS #define PCM027_ETH_SIZE (1*1024*1024) /* CAN controller SJA1000 (unsupported yet) */ #define PCM027_CAN_IRQ_GPIO 114 -#define PCM027_CAN_IRQ IRQ_GPIO(PCM027_CAN_IRQ_GPIO) +#define PCM027_CAN_IRQ PXA_GPIO_TO_IRQ(PCM027_CAN_IRQ_GPIO) #define PCM027_CAN_IRQ_EDGE IRQ_TYPE_EDGE_FALLING #define PCM027_CAN_PHYS 0x22000000 #define PCM027_CAN_SIZE 0x100 /* SPI GPIO expander (unsupported yet) */ #define PCM027_EGPIO_IRQ_GPIO 27 -#define PCM027_EGPIO_IRQ IRQ_GPIO(PCM027_EGPIO_IRQ_GPIO) +#define PCM027_EGPIO_IRQ PXA_GPIO_TO_IRQ(PCM027_EGPIO_IRQ_GPIO) #define PCM027_EGPIO_IRQ_EDGE IRQ_TYPE_EDGE_FALLING #define PCM027_EGPIO_CS 24 /* diff --git a/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h b/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h index 8a4383b776d7..d72791695b26 100644 --- a/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h +++ b/arch/arm/mach-pxa/include/mach/pcm990_baseboard.h @@ -28,14 +28,14 @@ /* CPLD's interrupt controller is connected to PCM-027 GPIO 9 */ #define PCM990_CTRL_INT_IRQ_GPIO 9 -#define PCM990_CTRL_INT_IRQ IRQ_GPIO(PCM990_CTRL_INT_IRQ_GPIO) +#define PCM990_CTRL_INT_IRQ PXA_GPIO_TO_IRQ(PCM990_CTRL_INT_IRQ_GPIO) #define PCM990_CTRL_INT_IRQ_EDGE IRQ_TYPE_EDGE_RISING #define PCM990_CTRL_PHYS PXA_CS1_PHYS /* 16-Bit */ #define PCM990_CTRL_BASE 0xea000000 #define PCM990_CTRL_SIZE (1*1024*1024) #define PCM990_CTRL_PWR_IRQ_GPIO 14 -#define PCM990_CTRL_PWR_IRQ IRQ_GPIO(PCM990_CTRL_PWR_IRQ_GPIO) +#define PCM990_CTRL_PWR_IRQ PXA_GPIO_TO_IRQ(PCM990_CTRL_PWR_IRQ_GPIO) #define PCM990_CTRL_PWR_IRQ_EDGE IRQ_TYPE_EDGE_RISING /* visible CPLD (U7) registers */ @@ -132,7 +132,7 @@ * IDE */ #define PCM990_IDE_IRQ_GPIO 13 -#define PCM990_IDE_IRQ IRQ_GPIO(PCM990_IDE_IRQ_GPIO) +#define PCM990_IDE_IRQ PXA_GPIO_TO_IRQ(PCM990_IDE_IRQ_GPIO) #define PCM990_IDE_IRQ_EDGE IRQ_TYPE_EDGE_RISING #define PCM990_IDE_PLD_PHYS 0x20000000 /* 16 bit wide */ #define PCM990_IDE_PLD_BASE 0xee000000 @@ -188,11 +188,11 @@ * Compact Flash */ #define PCM990_CF_IRQ_GPIO 11 -#define PCM990_CF_IRQ IRQ_GPIO(PCM990_CF_IRQ_GPIO) +#define PCM990_CF_IRQ PXA_GPIO_TO_IRQ(PCM990_CF_IRQ_GPIO) #define PCM990_CF_IRQ_EDGE IRQ_TYPE_EDGE_RISING #define PCM990_CF_CD_GPIO 12 -#define PCM990_CF_CD IRQ_GPIO(PCM990_CF_CD_GPIO) +#define PCM990_CF_CD PXA_GPIO_TO_IRQ(PCM990_CF_CD_GPIO) #define PCM990_CF_CD_EDGE IRQ_TYPE_EDGE_RISING #define PCM990_CF_PLD_PHYS 0x30000000 /* 16 bit wide */ @@ -258,14 +258,14 @@ * Wolfson AC97 Touch */ #define PCM990_AC97_IRQ_GPIO 10 -#define PCM990_AC97_IRQ IRQ_GPIO(PCM990_AC97_IRQ_GPIO) +#define PCM990_AC97_IRQ PXA_GPIO_TO_IRQ(PCM990_AC97_IRQ_GPIO) #define PCM990_AC97_IRQ_EDGE IRQ_TYPE_EDGE_RISING /* * MMC phyCORE */ #define PCM990_MMC0_IRQ_GPIO 9 -#define PCM990_MMC0_IRQ IRQ_GPIO(PCM990_MMC0_IRQ_GPIO) +#define PCM990_MMC0_IRQ PXA_GPIO_TO_IRQ(PCM990_MMC0_IRQ_GPIO) #define PCM990_MMC0_IRQ_EDGE IRQ_TYPE_EDGE_FALLING /* diff --git a/arch/arm/mach-pxa/include/mach/poodle.h b/arch/arm/mach-pxa/include/mach/poodle.h index 83d1cfd00fc9..f32ff75dcca8 100644 --- a/arch/arm/mach-pxa/include/mach/poodle.h +++ b/arch/arm/mach-pxa/include/mach/poodle.h @@ -47,18 +47,18 @@ #define POODLE_GPIO_DISCHARGE_ON (42) /* Enable battery discharge */ /* PXA GPIOs */ -#define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO(0) -#define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO(1) -#define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO(4) -#define POODLE_IRQ_GPIO_CO IRQ_GPIO(16) -#define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO(5) -#define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO(11) -#define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO(10) -#define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO(17) -#define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO(14) -#define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO(8) -#define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9) -#define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(13) +#define POODLE_IRQ_GPIO_ON_KEY PXA_GPIO_TO_IRQ(0) +#define POODLE_IRQ_GPIO_AC_IN PXA_GPIO_TO_IRQ(1) +#define POODLE_IRQ_GPIO_HP_IN PXA_GPIO_TO_IRQ(4) +#define POODLE_IRQ_GPIO_CO PXA_GPIO_TO_IRQ(16) +#define POODLE_IRQ_GPIO_TP_INT PXA_GPIO_TO_IRQ(5) +#define POODLE_IRQ_GPIO_WAKEUP PXA_GPIO_TO_IRQ(11) +#define POODLE_IRQ_GPIO_GA_INT PXA_GPIO_TO_IRQ(10) +#define POODLE_IRQ_GPIO_CF_IRQ PXA_GPIO_TO_IRQ(17) +#define POODLE_IRQ_GPIO_CF_CD PXA_GPIO_TO_IRQ(14) +#define POODLE_IRQ_GPIO_nSD_INT PXA_GPIO_TO_IRQ(8) +#define POODLE_IRQ_GPIO_nSD_DETECT PXA_GPIO_TO_IRQ(9) +#define POODLE_IRQ_GPIO_MAIN_BAT_LOW PXA_GPIO_TO_IRQ(13) /* SCOOP GPIOs */ #define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11 @@ -71,7 +71,7 @@ #define POODLE_SCOOP_IO_DIR ( POODLE_SCOOP_VPEN | POODLE_SCOOP_HS_OUT ) #define POODLE_SCOOP_IO_OUT ( 0 ) -#define POODLE_SCOOP_GPIO_BASE (NR_BUILTIN_GPIO) +#define POODLE_SCOOP_GPIO_BASE (PXA_NR_BUILTIN_GPIO) #define POODLE_GPIO_CHARGE_ON (POODLE_SCOOP_GPIO_BASE + 0) #define POODLE_GPIO_CP401 (POODLE_SCOOP_GPIO_BASE + 2) #define POODLE_GPIO_VPEN (POODLE_SCOOP_GPIO_BASE + 7) diff --git a/arch/arm/mach-pxa/include/mach/spitz.h b/arch/arm/mach-pxa/include/mach/spitz.h index 685749a51c42..0bfe6507c95d 100644 --- a/arch/arm/mach-pxa/include/mach/spitz.h +++ b/arch/arm/mach-pxa/include/mach/spitz.h @@ -108,7 +108,7 @@ #define SPITZ_SCP_SUS_CLR (SPITZ_SCP_MUTE_L | SPITZ_SCP_MUTE_R | SPITZ_SCP_JK_A | SPITZ_SCP_ADC_TEMP_ON) #define SPITZ_SCP_SUS_SET 0 -#define SPITZ_SCP_GPIO_BASE (NR_BUILTIN_GPIO) +#define SPITZ_SCP_GPIO_BASE (PXA_NR_BUILTIN_GPIO) #define SPITZ_GPIO_LED_GREEN (SPITZ_SCP_GPIO_BASE + 0) #define SPITZ_GPIO_JK_B (SPITZ_SCP_GPIO_BASE + 1) #define SPITZ_GPIO_CHRG_ON (SPITZ_SCP_GPIO_BASE + 2) @@ -140,7 +140,7 @@ SPITZ_SCP2_BACKLIGHT_CONT | SPITZ_SCP2_BACKLIGHT_ON | SPITZ_SCP2_MIC_BIAS) #define SPITZ_SCP2_SUS_SET (SPITZ_SCP2_IR_ON | SPITZ_SCP2_RESERVED_1) -#define SPITZ_SCP2_GPIO_BASE (NR_BUILTIN_GPIO + 12) +#define SPITZ_SCP2_GPIO_BASE (PXA_NR_BUILTIN_GPIO + 12) #define SPITZ_GPIO_IR_ON (SPITZ_SCP2_GPIO_BASE + 0) #define SPITZ_GPIO_AKIN_PULLUP (SPITZ_SCP2_GPIO_BASE + 1) #define SPITZ_GPIO_RESERVED_1 (SPITZ_SCP2_GPIO_BASE + 2) @@ -152,7 +152,7 @@ #define SPITZ_GPIO_MIC_BIAS (SPITZ_SCP2_GPIO_BASE + 8) /* Akita IO Expander GPIOs */ -#define AKITA_IOEXP_GPIO_BASE (NR_BUILTIN_GPIO + 12) +#define AKITA_IOEXP_GPIO_BASE (PXA_NR_BUILTIN_GPIO + 12) #define AKITA_GPIO_RESERVED_0 (AKITA_IOEXP_GPIO_BASE + 0) #define AKITA_GPIO_RESERVED_1 (AKITA_IOEXP_GPIO_BASE + 1) #define AKITA_GPIO_MIC_BIAS (AKITA_IOEXP_GPIO_BASE + 2) @@ -164,23 +164,23 @@ /* Spitz IRQ Definitions */ -#define SPITZ_IRQ_GPIO_KEY_INT IRQ_GPIO(SPITZ_GPIO_KEY_INT) -#define SPITZ_IRQ_GPIO_AC_IN IRQ_GPIO(SPITZ_GPIO_AC_IN) -#define SPITZ_IRQ_GPIO_AK_INT IRQ_GPIO(SPITZ_GPIO_AK_INT) -#define SPITZ_IRQ_GPIO_HP_IN IRQ_GPIO(SPITZ_GPIO_HP_IN) -#define SPITZ_IRQ_GPIO_TP_INT IRQ_GPIO(SPITZ_GPIO_TP_INT) -#define SPITZ_IRQ_GPIO_SYNC IRQ_GPIO(SPITZ_GPIO_SYNC) -#define SPITZ_IRQ_GPIO_ON_KEY IRQ_GPIO(SPITZ_GPIO_ON_KEY) -#define SPITZ_IRQ_GPIO_SWA IRQ_GPIO(SPITZ_GPIO_SWA) -#define SPITZ_IRQ_GPIO_SWB IRQ_GPIO(SPITZ_GPIO_SWB) -#define SPITZ_IRQ_GPIO_BAT_COVER IRQ_GPIO(SPITZ_GPIO_BAT_COVER) -#define SPITZ_IRQ_GPIO_FATAL_BAT IRQ_GPIO(SPITZ_GPIO_FATAL_BAT) -#define SPITZ_IRQ_GPIO_CO IRQ_GPIO(SPITZ_GPIO_CO) -#define SPITZ_IRQ_GPIO_CF_IRQ IRQ_GPIO(SPITZ_GPIO_CF_IRQ) -#define SPITZ_IRQ_GPIO_CF_CD IRQ_GPIO(SPITZ_GPIO_CF_CD) -#define SPITZ_IRQ_GPIO_CF2_IRQ IRQ_GPIO(SPITZ_GPIO_CF2_IRQ) -#define SPITZ_IRQ_GPIO_nSD_INT IRQ_GPIO(SPITZ_GPIO_nSD_INT) -#define SPITZ_IRQ_GPIO_nSD_DETECT IRQ_GPIO(SPITZ_GPIO_nSD_DETECT) +#define SPITZ_IRQ_GPIO_KEY_INT PXA_GPIO_TO_IRQ(SPITZ_GPIO_KEY_INT) +#define SPITZ_IRQ_GPIO_AC_IN PXA_GPIO_TO_IRQ(SPITZ_GPIO_AC_IN) +#define SPITZ_IRQ_GPIO_AK_INT PXA_GPIO_TO_IRQ(SPITZ_GPIO_AK_INT) +#define SPITZ_IRQ_GPIO_HP_IN PXA_GPIO_TO_IRQ(SPITZ_GPIO_HP_IN) +#define SPITZ_IRQ_GPIO_TP_INT PXA_GPIO_TO_IRQ(SPITZ_GPIO_TP_INT) +#define SPITZ_IRQ_GPIO_SYNC PXA_GPIO_TO_IRQ(SPITZ_GPIO_SYNC) +#define SPITZ_IRQ_GPIO_ON_KEY PXA_GPIO_TO_IRQ(SPITZ_GPIO_ON_KEY) +#define SPITZ_IRQ_GPIO_SWA PXA_GPIO_TO_IRQ(SPITZ_GPIO_SWA) +#define SPITZ_IRQ_GPIO_SWB PXA_GPIO_TO_IRQ(SPITZ_GPIO_SWB) +#define SPITZ_IRQ_GPIO_BAT_COVER PXA_GPIO_TO_IRQ(SPITZ_GPIO_BAT_COVER) +#define SPITZ_IRQ_GPIO_FATAL_BAT PXA_GPIO_TO_IRQ(SPITZ_GPIO_FATAL_BAT) +#define SPITZ_IRQ_GPIO_CO PXA_GPIO_TO_IRQ(SPITZ_GPIO_CO) +#define SPITZ_IRQ_GPIO_CF_IRQ PXA_GPIO_TO_IRQ(SPITZ_GPIO_CF_IRQ) +#define SPITZ_IRQ_GPIO_CF_CD PXA_GPIO_TO_IRQ(SPITZ_GPIO_CF_CD) +#define SPITZ_IRQ_GPIO_CF2_IRQ PXA_GPIO_TO_IRQ(SPITZ_GPIO_CF2_IRQ) +#define SPITZ_IRQ_GPIO_nSD_INT PXA_GPIO_TO_IRQ(SPITZ_GPIO_nSD_INT) +#define SPITZ_IRQ_GPIO_nSD_DETECT PXA_GPIO_TO_IRQ(SPITZ_GPIO_nSD_DETECT) /* * Shared data structures diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h index 1272c4b56ceb..2bb0e862598c 100644 --- a/arch/arm/mach-pxa/include/mach/tosa.h +++ b/arch/arm/mach-pxa/include/mach/tosa.h @@ -24,7 +24,7 @@ /* * SCOOP2 internal GPIOs */ -#define TOSA_SCOOP_GPIO_BASE NR_BUILTIN_GPIO +#define TOSA_SCOOP_GPIO_BASE PXA_NR_BUILTIN_GPIO #define TOSA_SCOOP_PXA_VCORE1 SCOOP_GPCR_PA11 #define TOSA_GPIO_TC6393XB_REST_IN (TOSA_SCOOP_GPIO_BASE + 1) #define TOSA_GPIO_IR_POWERDWN (TOSA_SCOOP_GPIO_BASE + 2) @@ -42,7 +42,7 @@ /* * SCOOP2 jacket GPIOs */ -#define TOSA_SCOOP_JC_GPIO_BASE (NR_BUILTIN_GPIO + 12) +#define TOSA_SCOOP_JC_GPIO_BASE (PXA_NR_BUILTIN_GPIO + 12) #define TOSA_GPIO_BT_LED (TOSA_SCOOP_JC_GPIO_BASE + 0) #define TOSA_GPIO_NOTE_LED (TOSA_SCOOP_JC_GPIO_BASE + 1) #define TOSA_GPIO_CHRG_ERR_LED (TOSA_SCOOP_JC_GPIO_BASE + 2) @@ -59,7 +59,7 @@ /* * TC6393XB GPIOs */ -#define TOSA_TC6393XB_GPIO_BASE (NR_BUILTIN_GPIO + 2 * 12) +#define TOSA_TC6393XB_GPIO_BASE (PXA_NR_BUILTIN_GPIO + 2 * 12) #define TOSA_GPIO_TG_ON (TOSA_TC6393XB_GPIO_BASE + 0) #define TOSA_GPIO_L_MUTE (TOSA_TC6393XB_GPIO_BASE + 1) @@ -141,30 +141,30 @@ /* * Interrupts */ -#define TOSA_IRQ_GPIO_WAKEUP IRQ_GPIO(TOSA_GPIO_WAKEUP) -#define TOSA_IRQ_GPIO_AC_IN IRQ_GPIO(TOSA_GPIO_AC_IN) -#define TOSA_IRQ_GPIO_RECORD_BTN IRQ_GPIO(TOSA_GPIO_RECORD_BTN) -#define TOSA_IRQ_GPIO_SYNC IRQ_GPIO(TOSA_GPIO_SYNC) -#define TOSA_IRQ_GPIO_USB_IN IRQ_GPIO(TOSA_GPIO_USB_IN) -#define TOSA_IRQ_GPIO_JACKET_DETECT IRQ_GPIO(TOSA_GPIO_JACKET_DETECT) -#define TOSA_IRQ_GPIO_nSD_INT IRQ_GPIO(TOSA_GPIO_nSD_INT) -#define TOSA_IRQ_GPIO_nSD_DETECT IRQ_GPIO(TOSA_GPIO_nSD_DETECT) -#define TOSA_IRQ_GPIO_BAT1_CRG IRQ_GPIO(TOSA_GPIO_BAT1_CRG) -#define TOSA_IRQ_GPIO_CF_CD IRQ_GPIO(TOSA_GPIO_CF_CD) -#define TOSA_IRQ_GPIO_BAT0_CRG IRQ_GPIO(TOSA_GPIO_BAT0_CRG) -#define TOSA_IRQ_GPIO_TC6393XB_INT IRQ_GPIO(TOSA_GPIO_TC6393XB_INT) -#define TOSA_IRQ_GPIO_BAT0_LOW IRQ_GPIO(TOSA_GPIO_BAT0_LOW) -#define TOSA_IRQ_GPIO_EAR_IN IRQ_GPIO(TOSA_GPIO_EAR_IN) -#define TOSA_IRQ_GPIO_CF_IRQ IRQ_GPIO(TOSA_GPIO_CF_IRQ) -#define TOSA_IRQ_GPIO_ON_KEY IRQ_GPIO(TOSA_GPIO_ON_KEY) -#define TOSA_IRQ_GPIO_VGA_LINE IRQ_GPIO(TOSA_GPIO_VGA_LINE) -#define TOSA_IRQ_GPIO_TP_INT IRQ_GPIO(TOSA_GPIO_TP_INT) -#define TOSA_IRQ_GPIO_JC_CF_IRQ IRQ_GPIO(TOSA_GPIO_JC_CF_IRQ) -#define TOSA_IRQ_GPIO_BAT_LOCKED IRQ_GPIO(TOSA_GPIO_BAT_LOCKED) -#define TOSA_IRQ_GPIO_BAT1_LOW IRQ_GPIO(TOSA_GPIO_BAT1_LOW) -#define TOSA_IRQ_GPIO_KEY_SENSE(a) IRQ_GPIO(69+(a)) - -#define TOSA_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(TOSA_GPIO_MAIN_BAT_LOW) +#define TOSA_IRQ_GPIO_WAKEUP PXA_GPIO_TO_IRQ(TOSA_GPIO_WAKEUP) +#define TOSA_IRQ_GPIO_AC_IN PXA_GPIO_TO_IRQ(TOSA_GPIO_AC_IN) +#define TOSA_IRQ_GPIO_RECORD_BTN PXA_GPIO_TO_IRQ(TOSA_GPIO_RECORD_BTN) +#define TOSA_IRQ_GPIO_SYNC PXA_GPIO_TO_IRQ(TOSA_GPIO_SYNC) +#define TOSA_IRQ_GPIO_USB_IN PXA_GPIO_TO_IRQ(TOSA_GPIO_USB_IN) +#define TOSA_IRQ_GPIO_JACKET_DETECT PXA_GPIO_TO_IRQ(TOSA_GPIO_JACKET_DETECT) +#define TOSA_IRQ_GPIO_nSD_INT PXA_GPIO_TO_IRQ(TOSA_GPIO_nSD_INT) +#define TOSA_IRQ_GPIO_nSD_DETECT PXA_GPIO_TO_IRQ(TOSA_GPIO_nSD_DETECT) +#define TOSA_IRQ_GPIO_BAT1_CRG PXA_GPIO_TO_IRQ(TOSA_GPIO_BAT1_CRG) +#define TOSA_IRQ_GPIO_CF_CD PXA_GPIO_TO_IRQ(TOSA_GPIO_CF_CD) +#define TOSA_IRQ_GPIO_BAT0_CRG PXA_GPIO_TO_IRQ(TOSA_GPIO_BAT0_CRG) +#define TOSA_IRQ_GPIO_TC6393XB_INT PXA_GPIO_TO_IRQ(TOSA_GPIO_TC6393XB_INT) +#define TOSA_IRQ_GPIO_BAT0_LOW PXA_GPIO_TO_IRQ(TOSA_GPIO_BAT0_LOW) +#define TOSA_IRQ_GPIO_EAR_IN PXA_GPIO_TO_IRQ(TOSA_GPIO_EAR_IN) +#define TOSA_IRQ_GPIO_CF_IRQ PXA_GPIO_TO_IRQ(TOSA_GPIO_CF_IRQ) +#define TOSA_IRQ_GPIO_ON_KEY PXA_GPIO_TO_IRQ(TOSA_GPIO_ON_KEY) +#define TOSA_IRQ_GPIO_VGA_LINE PXA_GPIO_TO_IRQ(TOSA_GPIO_VGA_LINE) +#define TOSA_IRQ_GPIO_TP_INT PXA_GPIO_TO_IRQ(TOSA_GPIO_TP_INT) +#define TOSA_IRQ_GPIO_JC_CF_IRQ PXA_GPIO_TO_IRQ(TOSA_GPIO_JC_CF_IRQ) +#define TOSA_IRQ_GPIO_BAT_LOCKED PXA_GPIO_TO_IRQ(TOSA_GPIO_BAT_LOCKED) +#define TOSA_IRQ_GPIO_BAT1_LOW PXA_GPIO_TO_IRQ(TOSA_GPIO_BAT1_LOW) +#define TOSA_IRQ_GPIO_KEY_SENSE(a) PXA_GPIO_TO_IRQ(69+(a)) + +#define TOSA_IRQ_GPIO_MAIN_BAT_LOW PXA_GPIO_TO_IRQ(TOSA_GPIO_MAIN_BAT_LOW) #define TOSA_KEY_SYNC KEY_102ND /* ??? */ diff --git a/arch/arm/mach-pxa/include/mach/trizeps4.h b/arch/arm/mach-pxa/include/mach/trizeps4.h index 903e1a2e6641..d2ca01053f69 100644 --- a/arch/arm/mach-pxa/include/mach/trizeps4.h +++ b/arch/arm/mach-pxa/include/mach/trizeps4.h @@ -43,30 +43,30 @@ /* Ethernet Controller Davicom DM9000 */ #define GPIO_DM9000 101 -#define TRIZEPS4_ETH_IRQ IRQ_GPIO(GPIO_DM9000) +#define TRIZEPS4_ETH_IRQ PXA_GPIO_TO_IRQ(GPIO_DM9000) /* UCB1400 audio / TS-controller */ #define GPIO_UCB1400 1 -#define TRIZEPS4_UCB1400_IRQ IRQ_GPIO(GPIO_UCB1400) +#define TRIZEPS4_UCB1400_IRQ PXA_GPIO_TO_IRQ(GPIO_UCB1400) /* PCMCIA socket Compact Flash */ #define GPIO_PCD 11 /* PCMCIA Card Detect */ -#define TRIZEPS4_CD_IRQ IRQ_GPIO(GPIO_PCD) +#define TRIZEPS4_CD_IRQ PXA_GPIO_TO_IRQ(GPIO_PCD) #define GPIO_PRDY 13 /* READY / nINT */ -#define TRIZEPS4_READY_NINT IRQ_GPIO(GPIO_PRDY) +#define TRIZEPS4_READY_NINT PXA_GPIO_TO_IRQ(GPIO_PRDY) /* MMC socket */ #define GPIO_MMC_DET 12 -#define TRIZEPS4_MMC_IRQ IRQ_GPIO(GPIO_MMC_DET) +#define TRIZEPS4_MMC_IRQ PXA_GPIO_TO_IRQ(GPIO_MMC_DET) /* DOC NAND chip */ #define GPIO_DOC_LOCK 94 #define GPIO_DOC_IRQ 93 -#define TRIZEPS4_DOC_IRQ IRQ_GPIO(GPIO_DOC_IRQ) +#define TRIZEPS4_DOC_IRQ PXA_GPIO_TO_IRQ(GPIO_DOC_IRQ) /* SPI interface */ #define GPIO_SPI 53 -#define TRIZEPS4_SPI_IRQ IRQ_GPIO(GPIO_SPI) +#define TRIZEPS4_SPI_IRQ PXA_GPIO_TO_IRQ(GPIO_SPI) /* LEDS using tx2 / rx2 */ #define GPIO_SYS_BUSY_LED 46 @@ -74,7 +74,7 @@ /* Off-module PIC on ConXS board */ #define GPIO_PIC 0 -#define TRIZEPS4_PIC_IRQ IRQ_GPIO(GPIO_PIC) +#define TRIZEPS4_PIC_IRQ PXA_GPIO_TO_IRQ(GPIO_PIC) #ifdef CONFIG_MACH_TRIZEPS_CONXS /* for CONXS base board define these registers */ diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 532c5d3a97d2..5dae15ea6718 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -22,7 +22,6 @@ #include <mach/hardware.h> #include <mach/irqs.h> -#include <mach/gpio-pxa.h> #include "generic.h" @@ -92,44 +91,6 @@ static struct irq_chip pxa_internal_irq_chip = { .irq_unmask = pxa_unmask_irq, }; -/* - * GPIO IRQs for GPIO 0 and 1 - */ -static int pxa_set_low_gpio_type(struct irq_data *d, unsigned int type) -{ - int gpio = d->irq - IRQ_GPIO0; - - if (__gpio_is_occupied(gpio)) { - pr_err("%s failed: GPIO is configured\n", __func__); - return -EINVAL; - } - - if (type & IRQ_TYPE_EDGE_RISING) - GRER0 |= GPIO_bit(gpio); - else - GRER0 &= ~GPIO_bit(gpio); - - if (type & IRQ_TYPE_EDGE_FALLING) - GFER0 |= GPIO_bit(gpio); - else - GFER0 &= ~GPIO_bit(gpio); - - return 0; -} - -static void pxa_ack_low_gpio(struct irq_data *d) -{ - GEDR0 = (1 << (d->irq - IRQ_GPIO0)); -} - -static struct irq_chip pxa_low_gpio_chip = { - .name = "GPIO-l", - .irq_ack = pxa_ack_low_gpio, - .irq_mask = pxa_mask_irq, - .irq_unmask = pxa_unmask_irq, - .irq_set_type = pxa_set_low_gpio_type, -}; - asmlinkage void __exception_irq_entry icip_handle_irq(struct pt_regs *regs) { uint32_t icip, icmr, mask; @@ -160,26 +121,7 @@ asmlinkage void __exception_irq_entry ichp_handle_irq(struct pt_regs *regs) } while (1); } -static void __init pxa_init_low_gpio_irq(set_wake_t fn) -{ - int irq; - - /* clear edge detection on GPIO 0 and 1 */ - GFER0 &= ~0x3; - GRER0 &= ~0x3; - GEDR0 = 0x3; - - for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { - irq_set_chip_and_handler(irq, &pxa_low_gpio_chip, - handle_edge_irq); - irq_set_chip_data(irq, irq_base(0)); - set_irq_flags(irq, IRQF_VALID); - } - - pxa_low_gpio_chip.irq_set_wake = fn; -} - -void __init pxa_init_irq(int irq_nr, set_wake_t fn) +void __init pxa_init_irq(int irq_nr, int (*fn)(struct irq_data *, unsigned int)) { int irq, i, n; @@ -209,7 +151,6 @@ void __init pxa_init_irq(int irq_nr, set_wake_t fn) __raw_writel(1, irq_base(0) + ICCR); pxa_internal_irq_chip.irq_set_wake = fn; - pxa_init_low_gpio_irq(fn); } #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 7b324ec6449f..d21e28b46d81 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -124,8 +124,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)), - .end = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO90)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO90)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO90)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, } }; @@ -396,7 +396,7 @@ static struct i2c_board_info littleton_i2c_info[] = { .type = "da9034", .addr = 0x34, .platform_data = &littleton_da9034_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO18)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO18)), }, [1] = { .type = "max7320", diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index 1dd530279e0b..565dd2f2eaa2 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -152,8 +152,8 @@ static void __init lpd270_init_irq(void) handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - irq_set_chained_handler(IRQ_GPIO(0), lpd270_irq_handler); - irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING); + irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), lpd270_irq_handler); + irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING); } diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index c48ce6da9184..2fb2b50831d1 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -170,8 +170,8 @@ static void __init lubbock_init_irq(void) set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - irq_set_chained_handler(IRQ_GPIO(0), lubbock_irq_handler); - irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING); + irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), lubbock_irq_handler); + irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING); } #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index 4b796c37af3e..e340ea084248 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -184,8 +184,8 @@ static struct resource egpio_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ), - .end = gpio_to_irq(GPIO13_MAGICIAN_CPLD_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), .flags = IORESOURCE_IRQ, }, }; @@ -468,8 +468,8 @@ static struct resource pasic3_resources[] = { }, /* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */ [1] = { - .start = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ), - .end = gpio_to_irq(GPIO107_MAGICIAN_DS1WM_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 0567d3965fda..ea62a990ae4b 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -178,8 +178,8 @@ static void __init mainstone_init_irq(void) MST_INTMSKENA = 0; MST_INTSETCLR = 0; - irq_set_chained_handler(IRQ_GPIO(0), mainstone_irq_handler); - irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING); + irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), mainstone_irq_handler); + irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING); } #ifdef CONFIG_PM diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index 43a5f6861ca3..f14775536b83 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -13,6 +13,7 @@ * published by the Free Software Foundation. */ #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -20,7 +21,6 @@ #include <mach/pxa2xx-regs.h> #include <mach/mfp-pxa2xx.h> -#include <mach/gpio-pxa.h> #include "generic.h" @@ -29,6 +29,10 @@ #define GAFR_L(x) __GAFR(0, x) #define GAFR_U(x) __GAFR(1, x) +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) +#define GPLR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5)) +#define GPDR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x0c) + #define PWER_WE35 (1 << 24) struct gpio_desc { diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index b938fc2c316a..23f90c74c191 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -541,15 +541,15 @@ static struct pda_power_pdata power_pdata = { static struct resource power_resources[] = { [0] = { .name = "ac", - .start = gpio_to_irq(GPIO96_AC_DETECT), - .end = gpio_to_irq(GPIO96_AC_DETECT), + .start = PXA_GPIO_TO_IRQ(GPIO96_AC_DETECT), + .end = PXA_GPIO_TO_IRQ(GPIO96_AC_DETECT), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, }, [1] = { .name = "usb", - .start = gpio_to_irq(GPIO13_nUSB_DETECT), - .end = gpio_to_irq(GPIO13_nUSB_DETECT), + .start = PXA_GPIO_TO_IRQ(GPIO13_nUSB_DETECT), + .end = PXA_GPIO_TO_IRQ(GPIO13_nUSB_DETECT), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, }, diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c index 90928d6e1a5b..83570a79e7d2 100644 --- a/arch/arm/mach-pxa/mxm8x10.c +++ b/arch/arm/mach-pxa/mxm8x10.c @@ -417,8 +417,8 @@ static struct resource dm9k_resources[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO9)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO9)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO9)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO9)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE } }; diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 6d38c6548b3d..abab4e2b122c 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -378,7 +378,7 @@ struct pxacamera_platform_data pcm990_pxacamera_platform_data = { #include <linux/i2c/pca953x.h> static struct pca953x_platform_data pca9536_data = { - .gpio_base = NR_BUILTIN_GPIO, + .gpio_base = PXA_NR_BUILTIN_GPIO, }; static int gpio_bus_switch = -EINVAL; @@ -406,9 +406,9 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link) int ret; if (gpio_bus_switch < 0) { - ret = gpio_request(NR_BUILTIN_GPIO, "camera"); + ret = gpio_request(PXA_NR_BUILTIN_GPIO, "camera"); if (!ret) { - gpio_bus_switch = NR_BUILTIN_GPIO; + gpio_bus_switch = PXA_NR_BUILTIN_GPIO; gpio_direction_output(gpio_bus_switch, 0); } } diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 50c833177866..8ee4b6cfa385 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -166,8 +166,8 @@ static struct resource locomo_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_GPIO(10), - .end = IRQ_GPIO(10), + .start = PXA_GPIO_TO_IRQ(10), + .end = PXA_GPIO_TO_IRQ(10), .flags = IORESOURCE_IRQ, }, }; @@ -212,7 +212,7 @@ static struct spi_board_info poodle_spi_devices[] = { .bus_num = 1, .platform_data = &poodle_ads7846_info, .controller_data= &poodle_ads7846_chip, - .irq = gpio_to_irq(POODLE_GPIO_TP_INT), + .irq = PXA_GPIO_TO_IRQ(POODLE_GPIO_TP_INT), }, }; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 37b1d51b7ae5..adf058fa97ee 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -17,6 +17,7 @@ * need be. */ #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -289,7 +290,7 @@ static inline void pxa25x_init_pm(void) {} static int pxa25x_set_wake(struct irq_data *d, unsigned int on) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); uint32_t mask = 0; if (gpio >= 0 && gpio < 85) @@ -314,14 +315,12 @@ set_pwer: void __init pxa25x_init_irq(void) { pxa_init_irq(32, pxa25x_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 84, pxa25x_set_wake); } #ifdef CONFIG_CPU_PXA26x void __init pxa26x_init_irq(void) { pxa_init_irq(32, pxa25x_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 89, pxa25x_set_wake); } #endif diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index e47fbe2de773..180bd8675d4b 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> @@ -357,7 +358,7 @@ static inline void pxa27x_init_pm(void) {} */ static int pxa27x_set_wake(struct irq_data *d, unsigned int on) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); uint32_t mask; if (gpio >= 0 && gpio < 128) @@ -388,7 +389,6 @@ static int pxa27x_set_wake(struct irq_data *d, unsigned int on) void __init pxa27x_init_irq(void) { pxa_init_irq(34, pxa27x_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 120, pxa27x_set_wake); } static struct map_desc pxa27x_io_desc[] __initdata = { @@ -424,6 +424,7 @@ void __init pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { + &pxa_device_gpio, &pxa27x_device_udc, &pxa_device_pmu, &pxa_device_i2s, diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 89675e354d9f..f107c71c7589 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -25,7 +25,6 @@ #include <asm/mach/map.h> #include <asm/suspend.h> #include <mach/hardware.h> -#include <mach/gpio-pxa.h> #include <mach/pxa3xx-regs.h> #include <mach/reset.h> #include <mach/ohci.h> @@ -56,6 +55,7 @@ static DEFINE_PXA3_CKEN(pxa3xx_pwm0, PWM0, 13000000, 0); static DEFINE_PXA3_CKEN(pxa3xx_pwm1, PWM1, 13000000, 0); static DEFINE_PXA3_CKEN(pxa3xx_mmc1, MMC1, 19500000, 0); static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0); +static DEFINE_PXA3_CKEN(pxa3xx_gpio, GPIO, 13000000, 0); static DEFINE_CK(pxa3xx_lcd, LCD, &clk_pxa3xx_hsio_ops); static DEFINE_CK(pxa3xx_smemc, SMC, &clk_pxa3xx_smemc_ops); @@ -89,6 +89,7 @@ static struct clk_lookup pxa3xx_clkregs[] = { INIT_CLKREG(&clk_pxa3xx_mmc1, "pxa2xx-mci.0", NULL), INIT_CLKREG(&clk_pxa3xx_mmc2, "pxa2xx-mci.1", NULL), INIT_CLKREG(&clk_pxa3xx_smemc, "pxa2xx-pcmcia", NULL), + INIT_CLKREG(&clk_pxa3xx_gpio, "pxa-gpio", NULL), }; #ifdef CONFIG_PM @@ -366,7 +367,8 @@ static struct irq_chip pxa_ext_wakeup_chip = { .irq_set_type = pxa_set_ext_wakeup_type, }; -static void __init pxa_init_ext_wakeup_irq(set_wake_t fn) +static void __init pxa_init_ext_wakeup_irq(int (*fn)(struct irq_data *, + unsigned int)) { int irq; @@ -389,7 +391,6 @@ void __init pxa3xx_init_irq(void) pxa_init_irq(56, pxa3xx_set_wake); pxa_init_ext_wakeup_irq(pxa3xx_set_wake); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL); } static struct map_desc pxa3xx_io_desc[] __initdata = { @@ -418,6 +419,7 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { + &pxa_device_gpio, &pxa27x_device_udc, &pxa_device_pmu, &pxa_device_i2s, diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c index 210b722e0615..fccc644702e6 100644 --- a/arch/arm/mach-pxa/pxa95x.c +++ b/arch/arm/mach-pxa/pxa95x.c @@ -20,7 +20,6 @@ #include <linux/syscore_ops.h> #include <mach/hardware.h> -#include <mach/gpio-pxa.h> #include <mach/pxa3xx-regs.h> #include <mach/pxa930.h> #include <mach/reset.h> @@ -212,6 +211,7 @@ static DEFINE_PXA3_CKEN(pxa95x_ssp3, SSP3, 13000000, 0); static DEFINE_PXA3_CKEN(pxa95x_ssp4, SSP4, 13000000, 0); static DEFINE_PXA3_CKEN(pxa95x_pwm0, PWM0, 13000000, 0); static DEFINE_PXA3_CKEN(pxa95x_pwm1, PWM1, 13000000, 0); +static DEFINE_PXA3_CKEN(pxa95x_gpio, GPIO, 13000000, 0); static struct clk_lookup pxa95x_clkregs[] = { INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"), @@ -231,12 +231,12 @@ static struct clk_lookup pxa95x_clkregs[] = { INIT_CLKREG(&clk_pxa95x_ssp4, "pxa27x-ssp.3", NULL), INIT_CLKREG(&clk_pxa95x_pwm0, "pxa27x-pwm.0", NULL), INIT_CLKREG(&clk_pxa95x_pwm1, "pxa27x-pwm.1", NULL), + INIT_CLKREG(&clk_pxa95x_gpio, "pxa-gpio", NULL), }; void __init pxa95x_init_irq(void) { pxa_init_irq(96, NULL); - pxa_init_gpio(IRQ_GPIO_2_x, 2, 127, NULL); } /* @@ -249,6 +249,7 @@ void __init pxa95x_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { + &pxa_device_gpio, &sa1100_device_rtc, &pxa_device_rtc, &pxa27x_device_ssp1, diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index f0c05f4d12ed..78d643783f99 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -292,8 +292,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, { - .start = gpio_to_irq(GPIO_ETH_IRQ), - .end = gpio_to_irq(GPIO_ETH_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO_ETH_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO_ETH_IRQ), .flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING, } }; @@ -672,7 +672,7 @@ static struct lis3lv02d_platform_data lis3_pdata = { .chip_select = 1, \ .controller_data = (void *) GPIO_ACCEL_CS, \ .platform_data = &lis3_pdata, \ - .irq = gpio_to_irq(GPIO_ACCEL_IRQ), \ + .irq = PXA_GPIO_TO_IRQ(GPIO_ACCEL_IRQ), \ } #define SPI_DAC7512 \ @@ -956,7 +956,7 @@ static struct eeti_ts_platform_data eeti_ts_pdata = { static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { .type = "eeti_ts", .addr = 0x0a, - .irq = gpio_to_irq(GPIO_TOUCH_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ), .platform_data = &eeti_ts_pdata, }; diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c index fc2c1e05af9c..423ec899a8a8 100644 --- a/arch/arm/mach-pxa/saar.c +++ b/arch/arm/mach-pxa/saar.c @@ -96,8 +96,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO97)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO97)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO97)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; @@ -502,7 +502,7 @@ static struct i2c_board_info saar_i2c_info[] = { .type = "da9034", .addr = 0x34, .platform_data = &saar_da9034_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)), }, }; diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c index 3e999e308a2d..d1cdd6a081ed 100644 --- a/arch/arm/mach-pxa/saarb.c +++ b/arch/arm/mach-pxa/saarb.c @@ -92,7 +92,7 @@ static struct i2c_board_info saarb_i2c_info[] = { .type = "88PM860x", .addr = 0x34, .platform_data = &saarb_pm8607_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)), }, }; diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 785880f67b60..8d5168d253a9 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -907,24 +907,24 @@ static int __devinit sharpsl_pm_probe(struct platform_device *pdev) gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock); /* Register interrupt handlers */ - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) { - dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); + if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) { + dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_acin)); } - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) { - dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); + if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) { + dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batlock)); } if (sharpsl_pm.machinfo->gpio_fatal) { - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) { - dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); + if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) { + dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_fatal)); } } if (sharpsl_pm.machinfo->batfull_irq) { /* Register interrupt handler. */ - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) { - dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull)); + if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) { + dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batfull)); } } @@ -953,14 +953,14 @@ static int sharpsl_pm_remove(struct platform_device *pdev) led_trigger_unregister_simple(sharpsl_charge_led_trigger); - free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); - free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); + free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); + free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); if (sharpsl_pm.machinfo->gpio_fatal) - free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); + free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr); if (sharpsl_pm.machinfo->batfull_irq) - free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); + free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); gpio_free(sharpsl_pm.machinfo->gpio_batlock); gpio_free(sharpsl_pm.machinfo->gpio_batfull); diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 953a9195f9e5..1b39cec03cce 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -552,7 +552,7 @@ static struct spi_board_info spitz_spi_devices[] = { .chip_select = 0, .platform_data = &spitz_ads7846_info, .controller_data = &spitz_ads7846_chip, - .irq = gpio_to_irq(SPITZ_GPIO_TP_INT), + .irq = PXA_GPIO_TO_IRQ(SPITZ_GPIO_TP_INT), }, { .modalias = "corgi-lcd", .max_speed_hz = 50000, diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 094279aefe9c..34cbdac51525 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -15,6 +15,7 @@ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/apm-emulation.h> @@ -41,6 +42,7 @@ static int spitz_last_ac_status; static struct gpio spitz_charger_gpios[] = { { SPITZ_GPIO_KEY_INT, GPIOF_IN, "Keyboard Interrupt" }, { SPITZ_GPIO_SYNC, GPIOF_IN, "Sync" }, + { SPITZ_GPIO_AC_IN, GPIOF_IN, "Charger Detection" }, { SPITZ_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" }, { SPITZ_GPIO_JK_B, GPIOF_OUT_INIT_LOW, "JK B" }, { SPITZ_GPIO_CHRG_ON, GPIOF_OUT_INIT_LOW, "Charger On" }, @@ -169,14 +171,19 @@ static int spitz_should_wakeup(unsigned int resume_on_alarm) static unsigned long spitz_charger_wakeup(void) { - return (~GPLR0 & GPIO_bit(SPITZ_GPIO_KEY_INT)) | (GPLR0 & GPIO_bit(SPITZ_GPIO_SYNC)); + unsigned long ret; + ret = (!gpio_get_value(SPITZ_GPIO_KEY_INT) + << GPIO_bit(SPITZ_GPIO_KEY_INT)) + | (!gpio_get_value(SPITZ_GPIO_SYNC) + << GPIO_bit(SPITZ_GPIO_SYNC)); + return ret; } unsigned long spitzpm_read_devdata(int type) { switch (type) { case SHARPSL_STATUS_ACIN: - return (((~GPLR(SPITZ_GPIO_AC_IN)) & GPIO_bit(SPITZ_GPIO_AC_IN)) != 0); + return !gpio_get_value(SPITZ_GPIO_AC_IN); case SHARPSL_STATUS_LOCK: return gpio_get_value(sharpsl_pm.machinfo->gpio_batlock); case SHARPSL_STATUS_CHRGFULL: diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index 4c9a48bef569..940ca56b37f9 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -376,7 +376,7 @@ static struct spi_board_info spi_board_info[] __initdata = { .bus_num = 1, .chip_select = 0, .controller_data = &staccel_chip_info, - .irq = IRQ_GPIO(96), + .irq = PXA_GPIO_TO_IRQ(96), }, { .modalias = "cc2420", .max_speed_hz = 6500000, @@ -546,7 +546,7 @@ static struct i2c_board_info __initdata imote2_pwr_i2c_board_info[] = { .type = "da9030", .addr = 0x49, .platform_data = &imote2_da9030_pdata, - .irq = gpio_to_irq(1), + .irq = PXA_GPIO_TO_IRQ(1), }, }; @@ -560,18 +560,18 @@ static struct i2c_board_info __initdata imote2_i2c_board_info[] = { /* Through a nand gate - Also beware, on V2 sensor board the * pull up resistors are missing. */ - .irq = IRQ_GPIO(99), + .irq = PXA_GPIO_TO_IRQ(99), }, { /* ITS400 Sensor board only */ .type = "tsl2561", .addr = 0x49, /* Through a nand gate - Also beware, on V2 sensor board the * pull up resistors are missing. */ - .irq = IRQ_GPIO(99), + .irq = PXA_GPIO_TO_IRQ(99), }, { /* ITS400 Sensor board only */ .type = "tmp175", .addr = 0x4A, - .irq = IRQ_GPIO(96), + .irq = PXA_GPIO_TO_IRQ(96), }, { /* IMB400 Multimedia board */ .type = "wm8940", .addr = 0x1A, @@ -661,8 +661,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = IRQ_GPIO(40), - .end = IRQ_GPIO(40), + .start = PXA_GPIO_TO_IRQ(40), + .end = PXA_GPIO_TO_IRQ(40), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; @@ -707,7 +707,7 @@ static int stargate2_mci_init(struct device *dev, } gpio_direction_input(SG2_GPIO_nSD_DETECT); - err = request_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), + err = request_irq(PXA_GPIO_TO_IRQ(SG2_GPIO_nSD_DETECT), stargate2_detect_int, IRQ_TYPE_EDGE_BOTH, "MMC card detect", @@ -738,7 +738,7 @@ static void stargate2_mci_setpower(struct device *dev, unsigned int vdd) static void stargate2_mci_exit(struct device *dev, void *data) { - free_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), data); + free_irq(PXA_GPIO_TO_IRQ(SG2_GPIO_nSD_DETECT), data); gpio_free(SG2_SD_POWER_ENABLE); gpio_free(SG2_GPIO_nSD_DETECT); } @@ -913,7 +913,7 @@ static struct i2c_board_info __initdata stargate2_pwr_i2c_board_info[] = { .type = "da9030", .addr = 0x49, .platform_data = &stargate2_da9030_pdata, - .irq = gpio_to_irq(1), + .irq = PXA_GPIO_TO_IRQ(1), }, }; @@ -938,18 +938,18 @@ static struct i2c_board_info __initdata stargate2_i2c_board_info[] = { /* Through a nand gate - Also beware, on V2 sensor board the * pull up resistors are missing. */ - .irq = IRQ_GPIO(99), + .irq = PXA_GPIO_TO_IRQ(99), }, { /* ITS400 Sensor board only */ .type = "tsl2561", .addr = 0x49, /* Through a nand gate - Also beware, on V2 sensor board the * pull up resistors are missing. */ - .irq = IRQ_GPIO(99), + .irq = PXA_GPIO_TO_IRQ(99), }, { /* ITS400 Sensor board only */ .type = "tmp175", .addr = 0x4A, - .irq = IRQ_GPIO(96), + .irq = PXA_GPIO_TO_IRQ(96), }, }; diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c index ad47bb98f30d..43bdcb9761f2 100644 --- a/arch/arm/mach-pxa/tavorevb.c +++ b/arch/arm/mach-pxa/tavorevb.c @@ -85,8 +85,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)), - .end = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO47)), + .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO47)), + .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO47)), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, } }; diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c index fd569167302a..46c60b3cbe79 100644 --- a/arch/arm/mach-pxa/tavorevb3.c +++ b/arch/arm/mach-pxa/tavorevb3.c @@ -101,7 +101,7 @@ static struct i2c_board_info evb3_i2c_info[] = { .type = "88PM860x", .addr = 0x34, .platform_data = &evb3_pm8607_info, - .irq = gpio_to_irq(mfp_to_gpio(MFP_PIN_GPIO83)), + .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)), }, }; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 402b0c96613b..1ddb9826448a 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -404,8 +404,8 @@ static struct pda_power_pdata tosa_power_data = { static struct resource tosa_power_resource[] = { { .name = "ac", - .start = gpio_to_irq(TOSA_GPIO_AC_IN), - .end = gpio_to_irq(TOSA_GPIO_AC_IN), + .start = PXA_GPIO_TO_IRQ(TOSA_GPIO_AC_IN), + .end = PXA_GPIO_TO_IRQ(TOSA_GPIO_AC_IN), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index 242ddae332d3..d9a653a77176 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -422,8 +422,8 @@ static struct resource smc91x_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = gpio_to_irq(VIPER_ETH_GPIO), - .end = gpio_to_irq(VIPER_ETH_GPIO), + .start = PXA_GPIO_TO_IRQ(VIPER_ETH_GPIO), + .end = PXA_GPIO_TO_IRQ(VIPER_ETH_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, }, [2] = { @@ -546,7 +546,7 @@ static struct plat_serial8250_port serial_platform_data[] = { /* External UARTs */ { .mapbase = VIPER_UARTA_PHYS, - .irq = gpio_to_irq(VIPER_UARTA_GPIO), + .irq = PXA_GPIO_TO_IRQ(VIPER_UARTA_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 1843200, .regshift = 1, @@ -556,7 +556,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { .mapbase = VIPER_UARTB_PHYS, - .irq = gpio_to_irq(VIPER_UARTB_GPIO), + .irq = PXA_GPIO_TO_IRQ(VIPER_UARTB_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 1843200, .regshift = 1, @@ -596,8 +596,8 @@ static struct resource isp116x_resources[] = { .flags = IORESOURCE_MEM, }, [2] = { - .start = gpio_to_irq(VIPER_USB_GPIO), - .end = gpio_to_irq(VIPER_USB_GPIO), + .start = PXA_GPIO_TO_IRQ(VIPER_USB_GPIO), + .end = PXA_GPIO_TO_IRQ(VIPER_USB_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, }, }; diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index ca0c6615028c..9edeec65f6a3 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -395,8 +395,8 @@ static struct resource vpac270_dm9000_resources[] = { .flags = IORESOURCE_MEM, }, [2] = { - .start = IRQ_GPIO(GPIO114_VPAC270_ETH_IRQ), - .end = IRQ_GPIO(GPIO114_VPAC270_ETH_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO114_VPAC270_ETH_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO114_VPAC270_ETH_IRQ), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, }, }; @@ -433,7 +433,7 @@ static pxa2xx_audio_ops_t vpac270_ac97_pdata = { }; static struct ucb1400_pdata vpac270_ucb1400_pdata = { - .irq = IRQ_GPIO(GPIO113_VPAC270_TS_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO113_VPAC270_TS_IRQ), }; static struct platform_device vpac270_ucb1400_device = { @@ -610,8 +610,8 @@ static struct resource vpac270_ide_resources[] = { .flags = IORESOURCE_DMA }, [3] = { /* IDE IRQ pin */ - .start = gpio_to_irq(GPIO36_VPAC270_IDE_IRQ), - .end = gpio_to_irq(GPIO36_VPAC270_IDE_IRQ), + .start = PXA_GPIO_TO_IRQ(GPIO36_VPAC270_IDE_IRQ), + .end = PXA_GPIO_TO_IRQ(GPIO36_VPAC270_IDE_IRQ), .flags = IORESOURCE_IRQ } }; diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index ead32c90fec1..424661833ce2 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -573,7 +573,7 @@ static struct spi_board_info spi_board_info[] __initdata = { .modalias = "libertas_spi", .platform_data = &z2_lbs_pdata, .controller_data = &z2_lbs_chip_info, - .irq = gpio_to_irq(GPIO36_ZIPITZ2_WIFI_IRQ), + .irq = PXA_GPIO_TO_IRQ(GPIO36_ZIPITZ2_WIFI_IRQ), .max_speed_hz = 13000000, .bus_num = 1, .chip_select = 0, diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 498b83b089f3..68de9c17e4c5 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -233,7 +233,7 @@ static struct plat_serial8250_port serial_platform_data[] = { /* FIXME: Shared IRQs on COM1-COM4 will not work properly on v1i1 hardware. */ { /* COM1 */ .mapbase = 0x10000000, - .irq = gpio_to_irq(ZEUS_UARTA_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTA_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -242,7 +242,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { /* COM2 */ .mapbase = 0x10800000, - .irq = gpio_to_irq(ZEUS_UARTB_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTB_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -251,7 +251,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { /* COM3 */ .mapbase = 0x11000000, - .irq = gpio_to_irq(ZEUS_UARTC_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTC_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -260,7 +260,7 @@ static struct plat_serial8250_port serial_platform_data[] = { }, { /* COM4 */ .mapbase = 0x11800000, - .irq = gpio_to_irq(ZEUS_UARTD_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_UARTD_GPIO), .irqflags = IRQF_TRIGGER_RISING, .uartclk = 14745600, .regshift = 1, @@ -321,8 +321,8 @@ static struct resource zeus_dm9k0_resource[] = { .flags = IORESOURCE_MEM }, [2] = { - .start = gpio_to_irq(ZEUS_ETH0_GPIO), - .end = gpio_to_irq(ZEUS_ETH0_GPIO), + .start = PXA_GPIO_TO_IRQ(ZEUS_ETH0_GPIO), + .end = PXA_GPIO_TO_IRQ(ZEUS_ETH0_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; @@ -339,8 +339,8 @@ static struct resource zeus_dm9k1_resource[] = { .flags = IORESOURCE_MEM, }, [2] = { - .start = gpio_to_irq(ZEUS_ETH1_GPIO), - .end = gpio_to_irq(ZEUS_ETH1_GPIO), + .start = PXA_GPIO_TO_IRQ(ZEUS_ETH1_GPIO), + .end = PXA_GPIO_TO_IRQ(ZEUS_ETH1_GPIO), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; @@ -423,7 +423,7 @@ static struct spi_board_info zeus_spi_board_info[] = { [0] = { .modalias = "mcp2515", .platform_data = &zeus_mcp2515_pdata, - .irq = gpio_to_irq(ZEUS_CAN_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_CAN_GPIO), .max_speed_hz = 1*1000*1000, .bus_num = 3, .mode = SPI_MODE_0, @@ -753,7 +753,7 @@ static struct i2c_board_info __initdata zeus_i2c_devices[] = { { I2C_BOARD_INFO("pca9535", 0x20), .platform_data = &zeus_pca953x_pdata[2], - .irq = gpio_to_irq(ZEUS_EXTGPIO_GPIO), + .irq = PXA_GPIO_TO_IRQ(ZEUS_EXTGPIO_GPIO), }, { I2C_BOARD_INFO("lm75a", 0x48) }, { I2C_BOARD_INFO("24c01", 0x50) }, diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 6c39c3328418..a4c807527095 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -408,8 +408,8 @@ static void __init zylonite_init(void) * Note: We depend that the bootloader set * the correct value to MSC register for SMC91x. */ - smc91x_resources[1].start = gpio_to_irq(gpio_eth_irq); - smc91x_resources[1].end = gpio_to_irq(gpio_eth_irq); + smc91x_resources[1].start = PXA_GPIO_TO_IRQ(gpio_eth_irq); + smc91x_resources[1].end = PXA_GPIO_TO_IRQ(gpio_eth_irq); platform_device_register(&smc91x_device); pxa_set_ac97_info(NULL); diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c index 93c64d8d7de9..86e59c043de2 100644 --- a/arch/arm/mach-pxa/zylonite_pxa300.c +++ b/arch/arm/mach-pxa/zylonite_pxa300.c @@ -231,12 +231,12 @@ static struct i2c_board_info zylonite_i2c_board_info[] = { .type = "pca9539", .addr = 0x74, .platform_data = &gpio_exp[0], - .irq = IRQ_GPIO(18), + .irq = PXA_GPIO_TO_IRQ(18), }, { .type = "pca9539", .addr = 0x75, .platform_data = &gpio_exp[1], - .irq = IRQ_GPIO(19), + .irq = PXA_GPIO_TO_IRQ(19), }, }; diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index a20ae1ad4062..71b955877793 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -164,22 +164,6 @@ static struct map_desc bast_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c24xx_uart_clksrc bast_serial_clocks[] = { - [0] = { - .name = "uclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "pclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - } -}; - - static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { [0] = { .hwport = 0, @@ -187,8 +171,6 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = bast_serial_clocks, - .clocks_size = ARRAY_SIZE(bast_serial_clocks), }, [1] = { .hwport = 1, @@ -196,8 +178,6 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = bast_serial_clocks, - .clocks_size = ARRAY_SIZE(bast_serial_clocks), }, /* port 2 is not actually used */ [2] = { @@ -206,8 +186,6 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = bast_serial_clocks, - .clocks_size = ARRAY_SIZE(bast_serial_clocks), } }; diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index df47e8e90065..0f0a9a1795e9 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -109,23 +109,6 @@ static struct map_desc vr1000_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -/* uart clock source(s) */ - -static struct s3c24xx_uart_clksrc vr1000_serial_clocks[] = { - [0] = { - .name = "uclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "pclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0. - } -}; - static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { [0] = { .hwport = 0, @@ -133,8 +116,6 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = vr1000_serial_clocks, - .clocks_size = ARRAY_SIZE(vr1000_serial_clocks), }, [1] = { .hwport = 1, @@ -142,8 +123,6 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = vr1000_serial_clocks, - .clocks_size = ARRAY_SIZE(vr1000_serial_clocks), }, /* port 2 is not actually used */ [2] = { @@ -152,9 +131,6 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = vr1000_serial_clocks, - .clocks_size = ARRAY_SIZE(vr1000_serial_clocks), - } }; diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 3d7ebc557a72..af74927bca14 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -123,12 +123,18 @@ static struct clk s3c2410_armclk = { .id = -1, }; +static struct clk_lookup s3c2410_clk_lookup[] = { + CLKDEV_INIT(NULL, "clk_uart_baud0", &clk_p), + CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), +}; + void __init s3c2410_init_clocks(int xtal) { s3c24xx_register_baseclocks(xtal); s3c2410_setup_clocks(); s3c2410_baseclk_add(); s3c24xx_register_clock(&s3c2410_armclk); + clkdev_add_table(s3c2410_clk_lookup, ARRAY_SIZE(s3c2410_clk_lookup)); } struct sysdev_class s3c2410_sysclass = { diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c index 140711db6c89..cd50291931f7 100644 --- a/arch/arm/mach-s3c2412/clock.c +++ b/arch/arm/mach-s3c2412/clock.c @@ -659,6 +659,12 @@ static struct clk *clks[] __initdata = { &clk_armclk, }; +static struct clk_lookup s3c2412_clk_lookup[] = { + CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), + CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), + CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_usysclk), +}; + int __init s3c2412_baseclk_add(void) { unsigned long clkcon = __raw_readl(S3C2410_CLKCON); @@ -751,6 +757,7 @@ int __init s3c2412_baseclk_add(void) s3c2412_clkcon_enable(clkp, 0); } + clkdev_add_table(s3c2412_clk_lookup, ARRAY_SIZE(s3c2412_clk_lookup)); s3c_pwmclk_init(); return 0; } diff --git a/arch/arm/mach-s3c2416/Makefile b/arch/arm/mach-s3c2416/Makefile index 7b805b279caf..ca0cd227f873 100644 --- a/arch/arm/mach-s3c2416/Makefile +++ b/arch/arm/mach-s3c2416/Makefile @@ -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 diff --git a/arch/arm/mach-s3c2416/clock.c b/arch/arm/mach-s3c2416/clock.c index afbbe8bc21d1..59f54d1d7f8b 100644 --- a/arch/arm/mach-s3c2416/clock.c +++ b/arch/arm/mach-s3c2416/clock.c @@ -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(); diff --git a/arch/arm/mach-s3c2416/setup-sdhci.c b/arch/arm/mach-s3c2416/setup-sdhci.c deleted file mode 100644 index cee53955eb02..000000000000 --- a/arch/arm/mach-s3c2416/setup-sdhci.c +++ /dev/null @@ -1,24 +0,0 @@ -/* 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 */ -}; diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c index f9e6bdaf41d2..c9879af42b08 100644 --- a/arch/arm/mach-s3c2440/clock.c +++ b/arch/arm/mach-s3c2440/clock.c @@ -34,6 +34,7 @@ #include <linux/mutex.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/serial_core.h> #include <mach/hardware.h> #include <linux/atomic.h> @@ -43,6 +44,7 @@ #include <plat/clock.h> #include <plat/cpu.h> +#include <plat/regs-serial.h> /* S3C2440 extended clock support */ @@ -108,6 +110,46 @@ static struct clk s3c2440_clk_ac97 = { .ctrlbit = S3C2440_CLKCON_CAMERA, }; +static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) +{ + unsigned long ucon0, ucon1, ucon2, divisor; + + /* the fun of calculating the uart divisors on the s3c2440 */ + ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); + ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); + ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); + + ucon0 &= S3C2440_UCON0_DIVMASK; + ucon1 &= S3C2440_UCON1_DIVMASK; + ucon2 &= S3C2440_UCON2_DIVMASK; + + if (ucon0 != 0) + divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6; + else if (ucon1 != 0) + divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21; + else if (ucon2 != 0) + divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36; + else + /* manual calims 44, seems to be 9 */ + divisor = 9; + + return clk_get_rate(clk->parent) / divisor; +} + +static struct clk s3c2440_clk_fclk_n = { + .name = "fclk_n", + .parent = &clk_f, + .ops = &(struct clk_ops) { + .get_rate = s3c2440_fclk_n_getrate, + }, +}; + +static struct clk_lookup s3c2440_clk_lookup[] = { + CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk), + CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p), + CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n), +}; + static int s3c2440_clk_add(struct sys_device *sysdev) { struct clk *clock_upll; @@ -126,10 +168,12 @@ static int s3c2440_clk_add(struct sys_device *sysdev) s3c2440_clk_cam.parent = clock_h; s3c2440_clk_ac97.parent = clock_p; s3c2440_clk_cam_upll.parent = clock_upll; + s3c24xx_register_clock(&s3c2440_clk_fclk_n); s3c24xx_register_clock(&s3c2440_clk_ac97); s3c24xx_register_clock(&s3c2440_clk_cam); s3c24xx_register_clock(&s3c2440_clk_cam_upll); + clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup)); clk_disable(&s3c2440_clk_ac97); clk_disable(&s3c2440_clk_cam); diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index 74f92fc3fd04..d8f36c0a16ad 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c @@ -96,22 +96,6 @@ static struct map_desc anubis_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c24xx_uart_clksrc anubis_serial_clocks[] = { - [0] = { - .name = "uclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "pclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - } -}; - - static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = { [0] = { .hwport = 0, @@ -119,8 +103,7 @@ static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = anubis_serial_clocks, - .clocks_size = ARRAY_SIZE(anubis_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, }, [1] = { .hwport = 2, @@ -128,8 +111,7 @@ static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = anubis_serial_clocks, - .clocks_size = ARRAY_SIZE(anubis_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, }, }; diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c index 38887ee0c784..aa86ca8fa1e9 100644 --- a/arch/arm/mach-s3c2440/mach-at2440evb.c +++ b/arch/arm/mach-s3c2440/mach-at2440evb.c @@ -57,22 +57,6 @@ static struct map_desc at2440evb_iodesc[] __initdata = { #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE) #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) -static struct s3c24xx_uart_clksrc at2440evb_serial_clocks[] = { - [0] = { - .name = "uclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "pclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - } -}; - - static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = { [0] = { .hwport = 0, @@ -80,8 +64,7 @@ static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = at2440evb_serial_clocks, - .clocks_size = ARRAY_SIZE(at2440evb_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, }, [1] = { .hwport = 1, @@ -89,8 +72,7 @@ static struct s3c2410_uartcfg at2440evb_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = at2440evb_serial_clocks, - .clocks_size = ARRAY_SIZE(at2440evb_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, }, }; diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index dc142ebf8cba..d7e47b2b6ec9 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -100,21 +100,6 @@ static struct map_desc osiris_iodesc[] __initdata = { #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE -static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = { - [0] = { - .name = "uclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "pclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - } -}; - static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = { [0] = { .hwport = 0, @@ -122,8 +107,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = osiris_serial_clocks, - .clocks_size = ARRAY_SIZE(osiris_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, }, [1] = { .hwport = 1, @@ -131,8 +115,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = osiris_serial_clocks, - .clocks_size = ARRAY_SIZE(osiris_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, }, [2] = { .hwport = 2, @@ -140,8 +123,7 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = { .ucon = UCON, .ulcon = ULCON, .ufcon = UFCON, - .clocks = osiris_serial_clocks, - .clocks_size = ARRAY_SIZE(osiris_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL1 | S3C2410_UCON_CLKSEL2, } }; diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c index 0d3453bf567c..4267cd56bfe7 100644 --- a/arch/arm/mach-s3c2440/mach-rx1950.c +++ b/arch/arm/mach-s3c2440/mach-rx1950.c @@ -68,15 +68,6 @@ static struct map_desc rx1950_iodesc[] __initdata = { }; -static struct s3c24xx_uart_clksrc rx1950_serial_clocks[] = { - [0] = { - .name = "fclk", - .divisor = 0x0a, - .min_baud = 0, - .max_baud = 0, - }, -}; - static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = { [0] = { .hwport = 0, @@ -84,8 +75,7 @@ static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = { .ucon = 0x3c5, .ulcon = 0x03, .ufcon = 0x51, - .clocks = rx1950_serial_clocks, - .clocks_size = ARRAY_SIZE(rx1950_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL3, }, [1] = { .hwport = 1, @@ -93,8 +83,7 @@ static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = { .ucon = 0x3c5, .ulcon = 0x03, .ufcon = 0x51, - .clocks = rx1950_serial_clocks, - .clocks_size = ARRAY_SIZE(rx1950_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL3, }, /* IR port */ [2] = { @@ -103,8 +92,7 @@ static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = { .ucon = 0x3c5, .ulcon = 0x43, .ufcon = 0xf1, - .clocks = rx1950_serial_clocks, - .clocks_size = ARRAY_SIZE(rx1950_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL3, }, }; diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index e19499c2f909..3d5e2e67971e 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -67,16 +67,6 @@ static struct map_desc rx3715_iodesc[] __initdata = { }, }; - -static struct s3c24xx_uart_clksrc rx3715_serial_clocks[] = { - [0] = { - .name = "fclk", - .divisor = 0, - .min_baud = 0, - .max_baud = 0, - } -}; - static struct s3c2410_uartcfg rx3715_uartcfgs[] = { [0] = { .hwport = 0, @@ -84,8 +74,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = { .ucon = 0x3c5, .ulcon = 0x03, .ufcon = 0x51, - .clocks = rx3715_serial_clocks, - .clocks_size = ARRAY_SIZE(rx3715_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL3, }, [1] = { .hwport = 1, @@ -93,8 +82,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = { .ucon = 0x3c5, .ulcon = 0x03, .ufcon = 0x00, - .clocks = rx3715_serial_clocks, - .clocks_size = ARRAY_SIZE(rx3715_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL3, }, /* IR port */ [2] = { @@ -103,8 +91,7 @@ static struct s3c2410_uartcfg rx3715_uartcfgs[] = { .ucon = 0x3c5, .ulcon = 0x43, .ufcon = 0x51, - .clocks = rx3715_serial_clocks, - .clocks_size = ARRAY_SIZE(rx3715_serial_clocks), + .clk_sel = S3C2410_UCON_CLKSEL3, } }; diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index 5552e048c2be..90b34ab75b53 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -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 diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index cfc0b9941808..d7d9bb5dfb72 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -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 diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index 39c238d7a3dc..0187cde3a5dc 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -184,18 +184,6 @@ static struct clk init_clocks_off[] = { .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", .parent = &clk_48m, @@ -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", @@ -243,24 +247,6 @@ static struct clk init_clocks[] = { .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, .enable = s3c64xx_hclk_ctrl, @@ -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", @@ -578,36 +587,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, .enable = s3c64xx_sclk_ctrl, @@ -617,35 +596,6 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_uhost, }, { .clk = { - .name = "uclk1", - .ctrlbit = S3C_CLKCON_SCLK_UART, - .enable = s3c64xx_sclk_ctrl, - }, - .reg_src = { .reg = S3C_CLK_SRC, .shift = 13, .size = 1 }, - .reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 }, - .sources = &clkset_uart, - }, { -/* Where does UCLK0 come from? */ - .clk = { - .name = "spi-bus", - .devname = "s3c64xx-spi.0", - .ctrlbit = S3C_CLKCON_SCLK_SPI0, - .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", .devname = "samsung-i2s.0", .ctrlbit = S3C_CLKCON_SCLK_AUDIO0, @@ -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(); } diff --git a/arch/arm/mach-s3c64xx/dev-spi.c b/arch/arm/mach-s3c64xx/dev-spi.c deleted file mode 100644 index 3341fd118723..000000000000 --- a/arch/arm/mach-s3c64xx/dev-spi.c +++ /dev/null @@ -1,180 +0,0 @@ -/* 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]; -} diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h index 23a1d71e4d53..8e2097bb208a 100644 --- a/arch/arm/mach-s3c64xx/include/mach/map.h +++ b/arch/arm/mach-s3c64xx/include/mach/map.h @@ -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 diff --git a/arch/arm/mach-s3c64xx/setup-sdhci.c b/arch/arm/mach-s3c64xx/setup-sdhci.c deleted file mode 100644 index c75a71b21165..000000000000 --- a/arch/arm/mach-s3c64xx/setup-sdhci.c +++ /dev/null @@ -1,24 +0,0 @@ -/* 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 */ -}; diff --git a/arch/arm/mach-s3c64xx/setup-spi.c b/arch/arm/mach-s3c64xx/setup-spi.c new file mode 100644 index 000000000000..d9592ad7a825 --- /dev/null +++ b/arch/arm/mach-s3c64xx/setup-spi.c @@ -0,0 +1,45 @@ +/* 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 diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig index 18690c5f99e6..c87f6108eeb1 100644 --- a/arch/arm/mach-s5p64x0/Kconfig +++ b/arch/arm/mach-s5p64x0/Kconfig @@ -36,6 +36,16 @@ 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 + +config S5P64X0_SETUP_SDHCI_GPIO + bool + help + Common setup code for SDHCI gpio. + # machine support config MACH_SMDK6440 @@ -45,13 +55,16 @@ config MACH_SMDK6440 select S3C_DEV_I2C1 select S3C_DEV_RTC select S3C_DEV_WDT - select S3C64XX_DEV_SPI + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 select SAMSUNG_DEV_ADC select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_PWM select SAMSUNG_DEV_TS select S5P64X0_SETUP_FB_24BPP select S5P64X0_SETUP_I2C1 + select S5P64X0_SETUP_SDHCI_GPIO help Machine support for the Samsung SMDK6440 @@ -62,14 +75,28 @@ config MACH_SMDK6450 select S3C_DEV_I2C1 select S3C_DEV_RTC select S3C_DEV_WDT - select S3C64XX_DEV_SPI + select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 + select S3C_DEV_HSMMC2 select SAMSUNG_DEV_ADC select SAMSUNG_DEV_BACKLIGHT select SAMSUNG_DEV_PWM select SAMSUNG_DEV_TS select S5P64X0_SETUP_FB_24BPP select S5P64X0_SETUP_I2C1 + select S5P64X0_SETUP_SDHCI_GPIO help Machine support for the Samsung SMDK6450 +menu "Use 8-bit SDHCI bus width" + +config S5P64X0_SD_CH1_8BIT + bool "SDHCI Channel 1 (Slot 1)" + depends on MACH_SMDK6450 || MACH_SMDK6440 + help + Support SDHCI Channel 1 8-bit bus. + If selected, Channel 2 is disabled. + +endmenu + endif diff --git a/arch/arm/mach-s5p64x0/Makefile b/arch/arm/mach-s5p64x0/Makefile index a1324d8dc4e0..b44cc044b3c3 100644 --- a/arch/arm/mach-s5p64x0/Makefile +++ b/arch/arm/mach-s5p64x0/Makefile @@ -26,7 +26,8 @@ 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 +obj-$(CONFIG_S5P64X0_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c index c54c65d511f0..c041ad7fbd60 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6440.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c @@ -268,18 +268,6 @@ static struct clk init_clocks_off[] = { .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", .parent = &clk_48m, @@ -391,65 +379,6 @@ static struct clksrc_sources clkset_audio = { static struct clksrc_clk clksrcs[] = { { .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.0", - .ctrlbit = (1 << 24), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.1", - .ctrlbit = (1 << 25), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group1, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.2", - .ctrlbit = (1 << 26), - .enable = s5p64x0_sclk_ctrl, - }, - .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", .ctrlbit = (1 << 10), .enable = s5p64x0_sclk_ctrl, @@ -487,6 +416,77 @@ static struct clksrc_clk clksrcs[] = { }, }; +static struct clksrc_clk clk_sclk_mmc0 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.0", + .ctrlbit = (1 << 24), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc1 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.1", + .ctrlbit = (1 << 25), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc2 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.2", + .ctrlbit = (1 << 26), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, +}; + +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 +505,26 @@ static struct clk dummy_apb_pclk = { .id = -1, }; +static struct clksrc_clk *clksrc_cdev[] = { + &clk_sclk_uclk, + &clk_sclk_spi0, + &clk_sclk_spi1, + &clk_sclk_mmc0, + &clk_sclk_mmc1, + &clk_sclk_mmc2 +}; + +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), + 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), +}; + void __init_or_cpufreq s5p6440_setup_clocks(void) { struct clk *xtal_clk; @@ -583,9 +603,12 @@ void __init s5p6440_register_clocks(void) s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++) + s3c_register_clksrc(clksrc_cdev[ptr], 1); s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + clkdev_add_table(s5p6440_clk_lookup, ARRAY_SIZE(s5p6440_clk_lookup)); s3c24xx_register_clock(&dummy_apb_pclk); diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c index 2d04abfba12e..b5087cb6e818 100644 --- a/arch/arm/mach-s5p64x0/clock-s5p6450.c +++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c @@ -413,65 +413,6 @@ static struct clksrc_clk clk_sclk_audio0 = { static struct clksrc_clk clksrcs[] = { { .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.0", - .ctrlbit = (1 << 24), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.1", - .ctrlbit = (1 << 25), - .enable = s5p64x0_sclk_ctrl, - }, - .sources = &clkset_group2, - .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, - .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, - }, { - .clk = { - .name = "sclk_mmc", - .devname = "s3c-sdhci.2", - .ctrlbit = (1 << 26), - .enable = s5p64x0_sclk_ctrl, - }, - .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", .ctrlbit = (1 << 10), .enable = s5p64x0_sclk_ctrl, @@ -536,6 +477,97 @@ static struct clksrc_clk clksrcs[] = { }, }; +static struct clksrc_clk clk_sclk_mmc0 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.0", + .ctrlbit = (1 << 24), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 18, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 0, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc1 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.1", + .ctrlbit = (1 << 25), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 4, .size = 4 }, +}; + +static struct clksrc_clk clk_sclk_mmc2 = { + .clk = { + .name = "sclk_mmc", + .devname = "s3c-sdhci.2", + .ctrlbit = (1 << 26), + .enable = s5p64x0_sclk_ctrl, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 22, .size = 2 }, + .reg_div = { .reg = S5P64X0_CLK_DIV1, .shift = 8, .size = 4 }, +}; + +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, + &clk_sclk_mmc0, + &clk_sclk_mmc1, + &clk_sclk_mmc2, +}; + +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), + 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), +}; + /* Clock initialization code */ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, @@ -634,9 +666,12 @@ void __init s5p6450_register_clocks(void) s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++) + s3c_register_clksrc(clksrc_cdev[ptr], 1); s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + clkdev_add_table(s5p6450_clk_lookup, ARRAY_SIZE(s5p6450_clk_lookup)); s3c24xx_register_clock(&dummy_apb_pclk); diff --git a/arch/arm/mach-s5p64x0/cpu.c b/arch/arm/mach-s5p64x0/cpu.c index ecab40cf19ab..f6e24f3ef760 100644 --- a/arch/arm/mach-s5p64x0/cpu.c +++ b/arch/arm/mach-s5p64x0/cpu.c @@ -40,6 +40,7 @@ #include <plat/s5p6450.h> #include <plat/adc-core.h> #include <plat/fb-core.h> +#include <plat/sdhci.h> /* Initial IO mappings */ @@ -112,6 +113,10 @@ void __init s5p6440_map_io(void) s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s5p64x0_default_sdhci0(); + s5p64x0_default_sdhci1(); + s5p6440_default_sdhci2(); + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); iotable_init(s5p6440_iodesc, ARRAY_SIZE(s5p6440_iodesc)); init_consistent_dma_size(SZ_8M); @@ -123,6 +128,10 @@ void __init s5p6450_map_io(void) s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s5p64x0_default_sdhci0(); + s5p64x0_default_sdhci1(); + s5p6450_default_sdhci2(); + iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc)); iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc)); init_consistent_dma_size(SZ_8M); diff --git a/arch/arm/mach-s5p64x0/dev-spi.c b/arch/arm/mach-s5p64x0/dev-spi.c deleted file mode 100644 index 1fd9c79c7dbc..000000000000 --- a/arch/arm/mach-s5p64x0/dev-spi.c +++ /dev/null @@ -1,224 +0,0 @@ -/* 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]; -} diff --git a/arch/arm/mach-s5p64x0/dma.c b/arch/arm/mach-s5p64x0/dma.c index 442dd4ad12da..f820c0744405 100644 --- a/arch/arm/mach-s5p64x0/dma.c +++ b/arch/arm/mach-s5p64x0/dma.c @@ -38,176 +38,74 @@ static u64 dma_dmamask = DMA_BIT_MASK(32); -struct dma_pl330_peri s5p6440_pdma_peri[22] = { - { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = DMACH_MAX, - }, { - .peri_id = DMACH_MAX, - }, { - .peri_id = (u8)DMACH_PCM0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, +u8 s5p6440_pdma_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_MAX, + DMACH_MAX, + DMACH_PCM0_TX, + DMACH_PCM0_RX, + DMACH_I2S0_TX, + DMACH_I2S0_RX, + DMACH_SPI0_TX, + DMACH_SPI0_RX, + DMACH_MAX, + DMACH_MAX, + DMACH_MAX, + DMACH_MAX, + DMACH_SPI1_TX, + DMACH_SPI1_RX, }; struct dma_pl330_platdata s5p6440_pdma_pdata = { .nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri), - .peri = s5p6440_pdma_peri, + .peri_id = s5p6440_pdma_peri, }; -struct dma_pl330_peri s5p6450_pdma_peri[32] = { - { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART4_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART4_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_USI_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_USI_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_I2S1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PWM, - }, { - .peri_id = (u8)DMACH_UART5_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART5_TX, - .rqtype = MEMTODEV, - }, +u8 s5p6450_pdma_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_UART4_RX, + DMACH_UART4_TX, + DMACH_PCM0_TX, + DMACH_PCM0_RX, + DMACH_I2S0_TX, + DMACH_I2S0_RX, + DMACH_SPI0_TX, + DMACH_SPI0_RX, + DMACH_PCM1_TX, + DMACH_PCM1_RX, + DMACH_PCM2_TX, + DMACH_PCM2_RX, + DMACH_SPI1_TX, + DMACH_SPI1_RX, + DMACH_USI_TX, + DMACH_USI_RX, + DMACH_MAX, + DMACH_I2S1_TX, + DMACH_I2S1_RX, + DMACH_I2S2_TX, + DMACH_I2S2_RX, + DMACH_PWM, + DMACH_UART5_RX, + DMACH_UART5_TX, }; struct dma_pl330_platdata s5p6450_pdma_pdata = { .nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri), - .peri = s5p6450_pdma_peri, + .peri_id = s5p6450_pdma_peri, }; struct amba_device s5p64x0_device_pdma = { @@ -227,10 +125,15 @@ struct amba_device s5p64x0_device_pdma = { static int __init s5p64x0_dma_init(void) { - if (soc_is_s5p6450()) + if (soc_is_s5p6450()) { + dma_cap_set(DMA_SLAVE, s5p6450_pdma_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5p6450_pdma_pdata.cap_mask); s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata; - else + } else { + dma_cap_set(DMA_SLAVE, s5p6440_pdma_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5p6440_pdma_pdata.cap_mask); s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata; + } amba_device_register(&s5p64x0_device_pdma, &iomem_resource); diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h index 53982db9d259..5b845e849b30 100644 --- a/arch/arm/mach-s5p64x0/include/mach/irqs.h +++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h @@ -141,6 +141,8 @@ #define IRQ_EINT_GROUP(grp, x) (IRQ_EINT_GROUP##grp##_BASE + (x)) +#define IRQ_TIMER_BASE (11) + /* Set the default NR_IRQS */ #define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1) diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h index 4d3ac8a3709d..0c0175dbfa34 100644 --- a/arch/arm/mach-s5p64x0/include/mach/map.h +++ b/arch/arm/mach-s5p64x0/include/mach/map.h @@ -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 diff --git a/arch/arm/mach-s5p64x0/init.c b/arch/arm/mach-s5p64x0/init.c index 79833caf8165..659a66c131a1 100644 --- a/arch/arm/mach-s5p64x0/init.c +++ b/arch/arm/mach-s5p64x0/init.c @@ -23,36 +23,7 @@ #include <plat/s5p6450.h> #include <plat/regs-serial.h> -static struct s3c24xx_uart_clksrc s5p64x0_serial_clocks[] = { - [0] = { - .name = "pclk_low", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, - [1] = { - .name = "uclk1", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, -}; - /* uart registration process */ - -void __init s5p64x0_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) -{ - struct s3c2410_uartcfg *tcfg = cfg; - u32 ucnt; - - for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { - if (!tcfg->clocks) { - tcfg->clocks = s5p64x0_serial_clocks; - tcfg->clocks_size = ARRAY_SIZE(s5p64x0_serial_clocks); - } - } -} - void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no) { int uart; @@ -62,12 +33,10 @@ void __init s5p6440_init_uarts(struct s3c2410_uartcfg *cfg, int no) s5p_uart_resources[uart].resources->end = S5P6440_PA_UART(uart) + S5P_SZ_UART; } - s5p64x0_common_init_uarts(cfg, no); s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); } void __init s5p6450_init_uarts(struct s3c2410_uartcfg *cfg, int no) { - s5p64x0_common_init_uarts(cfg, no); s3c24xx_init_uartdevs("s3c6400-uart", s5p_uart_resources, cfg, no); } diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c index 4a1250cd1356..fe168a087531 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6440.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c @@ -24,6 +24,7 @@ #include <linux/gpio.h> #include <linux/pwm_backlight.h> #include <linux/fb.h> +#include <linux/mmc/host.h> #include <video/platform_lcd.h> @@ -52,6 +53,7 @@ #include <plat/backlight.h> #include <plat/fb.h> #include <plat/regs-fb.h> +#include <plat/sdhci.h> #define SMDK6440_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -161,6 +163,25 @@ static struct platform_device *smdk6440_devices[] __initdata = { &s5p6440_device_iis, &s3c_device_fb, &smdk6440_lcd_lte480wv, + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, +}; + +static struct s3c_sdhci_platdata smdk6440_hsmmc0_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +}; + +static struct s3c_sdhci_platdata smdk6440_hsmmc1_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_INTERNAL, +#if defined(CONFIG_S5P64X0_SD_CH1_8BIT) + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdk6440_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, }; static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = { @@ -234,6 +255,10 @@ static void __init smdk6440_machine_init(void) s5p6440_set_lcd_interface(); s3c_fb_set_platdata(&smdk6440_lcd_pdata); + s3c_sdhci0_set_platdata(&smdk6440_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdk6440_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdk6440_hsmmc2_pdata); + platform_add_devices(smdk6440_devices, ARRAY_SIZE(smdk6440_devices)); } diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c index 0ab129ecf009..242a415dcf6b 100644 --- a/arch/arm/mach-s5p64x0/mach-smdk6450.c +++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c @@ -24,6 +24,7 @@ #include <linux/gpio.h> #include <linux/pwm_backlight.h> #include <linux/fb.h> +#include <linux/mmc/host.h> #include <video/platform_lcd.h> @@ -52,6 +53,7 @@ #include <plat/backlight.h> #include <plat/fb.h> #include <plat/regs-fb.h> +#include <plat/sdhci.h> #define SMDK6450_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ S3C2410_UCON_RXILEVEL | \ @@ -179,10 +181,28 @@ static struct platform_device *smdk6450_devices[] __initdata = { &s5p6450_device_iis0, &s3c_device_fb, &smdk6450_lcd_lte480wv, - + &s3c_device_hsmmc0, + &s3c_device_hsmmc1, + &s3c_device_hsmmc2, /* s5p6450_device_spi0 will be added */ }; +static struct s3c_sdhci_platdata smdk6450_hsmmc0_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +}; + +static struct s3c_sdhci_platdata smdk6450_hsmmc1_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +#if defined(CONFIG_S5P64X0_SD_CH1_8BIT) + .max_width = 8, + .host_caps = MMC_CAP_8_BIT_DATA, +#endif +}; + +static struct s3c_sdhci_platdata smdk6450_hsmmc2_pdata __initdata = { + .cd_type = S3C_SDHCI_CD_NONE, +}; + static struct s3c2410_platform_i2c s5p6450_i2c0_data __initdata = { .flags = 0, .slave_addr = 0x10, @@ -254,6 +274,10 @@ static void __init smdk6450_machine_init(void) s5p6450_set_lcd_interface(); s3c_fb_set_platdata(&smdk6450_lcd_pdata); + s3c_sdhci0_set_platdata(&smdk6450_hsmmc0_pdata); + s3c_sdhci1_set_platdata(&smdk6450_hsmmc1_pdata); + s3c_sdhci2_set_platdata(&smdk6450_hsmmc2_pdata); + platform_add_devices(smdk6450_devices, ARRAY_SIZE(smdk6450_devices)); } diff --git a/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c b/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c new file mode 100644 index 000000000000..8410af0d12bf --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c @@ -0,0 +1,104 @@ +/* linux/arch/arm/mach-s5p64x0/setup-sdhci-gpio.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5P64X0 - Helper functions for setting up SDHCI device(s) GPIO (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/platform_device.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <mach/regs-gpio.h> +#include <mach/regs-clock.h> + +#include <plat/gpio-cfg.h> +#include <plat/sdhci.h> +#include <plat/cpu.h> + +void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + + /* Set all the necessary GPG pins to special-function 2 */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPG(0), 2 + width, + S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPG(0), 2 + width, + S3C_GPIO_SFN(2)); + + /* Set GPG[6] pin to special-function 2 - MMC0 CDn */ + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + if (soc_is_s5p6450()) { + s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(2)); + } else { + s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(2)); + } + } +} + +void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width) +{ + struct s3c_sdhci_platdata *pdata = dev->dev.platform_data; + + /* Set GPH[0:1] pins to special-function 2 - CLK and CMD */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPH(0), 2, S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPH(0), 2 , S3C_GPIO_SFN(2)); + + switch (width) { + case 8: + /* Set data pins GPH[6:9] special-function 2 */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPH(6), 4, + S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4, + S3C_GPIO_SFN(2)); + case 4: + /* set data pins GPH[2:5] special-function 2 */ + if (soc_is_s5p6450()) + s3c_gpio_cfgrange_nopull(S5P6450_GPH(2), 4, + S3C_GPIO_SFN(2)); + else + s3c_gpio_cfgrange_nopull(S5P6440_GPH(2), 4, + S3C_GPIO_SFN(2)); + default: + break; + } + + /* Set GPG[6] pin to special-funtion 3 : MMC1 CDn */ + if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { + if (soc_is_s5p6450()) { + s3c_gpio_setpull(S5P6450_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6450_GPG(6), S3C_GPIO_SFN(3)); + } else { + s3c_gpio_setpull(S5P6440_GPG(6), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5P6440_GPG(6), S3C_GPIO_SFN(3)); + } + } +} + +void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) +{ + /* Set GPC[4:5] pins to special-function 3 - CLK and CMD */ + s3c_gpio_cfgrange_nopull(S5P6440_GPC(4), 2, S3C_GPIO_SFN(3)); + + /* Set data pins GPH[6:9] pins to special-function 3 */ + s3c_gpio_cfgrange_nopull(S5P6440_GPH(6), 4, S3C_GPIO_SFN(3)); +} + +void s5p6450_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width) +{ + /* Set all the necessary GPG pins to special-function 3 */ + s3c_gpio_cfgrange_nopull(S5P6450_GPG(7), 2 + width, S3C_GPIO_SFN(3)); +} diff --git a/arch/arm/mach-s5p64x0/setup-spi.c b/arch/arm/mach-s5p64x0/setup-spi.c new file mode 100644 index 000000000000..e9b841240352 --- /dev/null +++ b/arch/arm/mach-s5p64x0/setup-spi.c @@ -0,0 +1,55 @@ +/* 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 diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig index e538a4c67e9c..75a26eaf2633 100644 --- a/arch/arm/mach-s5pc100/Kconfig +++ b/arch/arm/mach-s5pc100/Kconfig @@ -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 diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index a5e6e608b498..291e246c0ec0 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile @@ -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 diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c index 8d47709da713..eba721b551fc 100644 --- a/arch/arm/mach-s5pc100/clock.c +++ b/arch/arm/mach-s5pc100/clock.c @@ -426,24 +426,6 @@ static struct clk init_clocks_off[] = { .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, .enable = s5pc100_d1_0_ctrl, @@ -673,24 +655,6 @@ static struct clk init_clocks_off[] = { .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", .parent = &clk_mout_48m.clk, @@ -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, @@ -929,49 +941,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), .enable = s5pc100_sclk0_ctrl, @@ -1024,39 +993,6 @@ static struct clksrc_clk clksrcs[] = { .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", .ctrlbit = (1 << 10), .enable = s5pc100_sclk0_ctrl, @@ -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); diff --git a/arch/arm/mach-s5pc100/dev-spi.c b/arch/arm/mach-s5pc100/dev-spi.c deleted file mode 100644 index e5d6c4dceb56..000000000000 --- a/arch/arm/mach-s5pc100/dev-spi.c +++ /dev/null @@ -1,227 +0,0 @@ -/* 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]; -} diff --git a/arch/arm/mach-s5pc100/dma.c b/arch/arm/mach-s5pc100/dma.c index 065a087f5a8b..c841f4d313f2 100644 --- a/arch/arm/mach-s5pc100/dma.c +++ b/arch/arm/mach-s5pc100/dma.c @@ -35,100 +35,42 @@ static u64 dma_dmamask = DMA_BIT_MASK(32); -struct dma_pl330_peri pdma0_peri[30] = { - { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = DMACH_IRDA, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0S_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_AC97_MICIN, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_AC97_PCMIN, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_AC97_PCMOUT, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_EXTERNAL, - }, { - .peri_id = (u8)DMACH_PWM, - }, { - .peri_id = (u8)DMACH_SPDIF, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_HSI_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_HSI_TX, - .rqtype = MEMTODEV, - }, +u8 pdma0_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_IRDA, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S0S_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_I2S2_RX, + DMACH_I2S2_TX, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_SPI2_RX, + DMACH_SPI2_TX, + DMACH_AC97_MICIN, + DMACH_AC97_PCMIN, + DMACH_AC97_PCMOUT, + DMACH_EXTERNAL, + DMACH_PWM, + DMACH_SPDIF, + DMACH_HSI_RX, + DMACH_HSI_TX, }; struct dma_pl330_platdata s5pc100_pdma0_pdata = { .nr_valid_peri = ARRAY_SIZE(pdma0_peri), - .peri = pdma0_peri, + .peri_id = pdma0_peri, }; struct amba_device s5pc100_device_pdma0 = { @@ -147,98 +89,42 @@ struct amba_device s5pc100_device_pdma0 = { .periphid = 0x00041330, }; -struct dma_pl330_peri pdma1_peri[30] = { - { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = DMACH_IRDA, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0S_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MSM_REQ0, - }, { - .peri_id = (u8)DMACH_MSM_REQ1, - }, { - .peri_id = (u8)DMACH_MSM_REQ2, - }, { - .peri_id = (u8)DMACH_MSM_REQ3, - }, +u8 pdma1_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_IRDA, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S0S_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_I2S2_RX, + DMACH_I2S2_TX, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_SPI2_RX, + DMACH_SPI2_TX, + DMACH_PCM0_RX, + DMACH_PCM0_TX, + DMACH_PCM1_RX, + DMACH_PCM1_TX, + DMACH_MSM_REQ0, + DMACH_MSM_REQ1, + DMACH_MSM_REQ2, + DMACH_MSM_REQ3, }; struct dma_pl330_platdata s5pc100_pdma1_pdata = { .nr_valid_peri = ARRAY_SIZE(pdma1_peri), - .peri = pdma1_peri, + .peri_id = pdma1_peri, }; struct amba_device s5pc100_device_pdma1 = { @@ -259,7 +145,12 @@ struct amba_device s5pc100_device_pdma1 = { static int __init s5pc100_dma_init(void) { + dma_cap_set(DMA_SLAVE, s5pc100_pdma0_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5pc100_pdma0_pdata.cap_mask); amba_device_register(&s5pc100_device_pdma0, &iomem_resource); + + dma_cap_set(DMA_SLAVE, s5pc100_pdma1_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5pc100_pdma1_pdata.cap_mask); amba_device_register(&s5pc100_device_pdma1, &iomem_resource); return 0; diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h index d2eb4757381f..2870f12c7926 100644 --- a/arch/arm/mach-s5pc100/include/mach/irqs.h +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h @@ -97,6 +97,8 @@ #define IRQ_SDMFIQ S5P_IRQ_VIC2(31) #define IRQ_VIC_END S5P_IRQ_VIC2(31) +#define IRQ_TIMER_BASE (11) + #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index ccbe6b767f7d..54bc4f82e17a 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -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 diff --git a/arch/arm/mach-s5pc100/setup-sdhci.c b/arch/arm/mach-s5pc100/setup-sdhci.c deleted file mode 100644 index 6418c6e8a7b7..000000000000 --- a/arch/arm/mach-s5pc100/setup-sdhci.c +++ /dev/null @@ -1,23 +0,0 @@ -/* 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 */ -}; diff --git a/arch/arm/mach-s5pc100/setup-spi.c b/arch/arm/mach-s5pc100/setup-spi.c new file mode 100644 index 000000000000..431a6f747caa --- /dev/null +++ b/arch/arm/mach-s5pc100/setup-spi.c @@ -0,0 +1,65 @@ +/* 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 diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index 646057ab2e4c..2cdc42e838b8 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig @@ -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 diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 009fbe53df96..471df5d2d25c 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -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 diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 4c5ac7a69e9e..cead51321b29 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -399,30 +399,6 @@ static struct clk init_clocks_off[] = { .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, .enable = s5pv210_clk_ip3_ctrl, @@ -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, @@ -809,46 +817,6 @@ static struct clksrc_clk clksrcs[] = { .reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 }, }, { .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.0", - .enable = s5pv210_clk_mask0_ctrl, - .ctrlbit = (1 << 12), - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.1", - .enable = s5pv210_clk_mask0_ctrl, - .ctrlbit = (1 << 13), - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.2", - .enable = s5pv210_clk_mask0_ctrl, - .ctrlbit = (1 << 14), - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 }, - }, { - .clk = { - .name = "uclk1", - .devname = "s5pv210-uart.3", - .enable = s5pv210_clk_mask0_ctrl, - .ctrlbit = (1 << 15), - }, - .sources = &clkset_uart, - .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 }, - .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 }, - }, { - .clk = { .name = "sclk_fimc", .devname = "s5pv210-fimc.0", .enable = s5pv210_clk_mask1_ctrl, @@ -906,46 +874,6 @@ static struct clksrc_clk clksrcs[] = { .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", .devname = "s5p-mfc", .enable = s5pv210_clk_ip0_ctrl, @@ -983,26 +911,6 @@ static struct clksrc_clk clksrcs[] = { .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", .enable = s5pv210_clk_mask0_ctrl, .ctrlbit = (1 << 29), @@ -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(); diff --git a/arch/arm/mach-s5pv210/dev-spi.c b/arch/arm/mach-s5pv210/dev-spi.c deleted file mode 100644 index eaf9a7bff7a0..000000000000 --- a/arch/arm/mach-s5pv210/dev-spi.c +++ /dev/null @@ -1,175 +0,0 @@ -/* 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]; -} diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c index 86b749c18b77..a6113e0267f2 100644 --- a/arch/arm/mach-s5pv210/dma.c +++ b/arch/arm/mach-s5pv210/dma.c @@ -35,90 +35,40 @@ static u64 dma_dmamask = DMA_BIT_MASK(32); -struct dma_pl330_peri pdma0_peri[28] = { - { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = DMACH_MAX, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0S_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_AC97_MICIN, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_AC97_PCMIN, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_AC97_PCMOUT, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_PWM, - }, { - .peri_id = (u8)DMACH_SPDIF, - .rqtype = MEMTODEV, - }, +u8 pdma0_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_MAX, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S0S_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_MAX, + DMACH_MAX, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_MAX, + DMACH_MAX, + DMACH_AC97_MICIN, + DMACH_AC97_PCMIN, + DMACH_AC97_PCMOUT, + DMACH_MAX, + DMACH_PWM, + DMACH_SPDIF, }; struct dma_pl330_platdata s5pv210_pdma0_pdata = { .nr_valid_peri = ARRAY_SIZE(pdma0_peri), - .peri = pdma0_peri, + .peri_id = pdma0_peri, }; struct amba_device s5pv210_device_pdma0 = { @@ -137,102 +87,44 @@ struct amba_device s5pv210_device_pdma0 = { .periphid = 0x00041330, }; -struct dma_pl330_peri pdma1_peri[32] = { - { - .peri_id = (u8)DMACH_UART0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_UART3_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_UART3_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = DMACH_MAX, - }, { - .peri_id = (u8)DMACH_I2S0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S0S_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_I2S2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_I2S2_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_SPI1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_SPI1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_MAX, - }, { - .peri_id = (u8)DMACH_PCM0_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM0_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_PCM1_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM1_TX, - .rqtype = MEMTODEV, - }, { - .peri_id = (u8)DMACH_MSM_REQ0, - }, { - .peri_id = (u8)DMACH_MSM_REQ1, - }, { - .peri_id = (u8)DMACH_MSM_REQ2, - }, { - .peri_id = (u8)DMACH_MSM_REQ3, - }, { - .peri_id = (u8)DMACH_PCM2_RX, - .rqtype = DEVTOMEM, - }, { - .peri_id = (u8)DMACH_PCM2_TX, - .rqtype = MEMTODEV, - }, +u8 pdma1_peri[] = { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_MAX, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S0S_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_I2S2_RX, + DMACH_I2S2_TX, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_MAX, + DMACH_MAX, + DMACH_PCM0_RX, + DMACH_PCM0_TX, + DMACH_PCM1_RX, + DMACH_PCM1_TX, + DMACH_MSM_REQ0, + DMACH_MSM_REQ1, + DMACH_MSM_REQ2, + DMACH_MSM_REQ3, + DMACH_PCM2_RX, + DMACH_PCM2_TX, }; struct dma_pl330_platdata s5pv210_pdma1_pdata = { .nr_valid_peri = ARRAY_SIZE(pdma1_peri), - .peri = pdma1_peri, + .peri_id = pdma1_peri, }; struct amba_device s5pv210_device_pdma1 = { @@ -253,7 +145,12 @@ struct amba_device s5pv210_device_pdma1 = { static int __init s5pv210_dma_init(void) { + dma_cap_set(DMA_SLAVE, s5pv210_pdma0_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5pv210_pdma0_pdata.cap_mask); amba_device_register(&s5pv210_device_pdma0, &iomem_resource); + + dma_cap_set(DMA_SLAVE, s5pv210_pdma1_pdata.cap_mask); + dma_cap_set(DMA_CYCLIC, s5pv210_pdma1_pdata.cap_mask); amba_device_register(&s5pv210_device_pdma1, &iomem_resource); return 0; diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h index 5e0de3a31f3d..e777e010ed2e 100644 --- a/arch/arm/mach-s5pv210/include/mach/irqs.h +++ b/arch/arm/mach-s5pv210/include/mach/irqs.h @@ -118,6 +118,8 @@ #define IRQ_MDNIE3 S5P_IRQ_VIC3(8) #define IRQ_VIC_END S5P_IRQ_VIC3(31) +#define IRQ_TIMER_BASE (11) + #define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) #define S5P_EINT_BASE2 (IRQ_VIC_END + 1) diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index 7ff609f1568b..89c34b8f73bf 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -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 diff --git a/arch/arm/mach-s5pv210/init.c b/arch/arm/mach-s5pv210/init.c index 4865ae2c475a..468a5f886193 100644 --- a/arch/arm/mach-s5pv210/init.c +++ b/arch/arm/mach-s5pv210/init.c @@ -18,27 +18,8 @@ #include <plat/s5pv210.h> #include <plat/regs-serial.h> -static struct s3c24xx_uart_clksrc s5pv210_serial_clocks[] = { - [0] = { - .name = "pclk", - .divisor = 1, - .min_baud = 0, - .max_baud = 0, - }, -}; - /* uart registration process */ void __init s5pv210_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) { - struct s3c2410_uartcfg *tcfg = cfg; - u32 ucnt; - - for (ucnt = 0; ucnt < no; ucnt++, tcfg++) { - if (!tcfg->clocks) { - tcfg->clocks = s5pv210_serial_clocks; - tcfg->clocks_size = ARRAY_SIZE(s5pv210_serial_clocks); - } - } - s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no); } diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index a9106c392398..8662ef6e5681 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -273,6 +273,7 @@ static struct samsung_bl_gpio_info smdkv210_bl_gpio_info = { static struct platform_pwm_backlight_data smdkv210_bl_data = { .pwm_id = 3, + .pwm_period_ns = 1000, }; static void __init smdkv210_map_io(void) diff --git a/arch/arm/mach-s5pv210/setup-sdhci.c b/arch/arm/mach-s5pv210/setup-sdhci.c deleted file mode 100644 index 6b8ccc4d35fd..000000000000 --- a/arch/arm/mach-s5pv210/setup-sdhci.c +++ /dev/null @@ -1,22 +0,0 @@ -/* 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 */ -}; diff --git a/arch/arm/mach-s5pv210/setup-spi.c b/arch/arm/mach-s5pv210/setup-spi.c new file mode 100644 index 000000000000..f43c5048a37d --- /dev/null +++ b/arch/arm/mach-s5pv210/setup-spi.c @@ -0,0 +1,51 @@ +/* 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 diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c index 74aac96cda20..adbff706ef6f 100644 --- a/arch/arm/plat-mxc/cpufreq.c +++ b/arch/arm/plat-mxc/cpufreq.c @@ -17,6 +17,7 @@ * the CPU clock speed on the fly. */ +#include <linux/module.h> #include <linux/cpufreq.h> #include <linux/clk.h> #include <linux/err.h> diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c index 42d74ea59084..845de59f07ed 100644 --- a/arch/arm/plat-mxc/pwm.c +++ b/arch/arm/plat-mxc/pwm.c @@ -32,6 +32,9 @@ #define MX3_PWMSAR 0x0C /* PWM Sample Register */ #define MX3_PWMPR 0x10 /* PWM Period Register */ #define MX3_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4) +#define MX3_PWMCR_DOZEEN (1 << 24) +#define MX3_PWMCR_WAITEN (1 << 23) +#define MX3_PWMCR_DBGEN (1 << 22) #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) #define MX3_PWMCR_CLKSRC_IPG (1 << 16) #define MX3_PWMCR_EN (1 << 0) @@ -77,7 +80,9 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR); writel(period_cycles, pwm->mmio_base + MX3_PWMPR); - cr = MX3_PWMCR_PRESCALER(prescale) | MX3_PWMCR_EN; + cr = MX3_PWMCR_PRESCALER(prescale) | + MX3_PWMCR_DOZEEN | MX3_PWMCR_WAITEN | + MX3_PWMCR_DBGEN | MX3_PWMCR_EN; if (cpu_is_mx25()) cr |= MX3_PWMCR_CLKSRC_IPG; diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 30e10719b774..6e5d3a0cb9d5 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -357,7 +357,7 @@ #define INT_35XX_EMAC_C0_TX_PULSE_IRQ 69 #define INT_35XX_EMAC_C0_MISC_PULSE_IRQ 70 #define INT_35XX_USBOTG_IRQ 71 -#define INT_35XX_UART4 84 +#define INT_35XX_UART4_IRQ 84 #define INT_35XX_CCDC_VD0_IRQ 88 #define INT_35XX_CCDC_VD1_IRQ 92 #define INT_35XX_CCDC_VD2_IRQ 93 diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index 94cf70afb236..f75946c3293d 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -96,6 +96,7 @@ struct omap_mmc_platform_data { */ u8 wires; /* Used for the MMC driver on omap1 and 2420 */ u32 caps; /* Used for the MMC driver on 2430 and later */ + u32 pm_caps; /* PM capabilities of the mmc */ /* * nomux means "standard" muxing is wrong on this board, and diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index 1ab9fd6abe6d..865a2ba7ffa8 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -44,6 +44,7 @@ #define OMAP3_UART2_BASE OMAP2_UART2_BASE #define OMAP3_UART3_BASE 0x49020000 #define OMAP3_UART4_BASE 0x49042000 /* Only on 36xx */ +#define OMAP3_UART4_AM35XX_BASE 0x4809E000 /* Only on AM35xx */ /* OMAP4 serial ports */ #define OMAP4_UART1_BASE OMAP2_UART1_BASE diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h index 17d3c939775c..2b66dc266bcf 100644 --- a/arch/arm/plat-omap/include/plat/usb.h +++ b/arch/arm/plat-omap/include/plat/usb.h @@ -100,9 +100,6 @@ extern void usb_musb_init(struct omap_musb_board_data *board_data); extern void usbhs_init(const struct usbhs_omap_board_data *pdata); -extern int omap_usbhs_enable(struct device *dev); -extern void omap_usbhs_disable(struct device *dev); - extern int omap4430_phy_power(struct device *dev, int ID, int on); extern int omap4430_phy_set_clk(struct device *dev, int on); extern int omap4430_phy_init(struct device *dev); diff --git a/arch/arm/plat-pxa/include/plat/gpio-pxa.h b/arch/arm/plat-pxa/include/plat/gpio-pxa.h deleted file mode 100644 index b6390beff323..000000000000 --- a/arch/arm/plat-pxa/include/plat/gpio-pxa.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __PLAT_PXA_GPIO_H -#define __PLAT_PXA_GPIO_H - -struct irq_data; - -/* - * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with - * one set of registers. The register offsets are organized below: - * - * GPLR GPDR GPSR GPCR GRER GFER GEDR - * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 - * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C - * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 - * - * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 - * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C - * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 - * - * NOTE: - * BANK 3 is only available on PXA27x and later processors. - * BANK 4 and 5 are only available on PXA935 - */ - -#define GPIO_BANK(n) (GPIO_REGS_VIRT + BANK_OFF(n)) - -#define GPLR_OFFSET 0x00 -#define GPDR_OFFSET 0x0C -#define GPSR_OFFSET 0x18 -#define GPCR_OFFSET 0x24 -#define GRER_OFFSET 0x30 -#define GFER_OFFSET 0x3C -#define GEDR_OFFSET 0x48 - -/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). - * Those cases currently cause holes in the GPIO number space, the - * actual number of the last GPIO is recorded by 'pxa_last_gpio'. - */ -extern int pxa_last_gpio; - -typedef int (*set_wake_t)(struct irq_data *d, unsigned int on); - -extern void pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn); - -#endif /* __PLAT_PXA_GPIO_H */ diff --git a/arch/arm/plat-pxa/include/plat/gpio.h b/arch/arm/plat-pxa/include/plat/gpio.h deleted file mode 100644 index 258f77210b02..000000000000 --- a/arch/arm/plat-pxa/include/plat/gpio.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __PLAT_GPIO_H -#define __PLAT_GPIO_H - -#define __ARM_GPIOLIB_COMPLEX - -/* The individual machine provides register offsets and NR_BUILTIN_GPIO */ -#include <mach/gpio-pxa.h> - -static inline int gpio_get_value(unsigned gpio) -{ - if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) - return GPLR(gpio) & GPIO_bit(gpio); - else - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) { - if (value) - GPSR(gpio) = GPIO_bit(gpio); - else - GPCR(gpio) = GPIO_bit(gpio); - } else - __gpio_set_value(gpio, value); -} - -#define gpio_cansleep __gpio_cansleep - -#endif /* __PLAT_GPIO_H */ diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c index 5a21b15b2a97..95e68190d593 100644 --- a/arch/arm/plat-s3c24xx/s3c2443-clock.c +++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c @@ -297,13 +297,6 @@ static struct clksrc_clk clk_usb_bus_host = { static struct clksrc_clk clksrc_clks[] = { { - /* ART baud-rate clock sourced from esysclk via a divisor */ - .clk = { - .name = "uartclk", - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, - }, { /* camera interface bus-clock, divided down from esysclk */ .clk = { .name = "camif-upll", /* same as 2440 name */ @@ -323,6 +316,15 @@ static struct clksrc_clk clksrc_clks[] = { }, }; +static struct clksrc_clk clk_esys_uart = { + /* ART baud-rate clock sourced from esysclk via a divisor */ + .clk = { + .name = "uartclk", + .parent = &clk_esysclk.clk, + }, + .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, +}; + static struct clk clk_i2s_ext = { .name = "i2s-ext", }; @@ -425,12 +427,6 @@ static struct clk init_clocks[] = { .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, .enable = s3c2443_clkcon_enable_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); } diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 313eb26cfa62..160eea15a6ef 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -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 diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c index e657305644cc..a976c023b286 100644 --- a/arch/arm/plat-samsung/dev-backlight.c +++ b/arch/arm/plat-samsung/dev-backlight.c @@ -15,7 +15,6 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/pwm_backlight.h> -#include <linux/slab.h> #include <plat/devs.h> #include <plat/gpio-cfg.h> diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 4ca8b571f971..de0d88d6a0f1 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -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 */ diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index 93a994a5dd8f..2cded872f22b 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c @@ -18,23 +18,24 @@ #include <mach/dma.h> -static inline bool pl330_filter(struct dma_chan *chan, void *param) -{ - struct dma_pl330_peri *peri = chan->private; - return peri->peri_id == (unsigned)param; -} - static unsigned samsung_dmadev_request(enum dma_ch dma_ch, struct samsung_dma_info *info) { struct dma_chan *chan; dma_cap_mask_t mask; struct dma_slave_config slave_config; + void *filter_param; dma_cap_zero(mask); dma_cap_set(info->cap, mask); - chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch); + /* + * If a dma channel property of a device node from device tree is + * specified, use that as the fliter parameter. + */ + filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop : + (void *)dma_ch; + chan = dma_request_channel(mask, pl330_filter, filter_param); if (info->direction == DMA_FROM_DEVICE) { memset(&slave_config, 0, sizeof(struct dma_slave_config)); diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index ab633c9c2aec..4214ea0ff8fe 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -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; @@ -129,6 +123,7 @@ extern struct platform_device exynos4_device_dwmci; extern struct platform_device exynos4_device_i2s0; extern struct platform_device exynos4_device_i2s1; extern struct platform_device exynos4_device_i2s2; +extern struct platform_device exynos4_device_ohci; extern struct platform_device exynos4_device_pcm0; extern struct platform_device exynos4_device_pcm1; extern struct platform_device exynos4_device_pcm2; diff --git a/arch/arm/plat-samsung/include/plat/dma-ops.h b/arch/arm/plat-samsung/include/plat/dma-ops.h index 4c1a363526cf..22eafc310bd7 100644 --- a/arch/arm/plat-samsung/include/plat/dma-ops.h +++ b/arch/arm/plat-samsung/include/plat/dma-ops.h @@ -31,6 +31,7 @@ struct samsung_dma_info { enum dma_slave_buswidth width; dma_addr_t fifo; struct s3c2410_dma_client *client; + struct property *dt_dmach_prop; }; struct samsung_dma_ops { diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h index 2e55e5958674..c5eaad529de5 100644 --- a/arch/arm/plat-samsung/include/plat/dma-pl330.h +++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h @@ -21,7 +21,8 @@ * use these just as IDs. */ enum dma_ch { - DMACH_UART0_RX, + DMACH_DT_PROP = -1, + DMACH_UART0_RX = 0, DMACH_UART0_TX, DMACH_UART1_RX, DMACH_UART1_TX, diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h index 08d1a7ef97b7..df46b776976a 100644 --- a/arch/arm/plat-samsung/include/plat/irqs.h +++ b/arch/arm/plat-samsung/include/plat/irqs.h @@ -44,13 +44,14 @@ #define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x)) #define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x)) -#define S5P_TIMER_IRQ(x) (11 + (x)) +#define S5P_TIMER_IRQ(x) (IRQ_TIMER_BASE + (x)) #define IRQ_TIMER0 S5P_TIMER_IRQ(0) #define IRQ_TIMER1 S5P_TIMER_IRQ(1) #define IRQ_TIMER2 S5P_TIMER_IRQ(2) #define IRQ_TIMER3 S5P_TIMER_IRQ(3) #define IRQ_TIMER4 S5P_TIMER_IRQ(4) +#define IRQ_TIMER_COUNT (5) #define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \ : ((x) - 16 + S5P_EINT_BASE2)) diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index 720734847027..29c26a818842 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h @@ -71,6 +71,7 @@ #define S3C2410_LCON_IRM (1<<6) #define S3C2440_UCON_CLKMASK (3<<10) +#define S3C2440_UCON_CLKSHIFT (10) #define S3C2440_UCON_PCLK (0<<10) #define S3C2440_UCON_UCLK (1<<10) #define S3C2440_UCON_PCLK2 (2<<10) @@ -78,6 +79,7 @@ #define S3C2443_UCON_EPLL (3<<10) #define S3C6400_UCON_CLKMASK (3<<10) +#define S3C6400_UCON_CLKSHIFT (10) #define S3C6400_UCON_PCLK (0<<10) #define S3C6400_UCON_PCLK2 (2<<10) #define S3C6400_UCON_UCLK0 (1<<10) @@ -90,11 +92,14 @@ #define S3C2440_UCON_DIVSHIFT (12) #define S3C2412_UCON_CLKMASK (3<<10) +#define S3C2412_UCON_CLKSHIFT (10) #define S3C2412_UCON_UCLK (1<<10) #define S3C2412_UCON_USYSCLK (3<<10) #define S3C2412_UCON_PCLK (0<<10) #define S3C2412_UCON_PCLK2 (2<<10) +#define S3C2410_UCON_CLKMASK (1 << 10) +#define S3C2410_UCON_CLKSHIFT (10) #define S3C2410_UCON_UCLK (1<<10) #define S3C2410_UCON_SBREAK (1<<4) @@ -193,6 +198,7 @@ /* Following are specific to S5PV210 */ #define S5PV210_UCON_CLKMASK (1<<10) +#define S5PV210_UCON_CLKSHIFT (10) #define S5PV210_UCON_PCLK (0<<10) #define S5PV210_UCON_UCLK (1<<10) @@ -221,29 +227,24 @@ #define S5PV210_UFSTAT_RXMASK (255<<0) #define S5PV210_UFSTAT_RXSHIFT (0) -#define NO_NEED_CHECK_CLKSRC 1 +#define S3C2410_UCON_CLKSEL0 (1 << 0) +#define S3C2410_UCON_CLKSEL1 (1 << 1) +#define S3C2410_UCON_CLKSEL2 (1 << 2) +#define S3C2410_UCON_CLKSEL3 (1 << 3) -#ifndef __ASSEMBLY__ +/* Default values for s5pv210 UCON and UFCON uart registers */ +#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ + S3C2410_UCON_RXILEVEL | \ + S3C2410_UCON_TXIRQMODE | \ + S3C2410_UCON_RXIRQMODE | \ + S3C2410_UCON_RXFIFO_TOI | \ + S3C2443_UCON_RXERR_IRQEN) -/* struct s3c24xx_uart_clksrc - * - * this structure defines a named clock source that can be used for the - * uart, so that the best clock can be selected for the requested baud - * rate. - * - * min_baud and max_baud define the range of baud-rates this clock is - * acceptable for, if they are both zero, it is assumed any baud rate that - * can be generated from this clock will be used. - * - * divisor gives the divisor from the clock to the one seen by the uart -*/ +#define S5PV210_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE | \ + S5PV210_UFCON_TXTRIG4 | \ + S5PV210_UFCON_RXTRIG4) -struct s3c24xx_uart_clksrc { - const char *name; - unsigned int divisor; - unsigned int min_baud; - unsigned int max_baud; -}; +#ifndef __ASSEMBLY__ /* configuration structure for per-machine configurations for the * serial port @@ -257,15 +258,13 @@ struct s3c2410_uartcfg { unsigned char unused; unsigned short flags; upf_t uart_flags; /* default uart flags */ + unsigned int clk_sel; unsigned int has_fracval; unsigned long ucon; /* value of ucon for port */ unsigned long ulcon; /* value of ulcon for port */ unsigned long ufcon; /* value of ufcon for port */ - - struct s3c24xx_uart_clksrc *clocks; - unsigned int clocks_size; }; /* s3c24xx_uart_devs diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index 4c16fa3621bb..aea68b60ef98 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h @@ -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 */ diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h index e7b3c752e919..656dc00d30ed 100644 --- a/arch/arm/plat-samsung/include/plat/sdhci.h +++ b/arch/arm/plat-samsung/include/plat/sdhci.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 *, @@ -125,16 +123,17 @@ extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w); extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w); +extern void s5p64x0_setup_sdhci0_cfg_gpio(struct platform_device *, int w); +extern void s5p64x0_setup_sdhci1_cfg_gpio(struct platform_device *, int w); +extern void s5p6440_setup_sdhci2_cfg_gpio(struct platform_device *, int w); +extern void s5p6450_setup_sdhci2_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 +141,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 */ } @@ -152,15 +150,13 @@ static inline void s3c2416_default_sdhci0(void) { } static inline void s3c2416_default_sdhci1(void) { } #endif /* CONFIG_S3C2416_SETUP_SDHCI */ + /* 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 +164,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 +171,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 +178,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 +185,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 +192,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 } @@ -215,15 +206,51 @@ static inline void s3c6400_default_sdhci2(void) { } #endif /* CONFIG_S3C64XX_SETUP_SDHCI */ +/* S5P64X0 SDHCI setup */ + +#ifdef CONFIG_S5P64X0_SETUP_SDHCI +static inline void s5p64x0_default_sdhci0(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC + s3c_hsmmc0_def_platdata.cfg_gpio = s5p64x0_setup_sdhci0_cfg_gpio; +#endif +} + +static inline void s5p64x0_default_sdhci1(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC1 + s3c_hsmmc1_def_platdata.cfg_gpio = s5p64x0_setup_sdhci1_cfg_gpio; +#endif +} + +static inline void s5p6440_default_sdhci2(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC2 + s3c_hsmmc2_def_platdata.cfg_gpio = s5p6440_setup_sdhci2_cfg_gpio; +#endif +} + +static inline void s5p6450_default_sdhci2(void) +{ +#ifdef CONFIG_S3C_DEV_HSMMC2 + s3c_hsmmc2_def_platdata.cfg_gpio = s5p6450_setup_sdhci2_cfg_gpio; +#endif +} + +#else +static inline void s5p64x0_default_sdhci0(void) { } +static inline void s5p64x0_default_sdhci1(void) { } +static inline void s5p6440_default_sdhci2(void) { } +static inline void s5p6450_default_sdhci2(void) { } + +#endif /* CONFIG_S5P64X0_SETUP_SDHCI */ + /* 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 +258,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 +265,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 +279,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 +289,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 +296,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 +303,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 +317,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 +327,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 +334,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 +341,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 } diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index 1f17bde52cd4..7c756fb189f7 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c @@ -109,7 +109,7 @@ struct eth_addr { u8 addr[6]; }; static struct eth_addr __initdata hw_addr[2]; -static struct eth_platform_data __initdata eth_data[2]; +static struct macb_platform_data __initdata eth_data[2]; static struct spi_board_info spi0_board_info[] __initdata = { { diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index 4643ff5107c9..c56ddac85d61 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c @@ -105,7 +105,7 @@ struct eth_addr { }; static struct eth_addr __initdata hw_addr[2]; -static struct eth_platform_data __initdata eth_data[2] = { +static struct macb_platform_data __initdata eth_data[2] = { { /* * The MDIO pullups on STK1000 are a bit too weak for diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c index 86fab77a5a00..27bd6fbe21cb 100644 --- a/arch/avr32/boards/favr-32/setup.c +++ b/arch/avr32/boards/favr-32/setup.c @@ -50,7 +50,7 @@ struct eth_addr { u8 addr[6]; }; static struct eth_addr __initdata hw_addr[1]; -static struct eth_platform_data __initdata eth_data[1] = { +static struct macb_platform_data __initdata eth_data[1] = { { .phy_mask = ~(1U << 1), }, diff --git a/arch/avr32/boards/hammerhead/setup.c b/arch/avr32/boards/hammerhead/setup.c index da14fbdd4e8e..9d1efd1cd425 100644 --- a/arch/avr32/boards/hammerhead/setup.c +++ b/arch/avr32/boards/hammerhead/setup.c @@ -102,7 +102,7 @@ struct eth_addr { }; static struct eth_addr __initdata hw_addr[1]; -static struct eth_platform_data __initdata eth_data[1]; +static struct macb_platform_data __initdata eth_data[1]; /* * The next two functions should go away as the boot loader is diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c index e61bc948f959..ed137e335796 100644 --- a/arch/avr32/boards/merisc/setup.c +++ b/arch/avr32/boards/merisc/setup.c @@ -52,7 +52,7 @@ struct eth_addr { }; static struct eth_addr __initdata hw_addr[2]; -static struct eth_platform_data __initdata eth_data[2]; +static struct macb_platform_data __initdata eth_data[2]; static int ads7846_get_pendown_state_PB26(void) { diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c index c4da5cba2dbf..05358aa5ef7d 100644 --- a/arch/avr32/boards/mimc200/setup.c +++ b/arch/avr32/boards/mimc200/setup.c @@ -86,7 +86,7 @@ struct eth_addr { u8 addr[6]; }; static struct eth_addr __initdata hw_addr[2]; -static struct eth_platform_data __initdata eth_data[2]; +static struct macb_platform_data __initdata eth_data[2]; static struct spi_eeprom eeprom_25lc010 = { .name = "25lc010", diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 7fbf0dcb9afe..402a7bb72669 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -1067,7 +1067,7 @@ void __init at32_setup_serial_console(unsigned int usart_id) * -------------------------------------------------------------------- */ #ifdef CONFIG_CPU_AT32AP7000 -static struct eth_platform_data macb0_data; +static struct macb_platform_data macb0_data; static struct resource macb0_resource[] = { PBMEM(0xfff01800), IRQ(25), @@ -1076,7 +1076,7 @@ DEFINE_DEV_DATA(macb, 0); DEV_CLK(hclk, macb0, hsb, 8); DEV_CLK(pclk, macb0, pbb, 6); -static struct eth_platform_data macb1_data; +static struct macb_platform_data macb1_data; static struct resource macb1_resource[] = { PBMEM(0xfff01c00), IRQ(26), @@ -1086,7 +1086,7 @@ DEV_CLK(hclk, macb1, hsb, 9); DEV_CLK(pclk, macb1, pbb, 7); struct platform_device *__init -at32_add_device_eth(unsigned int id, struct eth_platform_data *data) +at32_add_device_eth(unsigned int id, struct macb_platform_data *data) { struct platform_device *pdev; u32 pin_mask; @@ -1163,7 +1163,7 @@ at32_add_device_eth(unsigned int id, struct eth_platform_data *data) return NULL; } - memcpy(pdev->dev.platform_data, data, sizeof(struct eth_platform_data)); + memcpy(pdev->dev.platform_data, data, sizeof(struct macb_platform_data)); platform_device_register(pdev); return pdev; diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index 5d7ffca7d69f..67b111ce332d 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h @@ -6,6 +6,7 @@ #include <linux/types.h> #include <linux/serial.h> +#include <linux/platform_data/macb.h> #define GPIO_PIN_NONE (-1) @@ -42,12 +43,8 @@ struct atmel_uart_data { void at32_map_usart(unsigned int hw_id, unsigned int line, int flags); struct platform_device *at32_add_device_usart(unsigned int id); -struct eth_platform_data { - u32 phy_mask; - u8 is_rmii; -}; struct platform_device * -at32_add_device_eth(unsigned int id, struct eth_platform_data *data); +at32_add_device_eth(unsigned int id, struct macb_platform_data *data); struct spi_board_info; struct platform_device * diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index 7429b47c3aca..381edcd5bc29 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -1181,13 +1181,11 @@ static int __devinit ds_probe(struct vio_dev *vdev, dp->rcv_buf_len = 4096; - dp->ds_states = kzalloc(sizeof(ds_states_template), - GFP_KERNEL); + dp->ds_states = kmemdup(ds_states_template, + sizeof(ds_states_template), GFP_KERNEL); if (!dp->ds_states) goto out_free_rcv_buf; - memcpy(dp->ds_states, ds_states_template, - sizeof(ds_states_template)); dp->num_ds_states = ARRAY_SIZE(ds_states_template); for (i = 0; i < dp->num_ds_states; i++) diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c index 46614807a57f..741df916c124 100644 --- a/arch/sparc/kernel/prom_common.c +++ b/arch/sparc/kernel/prom_common.c @@ -58,12 +58,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len void *new_val; int err; - new_val = kmalloc(len, GFP_KERNEL); + new_val = kmemdup(val, len, GFP_KERNEL); if (!new_val) return -ENOMEM; - memcpy(new_val, val, len); - err = -ENODEV; mutex_lock(&of_set_property_mutex); diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c index 5175ac2f4820..8a7f81743c12 100644 --- a/arch/sparc/mm/btfixup.c +++ b/arch/sparc/mm/btfixup.c @@ -302,8 +302,7 @@ void __init btfixup(void) case 'i': /* INT */ if ((insn & 0xc1c00000) == 0x01000000) /* %HI */ set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10)); - else if ((insn & 0x80002000) == 0x80002000 && - (insn & 0x01800000) != 0x01800000) /* %LO */ + else if ((insn & 0x80002000) == 0x80002000) /* %LO */ set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff)); else { prom_printf(insn_i, p, addr, insn); diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index c9547033e38e..908b96957d88 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -53,13 +53,6 @@ */ #define E820_RESERVED_KERN 128 -/* - * Address ranges that need to be mapped by the kernel direct - * mapping. This is used to make sure regions such as - * EFI_RUNTIME_SERVICES_DATA are directly mapped. See setup_arch(). - */ -#define E820_RESERVED_EFI 129 - #ifndef __ASSEMBLY__ #include <linux/types.h> struct e820entry { @@ -122,7 +115,6 @@ static inline void early_memtest(unsigned long start, unsigned long end) } #endif -extern unsigned long e820_end_pfn(unsigned long limit_pfn, unsigned type); extern unsigned long e820_end_of_ram_pfn(void); extern unsigned long e820_end_of_low_ram_pfn(void); extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index b8d8bfcd44a9..7093e4a6a0bc 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -33,6 +33,8 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ efi_call_virt(f, a1, a2, a3, a4, a5, a6) +#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) + #else /* !CONFIG_X86_32 */ extern u64 efi_call0(void *fp); @@ -82,6 +84,9 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \ (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) +extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, + u32 type); + #endif /* CONFIG_X86_32 */ extern int add_efi_memmap; diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 65ffd110a81b..303a0e48f076 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -135,7 +135,6 @@ static void __init e820_print_type(u32 type) printk(KERN_CONT "(usable)"); break; case E820_RESERVED: - case E820_RESERVED_EFI: printk(KERN_CONT "(reserved)"); break; case E820_ACPI: @@ -784,7 +783,7 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align) /* * Find the highest page frame number we have available */ -unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) +static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type) { int i; unsigned long last_pfn = 0; diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9a9e40fb091c..cf0ef986cb6d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -691,8 +691,6 @@ early_param("reservelow", parse_reservelow); void __init setup_arch(char **cmdline_p) { - unsigned long end_pfn; - #ifdef CONFIG_X86_32 memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data)); visws_early_detect(); @@ -934,24 +932,7 @@ void __init setup_arch(char **cmdline_p) init_gbpages(); /* max_pfn_mapped is updated here */ - end_pfn = max_low_pfn; - -#ifdef CONFIG_X86_64 - /* - * There may be regions after the last E820_RAM region that we - * want to include in the kernel direct mapping, such as - * EFI_RUNTIME_SERVICES_DATA. - */ - if (efi_enabled) { - unsigned long efi_end; - - efi_end = e820_end_pfn(MAXMEM>>PAGE_SHIFT, E820_RESERVED_EFI); - if (efi_end > max_low_pfn) - end_pfn = efi_end; - } -#endif - - max_low_pfn_mapped = init_memory_mapping(0, end_pfn << PAGE_SHIFT); + max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); max_pfn_mapped = max_low_pfn_mapped; #ifdef CONFIG_X86_64 diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index c9718a16be15..37718f0f053d 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -323,13 +323,10 @@ static void __init do_add_efi_memmap(void) case EFI_UNUSABLE_MEMORY: e820_type = E820_UNUSABLE; break; - case EFI_RUNTIME_SERVICES_DATA: - e820_type = E820_RESERVED_EFI; - break; default: /* * EFI_RESERVED_TYPE EFI_RUNTIME_SERVICES_CODE - * EFI_MEMORY_MAPPED_IO + * EFI_RUNTIME_SERVICES_DATA EFI_MEMORY_MAPPED_IO * EFI_MEMORY_MAPPED_IO_PORT_SPACE EFI_PAL_CODE */ e820_type = E820_RESERVED; @@ -674,21 +671,10 @@ void __init efi_enter_virtual_mode(void) end_pfn = PFN_UP(end); if (end_pfn <= max_low_pfn_mapped || (end_pfn > (1UL << (32 - PAGE_SHIFT)) - && end_pfn <= max_pfn_mapped)) { + && end_pfn <= max_pfn_mapped)) va = __va(md->phys_addr); - - if (!(md->attribute & EFI_MEMORY_WB)) { - addr = (u64) (unsigned long)va; - npages = md->num_pages; - memrange_efi_to_native(&addr, &npages); - set_memory_uc(addr, npages); - } - } else { - if (!(md->attribute & EFI_MEMORY_WB)) - va = ioremap_nocache(md->phys_addr, size); - else - va = ioremap_cache(md->phys_addr, size); - } + else + va = efi_ioremap(md->phys_addr, size, md->type); md->virt_addr = (u64) (unsigned long) va; @@ -698,6 +684,13 @@ void __init efi_enter_virtual_mode(void) continue; } + if (!(md->attribute & EFI_MEMORY_WB)) { + addr = md->virt_addr; + npages = md->num_pages; + memrange_efi_to_native(&addr, &npages); + set_memory_uc(addr, npages); + } + systab = (u64) (unsigned long) efi_phys.systab; if (md->phys_addr <= systab && systab < end) { systab += md->virt_addr - md->phys_addr; diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index e36bf714cb77..40e446941dd7 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -39,43 +39,14 @@ */ static unsigned long efi_rt_eflags; -static pgd_t efi_bak_pg_dir_pointer[2]; void efi_call_phys_prelog(void) { - unsigned long cr4; - unsigned long temp; struct desc_ptr gdt_descr; local_irq_save(efi_rt_eflags); - /* - * If I don't have PAE, I should just duplicate two entries in page - * directory. If I have PAE, I just need to duplicate one entry in - * page directory. - */ - cr4 = read_cr4_safe(); - - if (cr4 & X86_CR4_PAE) { - efi_bak_pg_dir_pointer[0].pgd = - swapper_pg_dir[pgd_index(0)].pgd; - swapper_pg_dir[0].pgd = - swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; - } else { - efi_bak_pg_dir_pointer[0].pgd = - swapper_pg_dir[pgd_index(0)].pgd; - efi_bak_pg_dir_pointer[1].pgd = - swapper_pg_dir[pgd_index(0x400000)].pgd; - swapper_pg_dir[pgd_index(0)].pgd = - swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; - temp = PAGE_OFFSET + 0x400000; - swapper_pg_dir[pgd_index(0x400000)].pgd = - swapper_pg_dir[pgd_index(temp)].pgd; - } - - /* - * After the lock is released, the original page table is restored. - */ + load_cr3(initial_page_table); __flush_tlb_all(); gdt_descr.address = __pa(get_cpu_gdt_table(0)); @@ -85,28 +56,13 @@ void efi_call_phys_prelog(void) void efi_call_phys_epilog(void) { - unsigned long cr4; struct desc_ptr gdt_descr; gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); - cr4 = read_cr4_safe(); - - if (cr4 & X86_CR4_PAE) { - swapper_pg_dir[pgd_index(0)].pgd = - efi_bak_pg_dir_pointer[0].pgd; - } else { - swapper_pg_dir[pgd_index(0)].pgd = - efi_bak_pg_dir_pointer[0].pgd; - swapper_pg_dir[pgd_index(0x400000)].pgd = - efi_bak_pg_dir_pointer[1].pgd; - } - - /* - * After the lock is released, the original page table is restored. - */ + load_cr3(swapper_pg_dir); __flush_tlb_all(); local_irq_restore(efi_rt_eflags); diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 312250c6b2de..ac3aa54e2654 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -80,3 +80,20 @@ void __init efi_call_phys_epilog(void) local_irq_restore(efi_flags); early_code_mapping_set_exec(0); } + +void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, + u32 type) +{ + unsigned long last_map_pfn; + + if (type == EFI_MEMORY_MAPPED_IO) + return ioremap(phys_addr, size); + + last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); + if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { + unsigned long top = last_map_pfn << PAGE_SHIFT; + efi_ioremap(top, size - (top - phys_addr), type); + } + + return (void __iomem *)__va(phys_addr); +} diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 1093f80c162d..b2c7179fa263 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -173,9 +173,21 @@ static unsigned long __init xen_get_max_pages(void) domid_t domid = DOMID_SELF; int ret; - ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); - if (ret > 0) - max_pages = ret; + /* + * For the initial domain we use the maximum reservation as + * the maximum page. + * + * For guest domains the current maximum reservation reflects + * the current maximum rather than the static maximum. In this + * case the e820 map provided to us will cover the static + * maximum region. + */ + if (xen_initial_domain()) { + ret = HYPERVISOR_memory_op(XENMEM_maximum_reservation, &domid); + if (ret > 0) + max_pages = ret; + } + return min(max_pages, MAX_DOMAIN_PAGES); } diff --git a/block/blk-core.c b/block/blk-core.c index ea70e6c80cd3..15de223c7f93 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -366,7 +366,14 @@ void blk_drain_queue(struct request_queue *q, bool drain_all) if (drain_all) blk_throtl_drain(q); - __blk_run_queue(q); + /* + * This function might be called on a queue which failed + * driver init after queue creation. Some drivers + * (e.g. fd) get unhappy in such cases. Kick queue iff + * dispatch queue has something on it. + */ + if (!list_empty(&q->queue_head)) + __blk_run_queue(q); if (drain_all) nr_rqs = q->rq.count[0] + q->rq.count[1]; @@ -467,6 +474,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) q->backing_dev_info.state = 0; q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY; q->backing_dev_info.name = "block"; + q->node = node_id; err = bdi_init(&q->backing_dev_info); if (err) { @@ -551,7 +559,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) if (!uninit_q) return NULL; - q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id); + q = blk_init_allocated_queue(uninit_q, rfn, lock); if (!q) blk_cleanup_queue(uninit_q); @@ -563,18 +571,9 @@ struct request_queue * blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, spinlock_t *lock) { - return blk_init_allocated_queue_node(q, rfn, lock, -1); -} -EXPORT_SYMBOL(blk_init_allocated_queue); - -struct request_queue * -blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, - spinlock_t *lock, int node_id) -{ if (!q) return NULL; - q->node = node_id; if (blk_init_free_list(q)) return NULL; @@ -604,7 +603,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn, return NULL; } -EXPORT_SYMBOL(blk_init_allocated_queue_node); +EXPORT_SYMBOL(blk_init_allocated_queue); int blk_get_queue(struct request_queue *q) { diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 16ace89613bc..4c12869fcf77 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3184,7 +3184,7 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, } } - if (ret) + if (ret && ret != -EEXIST) printk(KERN_ERR "cfq: cic link failed!\n"); return ret; @@ -3200,6 +3200,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) { struct io_context *ioc = NULL; struct cfq_io_context *cic; + int ret; might_sleep_if(gfp_mask & __GFP_WAIT); @@ -3207,6 +3208,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (!ioc) return NULL; +retry: cic = cfq_cic_lookup(cfqd, ioc); if (cic) goto out; @@ -3215,7 +3217,12 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (cic == NULL) goto err; - if (cfq_cic_link(cfqd, ioc, cic, gfp_mask)) + ret = cfq_cic_link(cfqd, ioc, cic, gfp_mask); + if (ret == -EEXIST) { + /* someone has linked cic to ioc already */ + cfq_cic_free(cic); + goto retry; + } else if (ret) goto err_free; out: @@ -4036,6 +4043,11 @@ static void *cfq_init_queue(struct request_queue *q) if (blkio_alloc_blkg_stats(&cfqg->blkg)) { kfree(cfqg); + + spin_lock(&cic_index_lock); + ida_remove(&cic_index_ida, cfqd->cic_index); + spin_unlock(&cic_index_lock); + kfree(cfqd); return NULL; } diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 8004ac30a7a8..587cce57adae 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2601,6 +2601,8 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, c->Request.Timeout = 0; c->Request.CDB[0] = BMIC_WRITE; c->Request.CDB[6] = BMIC_CACHE_FLUSH; + c->Request.CDB[7] = (size >> 8) & 0xFF; + c->Request.CDB[8] = size & 0xFF; break; case TEST_UNIT_READY: c->Request.CDBLen = 6; @@ -4880,7 +4882,7 @@ static int cciss_request_irq(ctlr_info_t *h, { if (h->msix_vector || h->msi_vector) { if (!request_irq(h->intr[h->intr_mode], msixhandler, - IRQF_DISABLED, h->devname, h)) + 0, h->devname, h)) return 0; dev_err(&h->pdev->dev, "Unable to get msi irq %d" " for %s\n", h->intr[h->intr_mode], @@ -4889,7 +4891,7 @@ static int cciss_request_irq(ctlr_info_t *h, } if (!request_irq(h->intr[h->intr_mode], intxhandler, - IRQF_DISABLED, h->devname, h)) + IRQF_SHARED, h->devname, h)) return 0; dev_err(&h->pdev->dev, "Unable to get irq %d for %s\n", h->intr[h->intr_mode], h->devname); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 68b205a9338f..1e888c9e85b3 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -422,7 +422,7 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) /* * We use punch hole to reclaim the free space used by the - * image a.k.a. discard. However we do support discard if + * image a.k.a. discard. However we do not support discard if * encryption is enabled, because it may give an attacker * useful information. */ @@ -797,7 +797,7 @@ static void loop_config_discard(struct loop_device *lo) } q->limits.discard_granularity = inode->i_sb->s_blocksize; - q->limits.discard_alignment = inode->i_sb->s_blocksize; + q->limits.discard_alignment = 0; q->limits.max_discard_sectors = UINT_MAX >> 9; q->limits.discard_zeroes_data = 1; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 65cc424359b0..148ab944378d 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -183,10 +183,6 @@ static LIST_HEAD(rbd_client_list); /* clients */ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev); static void rbd_dev_release(struct device *dev); -static ssize_t rbd_snap_rollback(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size); static ssize_t rbd_snap_add(struct device *dev, struct device_attribute *attr, const char *buf, @@ -461,6 +457,10 @@ static int rbd_header_from_disk(struct rbd_image_header *header, u32 snap_count = le32_to_cpu(ondisk->snap_count); int ret = -ENOMEM; + if (memcmp(ondisk, RBD_HEADER_TEXT, sizeof(RBD_HEADER_TEXT))) { + return -ENXIO; + } + init_rwsem(&header->snap_rwsem); header->snap_names_len = le64_to_cpu(ondisk->snap_names_len); header->snapc = kmalloc(sizeof(struct ceph_snap_context) + @@ -1356,32 +1356,6 @@ fail: } /* - * Request sync osd rollback - */ -static int rbd_req_sync_rollback_obj(struct rbd_device *dev, - u64 snapid, - const char *obj) -{ - struct ceph_osd_req_op *ops; - int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_ROLLBACK, 0); - if (ret < 0) - return ret; - - ops[0].snap.snapid = snapid; - - ret = rbd_req_sync_op(dev, NULL, - CEPH_NOSNAP, - 0, - CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, - ops, - 1, obj, 0, 0, NULL, NULL, NULL); - - rbd_destroy_ops(ops); - - return ret; -} - -/* * Request sync osd read */ static int rbd_req_sync_exec(struct rbd_device *dev, @@ -1610,8 +1584,13 @@ static int rbd_read_header(struct rbd_device *rbd_dev, goto out_dh; rc = rbd_header_from_disk(header, dh, snap_count, GFP_KERNEL); - if (rc < 0) + if (rc < 0) { + if (rc == -ENXIO) { + pr_warning("unrecognized header format" + " for image %s", rbd_dev->obj); + } goto out_dh; + } if (snap_count != header->total_snaps) { snap_count = header->total_snaps; @@ -1882,7 +1861,6 @@ static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL); static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add); -static DEVICE_ATTR(rollback_snap, S_IWUSR, NULL, rbd_snap_rollback); static struct attribute *rbd_attrs[] = { &dev_attr_size.attr, @@ -1893,7 +1871,6 @@ static struct attribute *rbd_attrs[] = { &dev_attr_current_snap.attr, &dev_attr_refresh.attr, &dev_attr_create_snap.attr, - &dev_attr_rollback_snap.attr, NULL }; @@ -2424,64 +2401,6 @@ err_unlock: return ret; } -static ssize_t rbd_snap_rollback(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct rbd_device *rbd_dev = dev_to_rbd(dev); - int ret; - u64 snapid; - u64 cur_ofs; - char *seg_name = NULL; - char *snap_name = kmalloc(count + 1, GFP_KERNEL); - ret = -ENOMEM; - if (!snap_name) - return ret; - - /* parse snaps add command */ - snprintf(snap_name, count, "%s", buf); - seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); - if (!seg_name) - goto done; - - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - - ret = snap_by_name(&rbd_dev->header, snap_name, &snapid, NULL); - if (ret < 0) - goto done_unlock; - - dout("snapid=%lld\n", snapid); - - cur_ofs = 0; - while (cur_ofs < rbd_dev->header.image_size) { - cur_ofs += rbd_get_segment(&rbd_dev->header, - rbd_dev->obj, - cur_ofs, (u64)-1, - seg_name, NULL); - dout("seg_name=%s\n", seg_name); - - ret = rbd_req_sync_rollback_obj(rbd_dev, snapid, seg_name); - if (ret < 0) - pr_warning("could not roll back obj %s err=%d\n", - seg_name, ret); - } - - ret = __rbd_update_snaps(rbd_dev); - if (ret < 0) - goto done_unlock; - - ret = count; - -done_unlock: - mutex_unlock(&ctl_mutex); -done: - kfree(seg_name); - kfree(snap_name); - - return ret; -} - static struct bus_attribute rbd_bus_attrs[] = { __ATTR(add, S_IWUSR, NULL, rbd_add), __ATTR(remove, S_IWUSR, NULL, rbd_remove), diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index ae3e167e17ad..89ddab127e33 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -16,6 +16,8 @@ * handle GCR disks */ +#undef DEBUG + #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -36,13 +38,11 @@ #include <asm/machdep.h> #include <asm/pmac_feature.h> -static DEFINE_MUTEX(swim3_mutex); -static struct request_queue *swim3_queue; -static struct gendisk *disks[2]; -static struct request *fd_req; - #define MAX_FLOPPIES 2 +static DEFINE_MUTEX(swim3_mutex); +static struct gendisk *disks[MAX_FLOPPIES]; + enum swim_state { idle, locating, @@ -177,7 +177,6 @@ struct swim3 { struct floppy_state { enum swim_state state; - spinlock_t lock; struct swim3 __iomem *swim3; /* hardware registers */ struct dbdma_regs __iomem *dma; /* DMA controller registers */ int swim3_intr; /* interrupt number for SWIM3 */ @@ -204,8 +203,20 @@ struct floppy_state { int wanted; struct macio_dev *mdev; char dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)]; + int index; + struct request *cur_req; }; +#define swim3_err(fmt, arg...) dev_err(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) +#define swim3_warn(fmt, arg...) dev_warn(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) +#define swim3_info(fmt, arg...) dev_info(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) + +#ifdef DEBUG +#define swim3_dbg(fmt, arg...) dev_dbg(&fs->mdev->ofdev.dev, "[fd%d] " fmt, fs->index, arg) +#else +#define swim3_dbg(fmt, arg...) do { } while(0) +#endif + static struct floppy_state floppy_states[MAX_FLOPPIES]; static int floppy_count = 0; static DEFINE_SPINLOCK(swim3_lock); @@ -224,17 +235,8 @@ static unsigned short write_postamble[] = { 0, 0, 0, 0, 0, 0 }; -static void swim3_select(struct floppy_state *fs, int sel); -static void swim3_action(struct floppy_state *fs, int action); -static int swim3_readbit(struct floppy_state *fs, int bit); -static void do_fd_request(struct request_queue * q); -static void start_request(struct floppy_state *fs); -static void set_timeout(struct floppy_state *fs, int nticks, - void (*proc)(unsigned long)); -static void scan_track(struct floppy_state *fs); static void seek_track(struct floppy_state *fs, int n); static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count); -static void setup_transfer(struct floppy_state *fs); static void act(struct floppy_state *fs); static void scan_timeout(unsigned long data); static void seek_timeout(unsigned long data); @@ -254,18 +256,21 @@ static unsigned int floppy_check_events(struct gendisk *disk, unsigned int clearing); static int floppy_revalidate(struct gendisk *disk); -static bool swim3_end_request(int err, unsigned int nr_bytes) +static bool swim3_end_request(struct floppy_state *fs, int err, unsigned int nr_bytes) { - if (__blk_end_request(fd_req, err, nr_bytes)) - return true; + struct request *req = fs->cur_req; + int rc; - fd_req = NULL; - return false; -} + swim3_dbg(" end request, err=%d nr_bytes=%d, cur_req=%p\n", + err, nr_bytes, req); -static bool swim3_end_request_cur(int err) -{ - return swim3_end_request(err, blk_rq_cur_bytes(fd_req)); + if (err) + nr_bytes = blk_rq_cur_bytes(req); + rc = __blk_end_request(req, err, nr_bytes); + if (rc) + return true; + fs->cur_req = NULL; + return false; } static void swim3_select(struct floppy_state *fs, int sel) @@ -303,50 +308,53 @@ static int swim3_readbit(struct floppy_state *fs, int bit) return (stat & DATA) == 0; } -static void do_fd_request(struct request_queue * q) -{ - int i; - - for(i=0; i<floppy_count; i++) { - struct floppy_state *fs = &floppy_states[i]; - if (fs->mdev->media_bay && - check_media_bay(fs->mdev->media_bay) != MB_FD) - continue; - start_request(fs); - } -} - static void start_request(struct floppy_state *fs) { struct request *req; unsigned long x; + swim3_dbg("start request, initial state=%d\n", fs->state); + if (fs->state == idle && fs->wanted) { fs->state = available; wake_up(&fs->wait); return; } while (fs->state == idle) { - if (!fd_req) { - fd_req = blk_fetch_request(swim3_queue); - if (!fd_req) + swim3_dbg("start request, idle loop, cur_req=%p\n", fs->cur_req); + if (!fs->cur_req) { + fs->cur_req = blk_fetch_request(disks[fs->index]->queue); + swim3_dbg(" fetched request %p\n", fs->cur_req); + if (!fs->cur_req) break; } - req = fd_req; -#if 0 - printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", - req->rq_disk->disk_name, req->cmd, - (long)blk_rq_pos(req), blk_rq_sectors(req), req->buffer); - printk(" errors=%d current_nr_sectors=%u\n", - req->errors, blk_rq_cur_sectors(req)); + req = fs->cur_req; + + if (fs->mdev->media_bay && + check_media_bay(fs->mdev->media_bay) != MB_FD) { + swim3_dbg("%s", " media bay absent, dropping req\n"); + swim3_end_request(fs, -ENODEV, 0); + continue; + } + +#if 0 /* This is really too verbose */ + swim3_dbg("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", + req->rq_disk->disk_name, req->cmd, + (long)blk_rq_pos(req), blk_rq_sectors(req), + req->buffer); + swim3_dbg(" errors=%d current_nr_sectors=%u\n", + req->errors, blk_rq_cur_sectors(req)); #endif if (blk_rq_pos(req) >= fs->total_secs) { - swim3_end_request_cur(-EIO); + swim3_dbg(" pos out of bounds (%ld, max is %ld)\n", + (long)blk_rq_pos(req), (long)fs->total_secs); + swim3_end_request(fs, -EIO, 0); continue; } if (fs->ejected) { - swim3_end_request_cur(-EIO); + swim3_dbg("%s", " disk ejected\n"); + swim3_end_request(fs, -EIO, 0); continue; } @@ -354,7 +362,8 @@ static void start_request(struct floppy_state *fs) if (fs->write_prot < 0) fs->write_prot = swim3_readbit(fs, WRITE_PROT); if (fs->write_prot) { - swim3_end_request_cur(-EIO); + swim3_dbg("%s", " try to write, disk write protected\n"); + swim3_end_request(fs, -EIO, 0); continue; } } @@ -369,7 +378,6 @@ static void start_request(struct floppy_state *fs) x = ((long)blk_rq_pos(req)) % fs->secpercyl; fs->head = x / fs->secpertrack; fs->req_sector = x % fs->secpertrack + 1; - fd_req = req; fs->state = do_transfer; fs->retries = 0; @@ -377,12 +385,14 @@ static void start_request(struct floppy_state *fs) } } +static void do_fd_request(struct request_queue * q) +{ + start_request(q->queuedata); +} + static void set_timeout(struct floppy_state *fs, int nticks, void (*proc)(unsigned long)) { - unsigned long flags; - - spin_lock_irqsave(&fs->lock, flags); if (fs->timeout_pending) del_timer(&fs->timeout); fs->timeout.expires = jiffies + nticks; @@ -390,7 +400,6 @@ static void set_timeout(struct floppy_state *fs, int nticks, fs->timeout.data = (unsigned long) fs; add_timer(&fs->timeout); fs->timeout_pending = 1; - spin_unlock_irqrestore(&fs->lock, flags); } static inline void scan_track(struct floppy_state *fs) @@ -442,40 +451,45 @@ static inline void setup_transfer(struct floppy_state *fs) struct swim3 __iomem *sw = fs->swim3; struct dbdma_cmd *cp = fs->dma_cmd; struct dbdma_regs __iomem *dr = fs->dma; + struct request *req = fs->cur_req; - if (blk_rq_cur_sectors(fd_req) <= 0) { - printk(KERN_ERR "swim3: transfer 0 sectors?\n"); + if (blk_rq_cur_sectors(req) <= 0) { + swim3_warn("%s", "Transfer 0 sectors ?\n"); return; } - if (rq_data_dir(fd_req) == WRITE) + if (rq_data_dir(req) == WRITE) n = 1; else { n = fs->secpertrack - fs->req_sector + 1; - if (n > blk_rq_cur_sectors(fd_req)) - n = blk_rq_cur_sectors(fd_req); + if (n > blk_rq_cur_sectors(req)) + n = blk_rq_cur_sectors(req); } + + swim3_dbg(" setup xfer at sect %d (of %d) head %d for %d\n", + fs->req_sector, fs->secpertrack, fs->head, n); + fs->scount = n; swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); out_8(&sw->sector, fs->req_sector); out_8(&sw->nsect, n); out_8(&sw->gap3, 0); out_le32(&dr->cmdptr, virt_to_bus(cp)); - if (rq_data_dir(fd_req) == WRITE) { + if (rq_data_dir(req) == WRITE) { /* Set up 3 dma commands: write preamble, data, postamble */ init_dma(cp, OUTPUT_MORE, write_preamble, sizeof(write_preamble)); ++cp; - init_dma(cp, OUTPUT_MORE, fd_req->buffer, 512); + init_dma(cp, OUTPUT_MORE, req->buffer, 512); ++cp; init_dma(cp, OUTPUT_LAST, write_postamble, sizeof(write_postamble)); } else { - init_dma(cp, INPUT_LAST, fd_req->buffer, n * 512); + init_dma(cp, INPUT_LAST, req->buffer, n * 512); } ++cp; out_le16(&cp->command, DBDMA_STOP); out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); in_8(&sw->error); out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); - if (rq_data_dir(fd_req) == WRITE) + if (rq_data_dir(req) == WRITE) out_8(&sw->control_bis, WRITE_SECTORS); in_8(&sw->intr); out_le32(&dr->control, (RUN << 16) | RUN); @@ -488,12 +502,16 @@ static inline void setup_transfer(struct floppy_state *fs) static void act(struct floppy_state *fs) { for (;;) { + swim3_dbg(" act loop, state=%d, req_cyl=%d, cur_cyl=%d\n", + fs->state, fs->req_cyl, fs->cur_cyl); + switch (fs->state) { case idle: return; /* XXX shouldn't get here */ case locating: if (swim3_readbit(fs, TRACK_ZERO)) { + swim3_dbg("%s", " locate track 0\n"); fs->cur_cyl = 0; if (fs->req_cyl == 0) fs->state = do_transfer; @@ -511,7 +529,7 @@ static void act(struct floppy_state *fs) break; } if (fs->req_cyl == fs->cur_cyl) { - printk("whoops, seeking 0\n"); + swim3_warn("%s", "Whoops, seeking 0\n"); fs->state = do_transfer; break; } @@ -527,7 +545,9 @@ static void act(struct floppy_state *fs) case do_transfer: if (fs->cur_cyl != fs->req_cyl) { if (fs->retries > 5) { - swim3_end_request_cur(-EIO); + swim3_err("Wrong cylinder in transfer, want: %d got %d\n", + fs->req_cyl, fs->cur_cyl); + swim3_end_request(fs, -EIO, 0); fs->state = idle; return; } @@ -542,7 +562,7 @@ static void act(struct floppy_state *fs) return; default: - printk(KERN_ERR"swim3: unknown state %d\n", fs->state); + swim3_err("Unknown state %d\n", fs->state); return; } } @@ -552,59 +572,75 @@ static void scan_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; + unsigned long flags; + + swim3_dbg("* scan timeout, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); fs->cur_cyl = -1; if (fs->retries > 5) { - swim3_end_request_cur(-EIO); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); } else { fs->state = jogging; act(fs); } + spin_unlock_irqrestore(&swim3_lock, flags); } static void seek_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; + unsigned long flags; + + swim3_dbg("* seek timeout, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; out_8(&sw->control_bic, DO_SEEK); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); - printk(KERN_ERR "swim3: seek timeout\n"); - swim3_end_request_cur(-EIO); + swim3_err("%s", "Seek timeout\n"); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); + spin_unlock_irqrestore(&swim3_lock, flags); } static void settle_timeout(unsigned long data) { struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; + unsigned long flags; + + swim3_dbg("* settle timeout, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; if (swim3_readbit(fs, SEEK_COMPLETE)) { out_8(&sw->select, RELAX); fs->state = locating; act(fs); - return; + goto unlock; } out_8(&sw->select, RELAX); if (fs->settle_time < 2*HZ) { ++fs->settle_time; set_timeout(fs, 1, settle_timeout); - return; + goto unlock; } - printk(KERN_ERR "swim3: seek settle timeout\n"); - swim3_end_request_cur(-EIO); + swim3_err("%s", "Seek settle timeout\n"); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); + unlock: + spin_unlock_irqrestore(&swim3_lock, flags); } static void xfer_timeout(unsigned long data) @@ -612,8 +648,12 @@ static void xfer_timeout(unsigned long data) struct floppy_state *fs = (struct floppy_state *) data; struct swim3 __iomem *sw = fs->swim3; struct dbdma_regs __iomem *dr = fs->dma; + unsigned long flags; int n; + swim3_dbg("* xfer timeout, state=%d\n", fs->state); + + spin_lock_irqsave(&swim3_lock, flags); fs->timeout_pending = 0; out_le32(&dr->control, RUN << 16); /* We must wait a bit for dbdma to stop */ @@ -622,12 +662,13 @@ static void xfer_timeout(unsigned long data) out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); - printk(KERN_ERR "swim3: timeout %sing sector %ld\n", - (rq_data_dir(fd_req)==WRITE? "writ": "read"), - (long)blk_rq_pos(fd_req)); - swim3_end_request_cur(-EIO); + swim3_err("Timeout %sing sector %ld\n", + (rq_data_dir(fs->cur_req)==WRITE? "writ": "read"), + (long)blk_rq_pos(fs->cur_req)); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); + spin_unlock_irqrestore(&swim3_lock, flags); } static irqreturn_t swim3_interrupt(int irq, void *dev_id) @@ -638,12 +679,17 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) int stat, resid; struct dbdma_regs __iomem *dr; struct dbdma_cmd *cp; + unsigned long flags; + struct request *req = fs->cur_req; + + swim3_dbg("* interrupt, state=%d\n", fs->state); + spin_lock_irqsave(&swim3_lock, flags); intr = in_8(&sw->intr); err = (intr & ERROR_INTR)? in_8(&sw->error): 0; if ((intr & ERROR_INTR) && fs->state != do_transfer) - printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n", - fs->state, rq_data_dir(fd_req), intr, err); + swim3_err("Non-transfer error interrupt: state=%d, dir=%x, intr=%x, err=%x\n", + fs->state, rq_data_dir(req), intr, err); switch (fs->state) { case locating: if (intr & SEEN_SECTOR) { @@ -653,10 +699,10 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) del_timer(&fs->timeout); fs->timeout_pending = 0; if (sw->ctrack == 0xff) { - printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); + swim3_err("%s", "Seen sector but cyl=ff?\n"); fs->cur_cyl = -1; if (fs->retries > 5) { - swim3_end_request_cur(-EIO); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); } else { @@ -668,8 +714,8 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) fs->cur_cyl = sw->ctrack; fs->cur_sector = sw->csect; if (fs->expect_cyl != -1 && fs->expect_cyl != fs->cur_cyl) - printk(KERN_ERR "swim3: expected cyl %d, got %d\n", - fs->expect_cyl, fs->cur_cyl); + swim3_err("Expected cyl %d, got %d\n", + fs->expect_cyl, fs->cur_cyl); fs->state = do_transfer; act(fs); } @@ -704,7 +750,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) fs->timeout_pending = 0; dr = fs->dma; cp = fs->dma_cmd; - if (rq_data_dir(fd_req) == WRITE) + if (rq_data_dir(req) == WRITE) ++cp; /* * Check that the main data transfer has finished. @@ -729,31 +775,32 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) if (intr & ERROR_INTR) { n = fs->scount - 1 - resid / 512; if (n > 0) { - blk_update_request(fd_req, 0, n << 9); + blk_update_request(req, 0, n << 9); fs->req_sector += n; } if (fs->retries < 5) { ++fs->retries; act(fs); } else { - printk("swim3: error %sing block %ld (err=%x)\n", - rq_data_dir(fd_req) == WRITE? "writ": "read", - (long)blk_rq_pos(fd_req), err); - swim3_end_request_cur(-EIO); + swim3_err("Error %sing block %ld (err=%x)\n", + rq_data_dir(req) == WRITE? "writ": "read", + (long)blk_rq_pos(req), err); + swim3_end_request(fs, -EIO, 0); fs->state = idle; } } else { if ((stat & ACTIVE) == 0 || resid != 0) { /* musta been an error */ - printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid); - printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n", - fs->state, rq_data_dir(fd_req), intr, err); - swim3_end_request_cur(-EIO); + swim3_err("fd dma error: stat=%x resid=%d\n", stat, resid); + swim3_err(" state=%d, dir=%x, intr=%x, err=%x\n", + fs->state, rq_data_dir(req), intr, err); + swim3_end_request(fs, -EIO, 0); fs->state = idle; start_request(fs); break; } - if (swim3_end_request(0, fs->scount << 9)) { + fs->retries = 0; + if (swim3_end_request(fs, 0, fs->scount << 9)) { fs->req_sector += fs->scount; if (fs->req_sector > fs->secpertrack) { fs->req_sector -= fs->secpertrack; @@ -770,8 +817,9 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) start_request(fs); break; default: - printk(KERN_ERR "swim3: don't know what to do in state %d\n", fs->state); + swim3_err("Don't know what to do in state %d\n", fs->state); } + spin_unlock_irqrestore(&swim3_lock, flags); return IRQ_HANDLED; } @@ -781,26 +829,31 @@ static void fd_dma_interrupt(int irq, void *dev_id) } */ +/* Called under the mutex to grab exclusive access to a drive */ static int grab_drive(struct floppy_state *fs, enum swim_state state, int interruptible) { unsigned long flags; - spin_lock_irqsave(&fs->lock, flags); - if (fs->state != idle) { + swim3_dbg("%s", "-> grab drive\n"); + + spin_lock_irqsave(&swim3_lock, flags); + if (fs->state != idle && fs->state != available) { ++fs->wanted; while (fs->state != available) { + spin_unlock_irqrestore(&swim3_lock, flags); if (interruptible && signal_pending(current)) { --fs->wanted; - spin_unlock_irqrestore(&fs->lock, flags); return -EINTR; } interruptible_sleep_on(&fs->wait); + spin_lock_irqsave(&swim3_lock, flags); } --fs->wanted; } fs->state = state; - spin_unlock_irqrestore(&fs->lock, flags); + spin_unlock_irqrestore(&swim3_lock, flags); + return 0; } @@ -808,10 +861,12 @@ static void release_drive(struct floppy_state *fs) { unsigned long flags; - spin_lock_irqsave(&fs->lock, flags); + swim3_dbg("%s", "-> release drive\n"); + + spin_lock_irqsave(&swim3_lock, flags); fs->state = idle; start_request(fs); - spin_unlock_irqrestore(&fs->lock, flags); + spin_unlock_irqrestore(&swim3_lock, flags); } static int fd_eject(struct floppy_state *fs) @@ -966,6 +1021,7 @@ static int floppy_release(struct gendisk *disk, fmode_t mode) { struct floppy_state *fs = disk->private_data; struct swim3 __iomem *sw = fs->swim3; + mutex_lock(&swim3_mutex); if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); @@ -1031,30 +1087,48 @@ static const struct block_device_operations floppy_fops = { .revalidate_disk= floppy_revalidate, }; +static void swim3_mb_event(struct macio_dev* mdev, int mb_state) +{ + struct floppy_state *fs = macio_get_drvdata(mdev); + struct swim3 __iomem *sw = fs->swim3; + + if (!fs) + return; + if (mb_state != MB_FD) + return; + + /* Clear state */ + out_8(&sw->intr_enable, 0); + in_8(&sw->intr); + in_8(&sw->error); +} + static int swim3_add_device(struct macio_dev *mdev, int index) { struct device_node *swim = mdev->ofdev.dev.of_node; struct floppy_state *fs = &floppy_states[index]; int rc = -EBUSY; + /* Do this first for message macros */ + memset(fs, 0, sizeof(*fs)); + fs->mdev = mdev; + fs->index = index; + /* Check & Request resources */ if (macio_resource_count(mdev) < 2) { - printk(KERN_WARNING "ifd%d: no address for %s\n", - index, swim->full_name); + swim3_err("%s", "No address in device-tree\n"); return -ENXIO; } - if (macio_irq_count(mdev) < 2) { - printk(KERN_WARNING "fd%d: no intrs for device %s\n", - index, swim->full_name); + if (macio_irq_count(mdev) < 1) { + swim3_err("%s", "No interrupt in device-tree\n"); + return -ENXIO; } if (macio_request_resource(mdev, 0, "swim3 (mmio)")) { - printk(KERN_ERR "fd%d: can't request mmio resource for %s\n", - index, swim->full_name); + swim3_err("%s", "Can't request mmio resource\n"); return -EBUSY; } if (macio_request_resource(mdev, 1, "swim3 (dma)")) { - printk(KERN_ERR "fd%d: can't request dma resource for %s\n", - index, swim->full_name); + swim3_err("%s", "Can't request dma resource\n"); macio_release_resource(mdev, 0); return -EBUSY; } @@ -1063,22 +1137,18 @@ static int swim3_add_device(struct macio_dev *mdev, int index) if (mdev->media_bay == NULL) pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 1); - memset(fs, 0, sizeof(*fs)); - spin_lock_init(&fs->lock); fs->state = idle; fs->swim3 = (struct swim3 __iomem *) ioremap(macio_resource_start(mdev, 0), 0x200); if (fs->swim3 == NULL) { - printk("fd%d: couldn't map registers for %s\n", - index, swim->full_name); + swim3_err("%s", "Couldn't map mmio registers\n"); rc = -ENOMEM; goto out_release; } fs->dma = (struct dbdma_regs __iomem *) ioremap(macio_resource_start(mdev, 1), 0x200); if (fs->dma == NULL) { - printk("fd%d: couldn't map DMA for %s\n", - index, swim->full_name); + swim3_err("%s", "Couldn't map dma registers\n"); iounmap(fs->swim3); rc = -ENOMEM; goto out_release; @@ -1090,31 +1160,25 @@ static int swim3_add_device(struct macio_dev *mdev, int index) fs->secpercyl = 36; fs->secpertrack = 18; fs->total_secs = 2880; - fs->mdev = mdev; init_waitqueue_head(&fs->wait); fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space); memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd)); st_le16(&fs->dma_cmd[1].command, DBDMA_STOP); + if (mdev->media_bay == NULL || check_media_bay(mdev->media_bay) == MB_FD) + swim3_mb_event(mdev, MB_FD); + if (request_irq(fs->swim3_intr, swim3_interrupt, 0, "SWIM3", fs)) { - printk(KERN_ERR "fd%d: couldn't request irq %d for %s\n", - index, fs->swim3_intr, swim->full_name); + swim3_err("%s", "Couldn't request interrupt\n"); pmac_call_feature(PMAC_FTR_SWIM3_ENABLE, swim, 0, 0); goto out_unmap; return -EBUSY; } -/* - if (request_irq(fs->dma_intr, fd_dma_interrupt, 0, "SWIM3-dma", fs)) { - printk(KERN_ERR "Couldn't get irq %d for SWIM3 DMA", - fs->dma_intr); - return -EBUSY; - } -*/ init_timer(&fs->timeout); - printk(KERN_INFO "fd%d: SWIM3 floppy controller %s\n", floppy_count, + swim3_info("SWIM3 floppy controller %s\n", mdev->media_bay ? "in media bay" : ""); return 0; @@ -1132,41 +1196,42 @@ static int swim3_add_device(struct macio_dev *mdev, int index) static int __devinit swim3_attach(struct macio_dev *mdev, const struct of_device_id *match) { - int i, rc; struct gendisk *disk; + int index, rc; + + index = floppy_count++; + if (index >= MAX_FLOPPIES) + return -ENXIO; /* Add the drive */ - rc = swim3_add_device(mdev, floppy_count); + rc = swim3_add_device(mdev, index); if (rc) return rc; + /* Now register that disk. Same comment about failure handling */ + disk = disks[index] = alloc_disk(1); + if (disk == NULL) + return -ENOMEM; + disk->queue = blk_init_queue(do_fd_request, &swim3_lock); + if (disk->queue == NULL) { + put_disk(disk); + return -ENOMEM; + } + disk->queue->queuedata = &floppy_states[index]; - /* Now create the queue if not there yet */ - if (swim3_queue == NULL) { + if (index == 0) { /* If we failed, there isn't much we can do as the driver is still * too dumb to remove the device, just bail out */ if (register_blkdev(FLOPPY_MAJOR, "fd")) return 0; - swim3_queue = blk_init_queue(do_fd_request, &swim3_lock); - if (swim3_queue == NULL) { - unregister_blkdev(FLOPPY_MAJOR, "fd"); - return 0; - } } - /* Now register that disk. Same comment about failure handling */ - i = floppy_count++; - disk = disks[i] = alloc_disk(1); - if (disk == NULL) - return 0; - disk->major = FLOPPY_MAJOR; - disk->first_minor = i; + disk->first_minor = index; disk->fops = &floppy_fops; - disk->private_data = &floppy_states[i]; - disk->queue = swim3_queue; + disk->private_data = &floppy_states[index]; disk->flags |= GENHD_FL_REMOVABLE; - sprintf(disk->disk_name, "fd%d", i); + sprintf(disk->disk_name, "fd%d", index); set_capacity(disk, 2880); add_disk(disk); @@ -1194,6 +1259,9 @@ static struct macio_driver swim3_driver = .of_match_table = swim3_match, }, .probe = swim3_attach, +#ifdef CONFIG_PMAC_MEDIABAY + .mediabay_event = swim3_mb_event, +#endif #if 0 .suspend = swim3_suspend, .resume = swim3_resume, diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 11b41fd40c27..5ccf142ef0b8 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -188,7 +188,7 @@ config BT_MRVL The core driver to support Marvell Bluetooth devices. This driver is required if you want to support - Marvell Bluetooth devices, such as 8688/8787. + Marvell Bluetooth devices, such as 8688/8787/8797. Say Y here to compile Marvell Bluetooth driver into the kernel or say M to compile it as module. @@ -201,8 +201,8 @@ config BT_MRVL_SDIO The driver for Marvell Bluetooth chipsets with SDIO interface. This driver is required if you want to use Marvell Bluetooth - devices with SDIO interface. Currently SD8688/SD8787 chipsets are - supported. + devices with SDIO interface. Currently SD8688/SD8787/SD8797 + chipsets are supported. Say Y here to compile support for Marvell BT-over-SDIO driver into the kernel or say M to compile it as module. diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 9ef48167e2cf..27b74b0d547b 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { .io_port_1 = 0x01, .io_port_2 = 0x02, }; -static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { +static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { .cfg = 0x00, .host_int_mask = 0x02, .host_intstatus = 0x03, @@ -92,7 +92,14 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { .helper = NULL, .firmware = "mrvl/sd8787_uapsta.bin", - .reg = &btmrvl_reg_8787, + .reg = &btmrvl_reg_87xx, + .sd_blksz_fw_dl = 256, +}; + +static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { + .helper = NULL, + .firmware = "mrvl/sd8797_uapsta.bin", + .reg = &btmrvl_reg_87xx, .sd_blksz_fw_dl = 256, }; @@ -103,6 +110,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { /* Marvell SD8787 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, + /* Marvell SD8797 Bluetooth device */ + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), + .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, { } /* Terminating entry */ }; @@ -1076,3 +1086,4 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); +MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index fe4ebc375b3d..eabc437ce500 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -777,9 +777,8 @@ skip_waking: usb_mark_last_busy(data->udev); } - usb_free_urb(urb); - done: + usb_free_urb(urb); return err; } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 571041477ab2..a626e15799a5 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -19,6 +19,7 @@ #include <linux/amba/pl330.h> #include <linux/pm_runtime.h> #include <linux/scatterlist.h> +#include <linux/of.h> #define NR_DEFAULT_DESC 16 @@ -116,6 +117,9 @@ struct dma_pl330_desc { struct dma_pl330_chan *pchan; }; +/* forward declaration */ +static struct amba_driver pl330_driver; + static inline struct dma_pl330_chan * to_pchan(struct dma_chan *ch) { @@ -267,6 +271,32 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) tasklet_schedule(&pch->task); } +bool pl330_filter(struct dma_chan *chan, void *param) +{ + u8 *peri_id; + + if (chan->device->dev->driver != &pl330_driver.drv) + return false; + +#ifdef CONFIG_OF + if (chan->device->dev->of_node) { + const __be32 *prop_value; + phandle phandle; + struct device_node *node; + + prop_value = ((struct property *)param)->value; + phandle = be32_to_cpup(prop_value++); + node = of_find_node_by_phandle(phandle); + return ((chan->private == node) && + (chan->chan_id == be32_to_cpup(prop_value))); + } +#endif + + peri_id = chan->private; + return *peri_id == (unsigned)param; +} +EXPORT_SYMBOL(pl330_filter); + static int pl330_alloc_chan_resources(struct dma_chan *chan) { struct dma_pl330_chan *pch = to_pchan(chan); @@ -497,7 +527,7 @@ pluck_desc(struct dma_pl330_dmac *pdmac) static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) { struct dma_pl330_dmac *pdmac = pch->dmac; - struct dma_pl330_peri *peri = pch->chan.private; + u8 *peri_id = pch->chan.private; struct dma_pl330_desc *desc; /* Pluck one desc from the pool of DMAC */ @@ -522,13 +552,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) desc->txd.cookie = 0; async_tx_ack(&desc->txd); - if (peri) { - desc->req.rqtype = peri->rqtype; - desc->req.peri = pch->chan.chan_id; - } else { - desc->req.rqtype = MEMTOMEM; - desc->req.peri = 0; - } + desc->req.peri = peri_id ? pch->chan.chan_id : 0; dma_async_tx_descriptor_init(&desc->txd, &pch->chan); @@ -615,12 +639,14 @@ static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( case DMA_TO_DEVICE: desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; + desc->req.rqtype = MEMTODEV; src = dma_addr; dst = pch->fifo_addr; break; case DMA_FROM_DEVICE: desc->rqcfg.src_inc = 0; desc->rqcfg.dst_inc = 1; + desc->req.rqtype = DEVTOMEM; src = pch->fifo_addr; dst = dma_addr; break; @@ -646,16 +672,12 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, { struct dma_pl330_desc *desc; struct dma_pl330_chan *pch = to_pchan(chan); - struct dma_pl330_peri *peri = chan->private; struct pl330_info *pi; int burst; if (unlikely(!pch || !len)) return NULL; - if (peri && peri->rqtype != MEMTOMEM) - return NULL; - pi = &pch->dmac->pif; desc = __pl330_prep_dma_memcpy(pch, dst, src, len); @@ -664,6 +686,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 1; + desc->req.rqtype = MEMTOMEM; /* Select max possible burst size */ burst = pi->pcfg.data_bus_width / 8; @@ -692,25 +715,14 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, { struct dma_pl330_desc *first, *desc = NULL; struct dma_pl330_chan *pch = to_pchan(chan); - struct dma_pl330_peri *peri = chan->private; struct scatterlist *sg; unsigned long flags; int i; dma_addr_t addr; - if (unlikely(!pch || !sgl || !sg_len || !peri)) + if (unlikely(!pch || !sgl || !sg_len)) return NULL; - /* Make sure the direction is consistent */ - if ((direction == DMA_TO_DEVICE && - peri->rqtype != MEMTODEV) || - (direction == DMA_FROM_DEVICE && - peri->rqtype != DEVTOMEM)) { - dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n", - __func__, __LINE__); - return NULL; - } - addr = pch->fifo_addr; first = NULL; @@ -750,11 +762,13 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (direction == DMA_TO_DEVICE) { desc->rqcfg.src_inc = 1; desc->rqcfg.dst_inc = 0; + desc->req.rqtype = MEMTODEV; fill_px(&desc->px, addr, sg_dma_address(sg), sg_dma_len(sg)); } else { desc->rqcfg.src_inc = 0; desc->rqcfg.dst_inc = 1; + desc->req.rqtype = DEVTOMEM; fill_px(&desc->px, sg_dma_address(sg), addr, sg_dma_len(sg)); } @@ -856,32 +870,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) INIT_LIST_HEAD(&pd->channels); /* Initialize channel parameters */ - num_chan = max(pdat ? pdat->nr_valid_peri : 0, (u8)pi->pcfg.num_chan); + num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri, + (u8)pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); for (i = 0; i < num_chan; i++) { pch = &pdmac->peripherals[i]; - if (pdat) { - struct dma_pl330_peri *peri = &pdat->peri[i]; - - switch (peri->rqtype) { - case MEMTOMEM: - dma_cap_set(DMA_MEMCPY, pd->cap_mask); - break; - case MEMTODEV: - case DEVTOMEM: - dma_cap_set(DMA_SLAVE, pd->cap_mask); - dma_cap_set(DMA_CYCLIC, pd->cap_mask); - break; - default: - dev_err(&adev->dev, "DEVTODEV Not Supported\n"); - continue; - } - pch->chan.private = peri; - } else { - dma_cap_set(DMA_MEMCPY, pd->cap_mask); - pch->chan.private = NULL; - } + if (!adev->dev.of_node) + pch->chan.private = pdat ? &pdat->peri_id[i] : NULL; + else + pch->chan.private = adev->dev.of_node; INIT_LIST_HEAD(&pch->work_list); spin_lock_init(&pch->lock); @@ -894,6 +892,15 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) } pd->dev = &adev->dev; + if (pdat) { + pd->cap_mask = pdat->cap_mask; + } else { + dma_cap_set(DMA_MEMCPY, pd->cap_mask); + if (pi->pcfg.num_peri) { + dma_cap_set(DMA_SLAVE, pd->cap_mask); + dma_cap_set(DMA_CYCLIC, pd->cap_mask); + } + } pd->device_alloc_chan_resources = pl330_alloc_chan_resources; pd->device_free_chan_resources = pl330_free_chan_resources; diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index c811cb107904..2cce44a1d7d0 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -746,6 +746,37 @@ static void __exit ibft_exit(void) ibft_cleanup(); } +#ifdef CONFIG_ACPI +static const struct { + char *sign; +} ibft_signs[] = { + /* + * One spec says "IBFT", the other says "iBFT". We have to check + * for both. + */ + { ACPI_SIG_IBFT }, + { "iBFT" }, +}; + +static void __init acpi_find_ibft_region(void) +{ + int i; + struct acpi_table_header *table = NULL; + + if (acpi_disabled) + return; + + for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) { + acpi_get_table(ibft_signs[i].sign, 0, &table); + ibft_addr = (struct acpi_table_ibft *)table; + } +} +#else +static void __init acpi_find_ibft_region(void) +{ +} +#endif + /* * ibft_init() - creates sysfs tree entries for the iBFT data. */ @@ -753,9 +784,16 @@ static int __init ibft_init(void) { int rc = 0; + /* + As on UEFI systems the setup_arch()/find_ibft_region() + is called before ACPI tables are parsed and it only does + legacy finding. + */ + if (!ibft_addr) + acpi_find_ibft_region(); + if (ibft_addr) { - printk(KERN_INFO "iBFT detected at 0x%llx.\n", - (u64)isa_virt_to_bus(ibft_addr)); + pr_info("iBFT detected.\n"); rc = ibft_check_device(); if (rc) diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index bfe723266fd8..4da4eb9ae926 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -45,13 +45,6 @@ EXPORT_SYMBOL_GPL(ibft_addr); static const struct { char *sign; } ibft_signs[] = { -#ifdef CONFIG_ACPI - /* - * One spec says "IBFT", the other says "iBFT". We have to check - * for both. - */ - { ACPI_SIG_IBFT }, -#endif { "iBFT" }, { "BIFT" }, /* Broadcom iSCSI Offload */ }; @@ -62,14 +55,6 @@ static const struct { #define VGA_MEM 0xA0000 /* VGA buffer */ #define VGA_SIZE 0x20000 /* 128kB */ -#ifdef CONFIG_ACPI -static int __init acpi_find_ibft(struct acpi_table_header *header) -{ - ibft_addr = (struct acpi_table_ibft *)header; - return 0; -} -#endif /* CONFIG_ACPI */ - static int __init find_ibft_in_mem(void) { unsigned long pos; @@ -94,6 +79,7 @@ static int __init find_ibft_in_mem(void) * the table cannot be valid. */ if (pos + len <= (IBFT_END-1)) { ibft_addr = (struct acpi_table_ibft *)virt; + pr_info("iBFT found at 0x%lx.\n", pos); goto done; } } @@ -108,20 +94,12 @@ done: */ unsigned long __init find_ibft_region(unsigned long *sizep) { -#ifdef CONFIG_ACPI - int i; -#endif ibft_addr = NULL; -#ifdef CONFIG_ACPI - for (i = 0; i < ARRAY_SIZE(ibft_signs) && !ibft_addr; i++) - acpi_table_parse(ibft_signs[i].sign, acpi_find_ibft); -#endif /* CONFIG_ACPI */ - /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will * only use ACPI for this */ - if (!ibft_addr && !efi_enabled) + if (!efi_enabled) find_ibft_in_mem(); if (ibft_addr) { diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 8482a23887dc..aa0b94ff36d0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -141,6 +141,12 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device +config GPIO_PXA + bool "PXA GPIO support" + depends on ARCH_PXA || ARCH_MMP + help + Say yes here to support the PXA GPIO device + config GPIO_XILINX bool "Xilinx GPIO support" depends on PPC_OF || MICROBLAZE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 4e018d6a7639..8ef9e9abe970 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o obj-$(CONFIG_GPIO_PCH) += gpio-pch.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o -obj-$(CONFIG_PLAT_PXA) += gpio-pxa.o +obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c index 038f5eb8b13d..f8ce29ef9f88 100644 --- a/drivers/gpio/gpio-da9052.c +++ b/drivers/gpio/gpio-da9052.c @@ -22,7 +22,6 @@ #include <linux/mfd/da9052/da9052.h> #include <linux/mfd/da9052/reg.h> #include <linux/mfd/da9052/pdata.h> -#include <linux/mfd/da9052/gpio.h> #define DA9052_INPUT 1 #define DA9052_OUTPUT_OPENDRAIN 2 @@ -43,6 +42,9 @@ #define DA9052_GPIO_MASK_UPPER_NIBBLE 0xF0 #define DA9052_GPIO_MASK_LOWER_NIBBLE 0x0F #define DA9052_GPIO_NIBBLE_SHIFT 4 +#define DA9052_IRQ_GPI0 16 +#define DA9052_GPIO_ODD_SHIFT 7 +#define DA9052_GPIO_EVEN_SHIFT 3 struct da9052_gpio { struct da9052 *da9052; @@ -104,33 +106,26 @@ static int da9052_gpio_get(struct gpio_chip *gc, unsigned offset) static void da9052_gpio_set(struct gpio_chip *gc, unsigned offset, int value) { struct da9052_gpio *gpio = to_da9052_gpio(gc); - unsigned char register_value = 0; int ret; if (da9052_gpio_port_odd(offset)) { - if (value) { - register_value = DA9052_GPIO_ODD_PORT_MODE; ret = da9052_reg_update(gpio->da9052, (offset >> 1) + DA9052_GPIO_0_1_REG, DA9052_GPIO_ODD_PORT_MODE, - register_value); + value << DA9052_GPIO_ODD_SHIFT); if (ret != 0) dev_err(gpio->da9052->dev, "Failed to updated gpio odd reg,%d", ret); - } } else { - if (value) { - register_value = DA9052_GPIO_EVEN_PORT_MODE; ret = da9052_reg_update(gpio->da9052, (offset >> 1) + DA9052_GPIO_0_1_REG, DA9052_GPIO_EVEN_PORT_MODE, - register_value); + value << DA9052_GPIO_EVEN_SHIFT); if (ret != 0) dev_err(gpio->da9052->dev, "Failed to updated gpio even reg,%d", ret); - } } } @@ -201,9 +196,9 @@ static struct gpio_chip reference_gp __devinitdata = { .direction_input = da9052_gpio_direction_input, .direction_output = da9052_gpio_direction_output, .to_irq = da9052_gpio_to_irq, - .can_sleep = 1; - .ngpio = 16; - .base = -1; + .can_sleep = 1, + .ngpio = 16, + .base = -1, }; static int __devinit da9052_gpio_probe(struct platform_device *pdev) diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index ea8e73869250..461958fc2264 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -332,6 +332,34 @@ static void ioh_irq_mask(struct irq_data *d) &chip->reg->regs[chip->ch].imask); } +static void ioh_irq_disable(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct ioh_gpio *chip = gc->private; + unsigned long flags; + u32 ien; + + spin_lock_irqsave(&chip->spinlock, flags); + ien = ioread32(&chip->reg->regs[chip->ch].ien); + ien &= ~(1 << (d->irq - chip->irq_base)); + iowrite32(ien, &chip->reg->regs[chip->ch].ien); + spin_unlock_irqrestore(&chip->spinlock, flags); +} + +static void ioh_irq_enable(struct irq_data *d) +{ + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); + struct ioh_gpio *chip = gc->private; + unsigned long flags; + u32 ien; + + spin_lock_irqsave(&chip->spinlock, flags); + ien = ioread32(&chip->reg->regs[chip->ch].ien); + ien |= 1 << (d->irq - chip->irq_base); + iowrite32(ien, &chip->reg->regs[chip->ch].ien); + spin_unlock_irqrestore(&chip->spinlock, flags); +} + static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) { struct ioh_gpio *chip = dev_id; @@ -339,7 +367,7 @@ static irqreturn_t ioh_gpio_handler(int irq, void *dev_id) int i, j; int ret = IRQ_NONE; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++, chip++) { reg_val = ioread32(&chip->reg->regs[i].istatus); for (j = 0; j < num_ports[i]; j++) { if (reg_val & BIT(j)) { @@ -370,6 +398,8 @@ static __devinit void ioh_gpio_alloc_generic_chip(struct ioh_gpio *chip, ct->chip.irq_mask = ioh_irq_mask; ct->chip.irq_unmask = ioh_irq_unmask; ct->chip.irq_set_type = ioh_irq_type; + ct->chip.irq_disable = ioh_irq_disable; + ct->chip.irq_enable = ioh_irq_enable; irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST | IRQ_NOPROBE, 0); diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index ec3fcf0a7e12..5cd04b65c556 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -132,6 +132,15 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val return 0; } +static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + /* GPIO 28..31 are input only on MPC5121 */ + if (gpio >= 28) + return -EINVAL; + + return mpc8xxx_gpio_dir_out(gc, gpio, val); +} + static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset) { struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); @@ -340,11 +349,10 @@ static void __init mpc8xxx_add_controller(struct device_node *np) mm_gc->save_regs = mpc8xxx_gpio_save_regs; gc->ngpio = MPC8XXX_GPIO_PINS; gc->direction_input = mpc8xxx_gpio_dir_in; - gc->direction_output = mpc8xxx_gpio_dir_out; - if (of_device_is_compatible(np, "fsl,mpc8572-gpio")) - gc->get = mpc8572_gpio_get; - else - gc->get = mpc8xxx_gpio_get; + gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ? + mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out; + gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ? + mpc8572_gpio_get : mpc8xxx_gpio_get; gc->set = mpc8xxx_gpio_set; gc->to_irq = mpc8xxx_gpio_to_irq; diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 093c90bd3c1d..4102f63230fd 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -238,10 +238,6 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id) int ret, irq, i; static DECLARE_BITMAP(init_irq, NR_IRQS); - pdata = dev->dev.platform_data; - if (pdata == NULL) - return -ENODEV; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index ee137712f9db..b2d3ee1d183a 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -11,14 +11,46 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/clk.h> +#include <linux/err.h> #include <linux/gpio.h> +#include <linux/gpio-pxa.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/platform_device.h> #include <linux/syscore_ops.h> #include <linux/slab.h> -#include <mach/gpio-pxa.h> +/* + * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with + * one set of registers. The register offsets are organized below: + * + * GPLR GPDR GPSR GPCR GRER GFER GEDR + * BANK 0 - 0x0000 0x000C 0x0018 0x0024 0x0030 0x003C 0x0048 + * BANK 1 - 0x0004 0x0010 0x001C 0x0028 0x0034 0x0040 0x004C + * BANK 2 - 0x0008 0x0014 0x0020 0x002C 0x0038 0x0044 0x0050 + * + * BANK 3 - 0x0100 0x010C 0x0118 0x0124 0x0130 0x013C 0x0148 + * BANK 4 - 0x0104 0x0110 0x011C 0x0128 0x0134 0x0140 0x014C + * BANK 5 - 0x0108 0x0114 0x0120 0x012C 0x0138 0x0144 0x0150 + * + * NOTE: + * BANK 3 is only available on PXA27x and later processors. + * BANK 4 and 5 are only available on PXA935 + */ + +#define GPLR_OFFSET 0x00 +#define GPDR_OFFSET 0x0C +#define GPSR_OFFSET 0x18 +#define GPCR_OFFSET 0x24 +#define GRER_OFFSET 0x30 +#define GFER_OFFSET 0x3C +#define GEDR_OFFSET 0x48 +#define GAFR_OFFSET 0x54 +#define ED_MASK_OFFSET 0x9C /* GPIO edge detection for AP side */ + +#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) int pxa_last_gpio; @@ -39,8 +71,20 @@ struct pxa_gpio_chip { #endif }; +enum { + PXA25X_GPIO = 0, + PXA26X_GPIO, + PXA27X_GPIO, + PXA3XX_GPIO, + PXA93X_GPIO, + MMP_GPIO = 0x10, + MMP2_GPIO, +}; + static DEFINE_SPINLOCK(gpio_lock); static struct pxa_gpio_chip *pxa_gpio_chips; +static int gpio_type; +static void __iomem *gpio_reg_base; #define for_each_gpio_chip(i, c) \ for (i = 0, c = &pxa_gpio_chips[0]; i <= pxa_last_gpio; i += 32, c++) @@ -55,6 +99,122 @@ static inline struct pxa_gpio_chip *gpio_to_pxachip(unsigned gpio) return &pxa_gpio_chips[gpio_to_bank(gpio)]; } +static inline int gpio_is_pxa_type(int type) +{ + return (type & MMP_GPIO) == 0; +} + +static inline int gpio_is_mmp_type(int type) +{ + return (type & MMP_GPIO) != 0; +} + +/* GPIO86/87/88/89 on PXA26x have their direction bits in PXA_GPDR(2 inverted, + * as well as their Alternate Function value being '1' for GPIO in GAFRx. + */ +static inline int __gpio_is_inverted(int gpio) +{ + if ((gpio_type == PXA26X_GPIO) && (gpio > 85)) + return 1; + return 0; +} + +/* + * On PXA25x and PXA27x, GAFRx and GPDRx together decide the alternate + * function of a GPIO, and GPDRx cannot be altered once configured. It + * is attributed as "occupied" here (I know this terminology isn't + * accurate, you are welcome to propose a better one :-) + */ +static inline int __gpio_is_occupied(unsigned gpio) +{ + struct pxa_gpio_chip *pxachip; + void __iomem *base; + unsigned long gafr = 0, gpdr = 0; + int ret, af = 0, dir = 0; + + pxachip = gpio_to_pxachip(gpio); + base = gpio_chip_base(&pxachip->chip); + gpdr = readl_relaxed(base + GPDR_OFFSET); + + switch (gpio_type) { + case PXA25X_GPIO: + case PXA26X_GPIO: + case PXA27X_GPIO: + gafr = readl_relaxed(base + GAFR_OFFSET); + af = (gafr >> ((gpio & 0xf) * 2)) & 0x3; + dir = gpdr & GPIO_bit(gpio); + + if (__gpio_is_inverted(gpio)) + ret = (af != 1) || (dir == 0); + else + ret = (af != 0) || (dir != 0); + break; + default: + ret = gpdr & GPIO_bit(gpio); + break; + } + return ret; +} + +#ifdef CONFIG_ARCH_PXA +static inline int __pxa_gpio_to_irq(int gpio) +{ + if (gpio_is_pxa_type(gpio_type)) + return PXA_GPIO_TO_IRQ(gpio); + return -1; +} + +static inline int __pxa_irq_to_gpio(int irq) +{ + if (gpio_is_pxa_type(gpio_type)) + return irq - PXA_GPIO_TO_IRQ(0); + return -1; +} +#else +static inline int __pxa_gpio_to_irq(int gpio) { return -1; } +static inline int __pxa_irq_to_gpio(int irq) { return -1; } +#endif + +#ifdef CONFIG_ARCH_MMP +static inline int __mmp_gpio_to_irq(int gpio) +{ + if (gpio_is_mmp_type(gpio_type)) + return MMP_GPIO_TO_IRQ(gpio); + return -1; +} + +static inline int __mmp_irq_to_gpio(int irq) +{ + if (gpio_is_mmp_type(gpio_type)) + return irq - MMP_GPIO_TO_IRQ(0); + return -1; +} +#else +static inline int __mmp_gpio_to_irq(int gpio) { return -1; } +static inline int __mmp_irq_to_gpio(int irq) { return -1; } +#endif + +static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + int gpio, ret; + + gpio = chip->base + offset; + ret = __pxa_gpio_to_irq(gpio); + if (ret >= 0) + return ret; + return __mmp_gpio_to_irq(gpio); +} + +int pxa_irq_to_gpio(int irq) +{ + int ret; + + ret = __pxa_irq_to_gpio(irq); + if (ret >= 0) + return ret; + return __mmp_irq_to_gpio(irq); +} + static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { void __iomem *base = gpio_chip_base(chip); @@ -63,12 +223,12 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&gpio_lock, flags); - value = __raw_readl(base + GPDR_OFFSET); + value = readl_relaxed(base + GPDR_OFFSET); if (__gpio_is_inverted(chip->base + offset)) value |= mask; else value &= ~mask; - __raw_writel(value, base + GPDR_OFFSET); + writel_relaxed(value, base + GPDR_OFFSET); spin_unlock_irqrestore(&gpio_lock, flags); return 0; @@ -81,16 +241,16 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, uint32_t tmp, mask = 1 << offset; unsigned long flags; - __raw_writel(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); + writel_relaxed(mask, base + (value ? GPSR_OFFSET : GPCR_OFFSET)); spin_lock_irqsave(&gpio_lock, flags); - tmp = __raw_readl(base + GPDR_OFFSET); + tmp = readl_relaxed(base + GPDR_OFFSET); if (__gpio_is_inverted(chip->base + offset)) tmp &= ~mask; else tmp |= mask; - __raw_writel(tmp, base + GPDR_OFFSET); + writel_relaxed(tmp, base + GPDR_OFFSET); spin_unlock_irqrestore(&gpio_lock, flags); return 0; @@ -98,16 +258,16 @@ static int pxa_gpio_direction_output(struct gpio_chip *chip, static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset) { - return __raw_readl(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); + return readl_relaxed(gpio_chip_base(chip) + GPLR_OFFSET) & (1 << offset); } static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - __raw_writel(1 << offset, gpio_chip_base(chip) + + writel_relaxed(1 << offset, gpio_chip_base(chip) + (value ? GPSR_OFFSET : GPCR_OFFSET)); } -static int __init pxa_init_gpio_chip(int gpio_end) +static int __devinit pxa_init_gpio_chip(int gpio_end) { int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; struct pxa_gpio_chip *chips; @@ -122,7 +282,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) struct gpio_chip *c = &chips[i].chip; sprintf(chips[i].label, "gpio-%d", i); - chips[i].regbase = GPIO_BANK(i); + chips[i].regbase = gpio_reg_base + BANK_OFF(i); c->base = gpio; c->label = chips[i].label; @@ -131,6 +291,7 @@ static int __init pxa_init_gpio_chip(int gpio_end) c->direction_output = pxa_gpio_direction_output; c->get = pxa_gpio_get; c->set = pxa_gpio_set; + c->to_irq = pxa_gpio_to_irq; /* number of GPIOs on last bank may be less than 32 */ c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; @@ -147,18 +308,18 @@ static inline void update_edge_detect(struct pxa_gpio_chip *c) { uint32_t grer, gfer; - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask; - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask; + grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~c->irq_mask; + gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~c->irq_mask; grer |= c->irq_edge_rise & c->irq_mask; gfer |= c->irq_edge_fall & c->irq_mask; - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); + writel_relaxed(grer, c->regbase + GRER_OFFSET); + writel_relaxed(gfer, c->regbase + GFER_OFFSET); } static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) { struct pxa_gpio_chip *c; - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); unsigned long gpdr, mask = GPIO_bit(gpio); c = gpio_to_pxachip(gpio); @@ -176,12 +337,12 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type) type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; } - gpdr = __raw_readl(c->regbase + GPDR_OFFSET); + gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); if (__gpio_is_inverted(gpio)) - __raw_writel(gpdr | mask, c->regbase + GPDR_OFFSET); + writel_relaxed(gpdr | mask, c->regbase + GPDR_OFFSET); else - __raw_writel(gpdr & ~mask, c->regbase + GPDR_OFFSET); + writel_relaxed(gpdr & ~mask, c->regbase + GPDR_OFFSET); if (type & IRQ_TYPE_EDGE_RISING) c->irq_edge_rise |= mask; @@ -212,9 +373,9 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) for_each_gpio_chip(gpio, c) { gpio_base = c->chip.base; - gedr = __raw_readl(c->regbase + GEDR_OFFSET); + gedr = readl_relaxed(c->regbase + GEDR_OFFSET); gedr = gedr & c->irq_mask; - __raw_writel(gedr, c->regbase + GEDR_OFFSET); + writel_relaxed(gedr, c->regbase + GEDR_OFFSET); n = find_first_bit(&gedr, BITS_PER_LONG); while (n < BITS_PER_LONG) { @@ -229,29 +390,29 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) static void pxa_ack_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); - __raw_writel(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); + writel_relaxed(GPIO_bit(gpio), c->regbase + GEDR_OFFSET); } static void pxa_mask_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); uint32_t grer, gfer; c->irq_mask &= ~GPIO_bit(gpio); - grer = __raw_readl(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); - gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); - __raw_writel(grer, c->regbase + GRER_OFFSET); - __raw_writel(gfer, c->regbase + GFER_OFFSET); + grer = readl_relaxed(c->regbase + GRER_OFFSET) & ~GPIO_bit(gpio); + gfer = readl_relaxed(c->regbase + GFER_OFFSET) & ~GPIO_bit(gpio); + writel_relaxed(grer, c->regbase + GRER_OFFSET); + writel_relaxed(gfer, c->regbase + GFER_OFFSET); } static void pxa_unmask_muxed_gpio(struct irq_data *d) { - int gpio = irq_to_gpio(d->irq); + int gpio = pxa_irq_to_gpio(d->irq); struct pxa_gpio_chip *c = gpio_to_pxachip(gpio); c->irq_mask |= GPIO_bit(gpio); @@ -266,34 +427,143 @@ static struct irq_chip pxa_muxed_gpio_chip = { .irq_set_type = pxa_gpio_irq_type, }; -void __init pxa_init_gpio(int mux_irq, int start, int end, set_wake_t fn) +static int pxa_gpio_nums(void) { - struct pxa_gpio_chip *c; - int gpio, irq; + int count = 0; + +#ifdef CONFIG_ARCH_PXA + if (cpu_is_pxa25x()) { +#ifdef CONFIG_CPU_PXA26x + count = 89; + gpio_type = PXA26X_GPIO; +#elif defined(CONFIG_PXA25x) + count = 84; + gpio_type = PXA26X_GPIO; +#endif /* CONFIG_CPU_PXA26x */ + } else if (cpu_is_pxa27x()) { + count = 120; + gpio_type = PXA27X_GPIO; + } else if (cpu_is_pxa93x() || cpu_is_pxa95x()) { + count = 191; + gpio_type = PXA93X_GPIO; + } else if (cpu_is_pxa3xx()) { + count = 127; + gpio_type = PXA3XX_GPIO; + } +#endif /* CONFIG_ARCH_PXA */ + +#ifdef CONFIG_ARCH_MMP + if (cpu_is_pxa168() || cpu_is_pxa910()) { + count = 127; + gpio_type = MMP_GPIO; + } else if (cpu_is_mmp2()) { + count = 191; + gpio_type = MMP2_GPIO; + } +#endif /* CONFIG_ARCH_MMP */ + return count; +} - pxa_last_gpio = end; +static int __devinit pxa_gpio_probe(struct platform_device *pdev) +{ + struct pxa_gpio_chip *c; + struct resource *res; + struct clk *clk; + int gpio, irq, ret; + int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; + + pxa_last_gpio = pxa_gpio_nums(); + if (!pxa_last_gpio) + return -EINVAL; + + irq0 = platform_get_irq_byname(pdev, "gpio0"); + irq1 = platform_get_irq_byname(pdev, "gpio1"); + irq_mux = platform_get_irq_byname(pdev, "gpio_mux"); + if ((irq0 > 0 && irq1 <= 0) || (irq0 <= 0 && irq1 > 0) + || (irq_mux <= 0)) + return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + gpio_reg_base = ioremap(res->start, resource_size(res)); + if (!gpio_reg_base) + return -EINVAL; + + if (irq0 > 0) + gpio_offset = 2; + + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Error %ld to get gpio clock\n", + PTR_ERR(clk)); + iounmap(gpio_reg_base); + return PTR_ERR(clk); + } + ret = clk_prepare(clk); + if (ret) { + clk_put(clk); + iounmap(gpio_reg_base); + return ret; + } + ret = clk_enable(clk); + if (ret) { + clk_unprepare(clk); + clk_put(clk); + iounmap(gpio_reg_base); + return ret; + } /* Initialize GPIO chips */ - pxa_init_gpio_chip(end); + pxa_init_gpio_chip(pxa_last_gpio); /* clear all GPIO edge detects */ for_each_gpio_chip(gpio, c) { - __raw_writel(0, c->regbase + GFER_OFFSET); - __raw_writel(0, c->regbase + GRER_OFFSET); - __raw_writel(~0,c->regbase + GEDR_OFFSET); + writel_relaxed(0, c->regbase + GFER_OFFSET); + writel_relaxed(0, c->regbase + GRER_OFFSET); + writel_relaxed(~0,c->regbase + GEDR_OFFSET); + /* unmask GPIO edge detect for AP side */ + if (gpio_is_mmp_type(gpio_type)) + writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); } - for (irq = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) { +#ifdef CONFIG_ARCH_PXA + irq = gpio_to_irq(0); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); + + irq = gpio_to_irq(1); + irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, + handle_edge_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); +#endif + + for (irq = gpio_to_irq(gpio_offset); + irq <= gpio_to_irq(pxa_last_gpio); irq++) { irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - /* Install handler for GPIO>=2 edge detect interrupts */ - irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler); - pxa_muxed_gpio_chip.irq_set_wake = fn; + irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); + return 0; } +static struct platform_driver pxa_gpio_driver = { + .probe = pxa_gpio_probe, + .driver = { + .name = "pxa-gpio", + }, +}; + +static int __init pxa_gpio_init(void) +{ + return platform_driver_register(&pxa_gpio_driver); +} +postcore_initcall(pxa_gpio_init); + #ifdef CONFIG_PM static int pxa_gpio_suspend(void) { @@ -301,13 +571,13 @@ static int pxa_gpio_suspend(void) int gpio; for_each_gpio_chip(gpio, c) { - c->saved_gplr = __raw_readl(c->regbase + GPLR_OFFSET); - c->saved_gpdr = __raw_readl(c->regbase + GPDR_OFFSET); - c->saved_grer = __raw_readl(c->regbase + GRER_OFFSET); - c->saved_gfer = __raw_readl(c->regbase + GFER_OFFSET); + c->saved_gplr = readl_relaxed(c->regbase + GPLR_OFFSET); + c->saved_gpdr = readl_relaxed(c->regbase + GPDR_OFFSET); + c->saved_grer = readl_relaxed(c->regbase + GRER_OFFSET); + c->saved_gfer = readl_relaxed(c->regbase + GFER_OFFSET); /* Clear GPIO transition detect bits */ - __raw_writel(0xffffffff, c->regbase + GEDR_OFFSET); + writel_relaxed(0xffffffff, c->regbase + GEDR_OFFSET); } return 0; } @@ -319,12 +589,12 @@ static void pxa_gpio_resume(void) for_each_gpio_chip(gpio, c) { /* restore level with set/clear */ - __raw_writel( c->saved_gplr, c->regbase + GPSR_OFFSET); - __raw_writel(~c->saved_gplr, c->regbase + GPCR_OFFSET); + writel_relaxed( c->saved_gplr, c->regbase + GPSR_OFFSET); + writel_relaxed(~c->saved_gplr, c->regbase + GPCR_OFFSET); - __raw_writel(c->saved_grer, c->regbase + GRER_OFFSET); - __raw_writel(c->saved_gfer, c->regbase + GFER_OFFSET); - __raw_writel(c->saved_gpdr, c->regbase + GPDR_OFFSET); + writel_relaxed(c->saved_grer, c->regbase + GRER_OFFSET); + writel_relaxed(c->saved_gfer, c->regbase + GFER_OFFSET); + writel_relaxed(c->saved_gpdr, c->regbase + GPDR_OFFSET); } } #else @@ -336,3 +606,10 @@ struct syscore_ops pxa_gpio_syscore_ops = { .suspend = pxa_gpio_suspend, .resume = pxa_gpio_resume, }; + +static int __init pxa_gpio_sysinit(void) +{ + register_syscore_ops(&pxa_gpio_syscore_ops); + return 0; +} +postcore_initcall(pxa_gpio_sysinit); diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 866251852719..6b4d23fd158e 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -24,6 +24,9 @@ #include <linux/interrupt.h> #include <linux/sysdev.h> #include <linux/ioport.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/of_address.h> #include <asm/irq.h> @@ -2374,6 +2377,63 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { #endif }; +#if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) +static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np, + const void *gpio_spec, u32 *flags) +{ + const __be32 *gpio = gpio_spec; + const u32 n = be32_to_cpup(gpio); + unsigned int pin = gc->base + be32_to_cpu(gpio[0]); + + if (WARN_ON(gc->of_gpio_n_cells < 4)) + return -EINVAL; + + if (n > gc->ngpio) + return -EINVAL; + + if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1])))) + pr_warn("gpio_xlate: failed to set pin function\n"); + if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2]))) + pr_warn("gpio_xlate: failed to set pin pull up/down\n"); + if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3]))) + pr_warn("gpio_xlate: failed to set pin drive strength\n"); + + return n; +} + +static const struct of_device_id exynos4_gpio_dt_match[] __initdata = { + { .compatible = "samsung,exynos4-gpio", }, + {} +}; + +static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, + u64 base, u64 offset) +{ + struct gpio_chip *gc = &chip->chip; + u64 address; + + if (!of_have_populated_dt()) + return; + + address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset; + gc->of_node = of_find_matching_node_by_address(NULL, + exynos4_gpio_dt_match, address); + if (!gc->of_node) { + pr_info("gpio: device tree node not found for gpio controller" + " with base address %08llx\n", address); + return; + } + gc->of_gpio_n_cells = 4; + gc->of_xlate = exynos4_gpio_xlate; +} +#elif defined(CONFIG_ARCH_EXYNOS4) +static __init void exynos4_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip, + u64 base, u64 offset) +{ + return; +} +#endif /* defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) */ + /* TODO: cleanup soc_is_* */ static __init int samsung_gpiolib_init(void) { @@ -2455,6 +2515,10 @@ static __init int samsung_gpiolib_init(void) chip->config = &exynos4_gpio_cfg; chip->group = group++; } +#ifdef CONFIG_CPU_EXYNOS4210 + exynos4_gpiolib_attach_ofnode(chip, + EXYNOS4_PA_GPIO1, i * 0x20); +#endif } samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1); @@ -2467,6 +2531,10 @@ static __init int samsung_gpiolib_init(void) chip->config = &exynos4_gpio_cfg; chip->group = group++; } +#ifdef CONFIG_CPU_EXYNOS4210 + exynos4_gpiolib_attach_ofnode(chip, + EXYNOS4_PA_GPIO2, i * 0x20); +#endif } samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2); @@ -2479,6 +2547,10 @@ static __init int samsung_gpiolib_init(void) chip->config = &exynos4_gpio_cfg; chip->group = group++; } +#ifdef CONFIG_CPU_EXYNOS4210 + exynos4_gpiolib_attach_ofnode(chip, + EXYNOS4_PA_GPIO3, i * 0x20); +#endif } samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d09a6e02dc95..004b048c5192 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -62,6 +62,7 @@ static int i915_capabilities(struct seq_file *m, void *data) const struct intel_device_info *info = INTEL_INFO(dev); seq_printf(m, "gen: %d\n", info->gen); + seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev)); #define B(x) seq_printf(m, #x ": %s\n", yesno(info->x)) B(is_mobile); B(is_i85x); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a9533c54c93c..a9ae374861e7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1454,6 +1454,14 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) diff1 = now - dev_priv->last_time1; + /* Prevent division-by-zero if we are asking too fast. + * Also, we don't get interesting results if we are polling + * faster than once in 10ms, so just return the saved value + * in such cases. + */ + if (diff1 <= 10) + return dev_priv->chipset_power; + count1 = I915_READ(DMIEC); count2 = I915_READ(DDREC); count3 = I915_READ(CSIEC); @@ -1484,6 +1492,8 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) dev_priv->last_count1 = total_count; dev_priv->last_time1 = now; + dev_priv->chipset_power = ret; + return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 15bfa9145d2b..a1103fc6597d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -58,15 +58,15 @@ module_param_named(powersave, i915_powersave, int, 0600); MODULE_PARM_DESC(powersave, "Enable powersavings, fbc, downclocking, etc. (default: true)"); -unsigned int i915_semaphores __read_mostly = 0; +int i915_semaphores __read_mostly = -1; module_param_named(semaphores, i915_semaphores, int, 0600); MODULE_PARM_DESC(semaphores, - "Use semaphores for inter-ring sync (default: false)"); + "Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))"); -unsigned int i915_enable_rc6 __read_mostly = 0; +int i915_enable_rc6 __read_mostly = -1; module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); MODULE_PARM_DESC(i915_enable_rc6, - "Enable power-saving render C-state 6 (default: true)"); + "Enable power-saving render C-state 6 (default: -1 (use per-chip default)"); int i915_enable_fbc __read_mostly = -1; module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600); @@ -328,7 +328,7 @@ void intel_detect_pch(struct drm_device *dev) } } -static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) { int count; @@ -344,6 +344,22 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) udelay(10); } +void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1)) + udelay(10); + + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 1); + POSTING_READ(FORCEWAKE_MT); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_MT_ACK) & 1) == 0) + udelay(10); +} + /* * Generally this is called implicitly by the register read function. However, * if some sequence requires the GT to not power down then this function should @@ -356,15 +372,21 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) /* Forcewake is atomic in case we get in here without the lock */ if (atomic_add_return(1, &dev_priv->forcewake_count) == 1) - __gen6_gt_force_wake_get(dev_priv); + dev_priv->display.force_wake_get(dev_priv); } -static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) +void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) { I915_WRITE_NOTRACE(FORCEWAKE, 0); POSTING_READ(FORCEWAKE); } +void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE_MT, (1<<16) | 0); + POSTING_READ(FORCEWAKE_MT); +} + /* * see gen6_gt_force_wake_get() */ @@ -373,7 +395,7 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); if (atomic_dec_and_test(&dev_priv->forcewake_count)) - __gen6_gt_force_wake_put(dev_priv); + dev_priv->display.force_wake_put(dev_priv); } void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) @@ -903,8 +925,9 @@ MODULE_LICENSE("GPL and additional rights"); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE) && \ + ((reg) != ECOBUS)) #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4a9c1b979804..554bef7a3b9c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -107,6 +107,7 @@ struct opregion_header; struct opregion_acpi; struct opregion_swsci; struct opregion_asle; +struct drm_i915_private; struct intel_opregion { struct opregion_header *header; @@ -221,6 +222,8 @@ struct drm_i915_display_funcs { struct drm_i915_gem_object *obj); int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y); + void (*force_wake_get)(struct drm_i915_private *dev_priv); + void (*force_wake_put)(struct drm_i915_private *dev_priv); /* clock updates for mode set */ /* cursor updates */ /* render clock increase/decrease */ @@ -710,6 +713,7 @@ typedef struct drm_i915_private { u64 last_count1; unsigned long last_time1; + unsigned long chipset_power; u64 last_count2; struct timespec last_time2; unsigned long gfx_power; @@ -998,11 +1002,11 @@ extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; extern int i915_panel_ignore_lid __read_mostly; extern unsigned int i915_powersave __read_mostly; -extern unsigned int i915_semaphores __read_mostly; +extern int i915_semaphores __read_mostly; extern unsigned int i915_lvds_downclock __read_mostly; extern int i915_panel_use_ssc __read_mostly; extern int i915_vbt_sdvo_panel_type __read_mostly; -extern unsigned int i915_enable_rc6 __read_mostly; +extern int i915_enable_rc6 __read_mostly; extern int i915_enable_fbc __read_mostly; extern bool i915_enable_hangcheck __read_mostly; @@ -1308,6 +1312,11 @@ extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch(struct drm_device *dev); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); +extern void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); +extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); + /* overlay */ #ifdef CONFIG_DEBUG_FS extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); @@ -1352,8 +1361,9 @@ void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE) && \ + ((reg) != ECOBUS)) #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 60ff1b63b568..8359dc777041 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2026,13 +2026,8 @@ i915_wait_request(struct intel_ring_buffer *ring, * to handle this, the waiter on a request often wants an associated * buffer to have made it to the inactive list, and we would need * a separate wait queue to handle that. - * - * To avoid a recursion with the ilk VT-d workaround (that calls - * gpu_idle when unbinding objects with interruptible==false) don't - * retire requests in that case (because it might call unbind if the - * active list holds the last reference to the object). */ - if (ret == 0 && dev_priv->mm.interruptible) + if (ret == 0) i915_gem_retire_requests_ring(ring); return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 3693e83a97f3..c681dc149d2a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -32,6 +32,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include <linux/dma_remapping.h> struct change_domains { uint32_t invalidate_domains; @@ -746,6 +747,22 @@ i915_gem_execbuffer_flush(struct drm_device *dev, return 0; } +static bool +intel_enable_semaphores(struct drm_device *dev) +{ + if (INTEL_INFO(dev)->gen < 6) + return 0; + + if (i915_semaphores >= 0) + return i915_semaphores; + + /* Enable semaphores on SNB when IO remapping is off */ + if (INTEL_INFO(dev)->gen == 6) + return !intel_iommu_enabled; + + return 1; +} + static int i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, struct intel_ring_buffer *to) @@ -758,7 +775,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, return 0; /* XXX gpu semaphores are implicated in various hard hangs on SNB */ - if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores) + if (!intel_enable_semaphores(obj->base.dev)) return i915_gem_object_wait_rendering(obj); idx = intel_ring_sync_index(from, to); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b080cc824001..a26d5b0a3690 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3303,10 +3303,10 @@ /* or SDVOB */ #define HDMIB 0xe1140 #define PORT_ENABLE (1 << 31) -#define TRANSCODER_A (0) -#define TRANSCODER_B (1 << 30) -#define TRANSCODER(pipe) ((pipe) << 30) -#define TRANSCODER_MASK (1 << 30) +#define TRANSCODER(pipe) ((pipe) << 30) +#define TRANSCODER_CPT(pipe) ((pipe) << 29) +#define TRANSCODER_MASK (1 << 30) +#define TRANSCODER_MASK_CPT (3 << 29) #define COLOR_FORMAT_8bpc (0) #define COLOR_FORMAT_12bpc (3 << 26) #define SDVOB_HOTPLUG_ENABLE (1 << 23) @@ -3447,8 +3447,30 @@ #define EDP_LINK_TRAIN_800_1200MV_0DB_SNB_B (0x38<<22) #define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22) +/* IVB */ +#define EDP_LINK_TRAIN_400MV_0DB_IVB (0x24 <<22) +#define EDP_LINK_TRAIN_400MV_3_5DB_IVB (0x2a <<22) +#define EDP_LINK_TRAIN_400MV_6DB_IVB (0x2f <<22) +#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22) +#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22) +#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22) +#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22) + +/* legacy values */ +#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22) +#define EDP_LINK_TRAIN_1000MV_0DB_IVB (0x20 <<22) +#define EDP_LINK_TRAIN_500MV_3_5DB_IVB (0x02 <<22) +#define EDP_LINK_TRAIN_1000MV_3_5DB_IVB (0x22 <<22) +#define EDP_LINK_TRAIN_1000MV_6DB_IVB (0x23 <<22) + +#define EDP_LINK_TRAIN_VOL_EMP_MASK_IVB (0x3f<<22) + #define FORCEWAKE 0xA18C #define FORCEWAKE_ACK 0x130090 +#define FORCEWAKE_MT 0xa188 /* multi-threaded */ +#define FORCEWAKE_MT_ACK 0x130040 +#define ECOBUS 0xa180 +#define FORCEWAKE_MT_ENABLE (1<<5) #define GT_FIFO_FREE_ENTRIES 0x120008 #define GT_FIFO_NUM_RESERVED_ENTRIES 20 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e77a863a3833..d809b038ca88 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -38,8 +38,8 @@ #include "i915_drv.h" #include "i915_trace.h" #include "drm_dp_helper.h" - #include "drm_crtc_helper.h" +#include <linux/dma_remapping.h> #define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) @@ -4670,6 +4670,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) /** * intel_choose_pipe_bpp_dither - figure out what color depth the pipe should send * @crtc: CRTC structure + * @mode: requested mode * * A pipe may be connected to one or more outputs. Based on the depth of the * attached framebuffer, choose a good color depth to use on the pipe. @@ -4681,13 +4682,15 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) * HDMI supports only 8bpc or 12bpc, so clamp to 8bpc with dither for 10bpc * Displays may support a restricted set as well, check EDID and clamp as * appropriate. + * DP may want to dither down to 6bpc to fit larger modes * * RETURNS: * Dithering requirement (i.e. false if display bpc and pipe bpc match, * true if they don't match). */ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, - unsigned int *pipe_bpp) + unsigned int *pipe_bpp, + struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -4758,6 +4761,11 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + DRM_DEBUG_KMS("Dithering DP to 6bpc\n"); + display_bpc = 6; + } + /* * We could just drive the pipe at the highest bpc all the time and * enable dithering as needed, but that costs bandwidth. So choose @@ -5019,6 +5027,16 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, pipeconf &= ~PIPECONF_DOUBLE_WIDE; } + /* default to 8bpc */ + pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); + if (is_dp) { + if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + pipeconf |= PIPECONF_BPP_6 | + PIPECONF_DITHER_EN | + PIPECONF_DITHER_TYPE_SP; + } + } + dpll |= DPLL_VCO_ENABLE; DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); @@ -5480,7 +5498,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; - dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp); + dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode); switch (pipe_bpp) { case 18: temp |= PIPE_6BPC; @@ -7189,11 +7207,16 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->old_fb_obj = intel_fb->obj; INIT_WORK(&work->work, intel_unpin_work_fn); + ret = drm_vblank_get(dev, intel_crtc->pipe); + if (ret) + goto free_work; + /* We borrow the event spin lock for protecting unpin_work */ spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) { spin_unlock_irqrestore(&dev->event_lock, flags); kfree(work); + drm_vblank_put(dev, intel_crtc->pipe); DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); return -EBUSY; @@ -7212,10 +7235,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, crtc->fb = fb; - ret = drm_vblank_get(dev, intel_crtc->pipe); - if (ret) - goto cleanup_objs; - work->pending_flip_obj = obj; work->enable_stall_check = true; @@ -7238,7 +7257,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, cleanup_pending: atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); -cleanup_objs: drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); @@ -7247,6 +7265,8 @@ cleanup_objs: intel_crtc->unpin_work = NULL; spin_unlock_irqrestore(&dev->event_lock, flags); + drm_vblank_put(dev, intel_crtc->pipe); +free_work: kfree(work); return ret; @@ -7887,6 +7907,33 @@ void intel_init_emon(struct drm_device *dev) dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); } +static bool intel_enable_rc6(struct drm_device *dev) +{ + /* + * Respect the kernel parameter if it is set + */ + if (i915_enable_rc6 >= 0) + return i915_enable_rc6; + + /* + * Disable RC6 on Ironlake + */ + if (INTEL_INFO(dev)->gen == 5) + return 0; + + /* + * Enable rc6 on Sandybridge if DMA remapping is disabled + */ + if (INTEL_INFO(dev)->gen == 6) { + DRM_DEBUG_DRIVER("Sandybridge: intel_iommu_enabled %s -- RC6 %sabled\n", + intel_iommu_enabled ? "true" : "false", + !intel_iommu_enabled ? "en" : "dis"); + return !intel_iommu_enabled; + } + DRM_DEBUG_DRIVER("RC6 enabled\n"); + return 1; +} + void gen6_enable_rps(struct drm_i915_private *dev_priv) { u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); @@ -7923,7 +7970,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ - if (i915_enable_rc6) + if (intel_enable_rc6(dev_priv->dev)) rc6_mask = GEN6_RC_CTL_RC6p_ENABLE | GEN6_RC_CTL_RC6_ENABLE; @@ -8372,7 +8419,7 @@ void ironlake_enable_rc6(struct drm_device *dev) /* rc6 disabled by default due to repeated reports of hanging during * boot and resume. */ - if (!i915_enable_rc6) + if (!intel_enable_rc6(dev)) return; mutex_lock(&dev->struct_mutex); @@ -8491,6 +8538,28 @@ static void intel_init_display(struct drm_device *dev) /* For FIFO watermark updates */ if (HAS_PCH_SPLIT(dev)) { + dev_priv->display.force_wake_get = __gen6_gt_force_wake_get; + dev_priv->display.force_wake_put = __gen6_gt_force_wake_put; + + /* IVB configs may use multi-threaded forcewake */ + if (IS_IVYBRIDGE(dev)) { + u32 ecobus; + + mutex_lock(&dev->struct_mutex); + __gen6_gt_force_wake_mt_get(dev_priv); + ecobus = I915_READ(ECOBUS); + __gen6_gt_force_wake_mt_put(dev_priv); + mutex_unlock(&dev->struct_mutex); + + if (ecobus & FORCEWAKE_MT_ENABLE) { + DRM_DEBUG_KMS("Using MT version of forcewake\n"); + dev_priv->display.force_wake_get = + __gen6_gt_force_wake_mt_get; + dev_priv->display.force_wake_put = + __gen6_gt_force_wake_mt_put; + } + } + if (HAS_PCH_IBX(dev)) dev_priv->display.init_pch_clock_gating = ibx_init_clock_gating; else if (HAS_PCH_CPT(dev)) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4d0358fad937..92b041b66e49 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -208,13 +208,15 @@ intel_dp_link_clock(uint8_t link_bw) */ static int -intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock) +intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp) { struct drm_crtc *crtc = intel_dp->base.base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int bpp = 24; - if (intel_crtc) + if (check_bpp) + bpp = check_bpp; + else if (intel_crtc) bpp = intel_crtc->bpp; return (pixel_clock * bpp + 9) / 10; @@ -233,6 +235,7 @@ intel_dp_mode_valid(struct drm_connector *connector, struct intel_dp *intel_dp = intel_attached_dp(connector); int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); int max_lanes = intel_dp_max_lane_count(intel_dp); + int max_rate, mode_rate; if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) @@ -242,9 +245,17 @@ intel_dp_mode_valid(struct drm_connector *connector, return MODE_PANEL; } - if (intel_dp_link_required(intel_dp, mode->clock) - > intel_dp_max_data_rate(max_link_clock, max_lanes)) - return MODE_CLOCK_HIGH; + mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0); + max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); + + if (mode_rate > max_rate) { + mode_rate = intel_dp_link_required(intel_dp, + mode->clock, 18); + if (mode_rate > max_rate) + return MODE_CLOCK_HIGH; + else + mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC; + } if (mode->clock < 10000) return MODE_CLOCK_LOW; @@ -362,8 +373,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, * clock divider. */ if (is_cpu_edp(intel_dp)) { - if (IS_GEN6(dev)) - aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */ + if (IS_GEN6(dev) || IS_GEN7(dev)) + aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */ else aux_clock_divider = 225; /* eDP input clock at 450Mhz */ } else if (HAS_PCH_SPLIT(dev)) @@ -672,6 +683,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, int lane_count, clock; int max_lane_count = intel_dp_max_lane_count(intel_dp); int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; + int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { @@ -689,7 +701,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); - if (intel_dp_link_required(intel_dp, mode->clock) + if (intel_dp_link_required(intel_dp, mode->clock, bpp) <= link_avail) { intel_dp->link_bw = bws[clock]; intel_dp->lane_count = lane_count; @@ -817,10 +829,11 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, } /* - * There are three kinds of DP registers: + * There are four kinds of DP registers: * * IBX PCH - * CPU + * SNB CPU + * IVB CPU * CPT PCH * * IBX PCH and CPU are the same for almost everything, @@ -873,7 +886,25 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, /* Split out the IBX/CPU vs CPT settings */ - if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { + if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) { + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + intel_dp->DP |= DP_SYNC_HS_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + intel_dp->DP |= DP_SYNC_VS_HIGH; + intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; + + if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN) + intel_dp->DP |= DP_ENHANCED_FRAMING; + + intel_dp->DP |= intel_crtc->pipe << 29; + + /* don't miss out required setting for eDP */ + intel_dp->DP |= DP_PLL_ENABLE; + if (adjusted_mode->clock < 200000) + intel_dp->DP |= DP_PLL_FREQ_160MHZ; + else + intel_dp->DP |= DP_PLL_FREQ_270MHZ; + } else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) { intel_dp->DP |= intel_dp->color_range; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1375,34 +1406,59 @@ static char *link_train_names[] = { * These are source-specific values; current Intel hardware supports * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB */ -#define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 -#define I830_DP_VOLTAGE_MAX_CPT DP_TRAIN_VOLTAGE_SWING_1200 static uint8_t -intel_dp_pre_emphasis_max(uint8_t voltage_swing) +intel_dp_voltage_max(struct intel_dp *intel_dp) { - switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { - case DP_TRAIN_VOLTAGE_SWING_400: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_600: - return DP_TRAIN_PRE_EMPHASIS_6; - case DP_TRAIN_VOLTAGE_SWING_800: - return DP_TRAIN_PRE_EMPHASIS_3_5; - case DP_TRAIN_VOLTAGE_SWING_1200: - default: - return DP_TRAIN_PRE_EMPHASIS_0; + struct drm_device *dev = intel_dp->base.base.dev; + + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) + return DP_TRAIN_VOLTAGE_SWING_800; + else if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + return DP_TRAIN_VOLTAGE_SWING_1200; + else + return DP_TRAIN_VOLTAGE_SWING_800; +} + +static uint8_t +intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) +{ + struct drm_device *dev = intel_dp->base.base.dev; + + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } + } else { + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } } } static void intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]) { - struct drm_device *dev = intel_dp->base.base.dev; uint8_t v = 0; uint8_t p = 0; int lane; uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS); - int voltage_max; + uint8_t voltage_max; + uint8_t preemph_max; for (lane = 0; lane < intel_dp->lane_count; lane++) { uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane); @@ -1414,15 +1470,13 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST p = this_p; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) - voltage_max = I830_DP_VOLTAGE_MAX_CPT; - else - voltage_max = I830_DP_VOLTAGE_MAX; + voltage_max = intel_dp_voltage_max(intel_dp); if (v >= voltage_max) v = voltage_max | DP_TRAIN_MAX_SWING_REACHED; - if (p >= intel_dp_pre_emphasis_max(v)) - p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + preemph_max = intel_dp_pre_emphasis_max(intel_dp, v); + if (p >= preemph_max) + p = preemph_max | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; for (lane = 0; lane < 4; lane++) intel_dp->train_set[lane] = v | p; @@ -1494,6 +1548,37 @@ intel_gen6_edp_signal_levels(uint8_t train_set) } } +/* Gen7's DP voltage swing and pre-emphasis control */ +static uint32_t +intel_gen7_edp_signal_levels(uint8_t train_set) +{ + int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK | + DP_TRAIN_PRE_EMPHASIS_MASK); + switch (signal_levels) { + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_400MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_400MV_3_5DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6: + return EDP_LINK_TRAIN_400MV_6DB_IVB; + + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_600MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_600MV_3_5DB_IVB; + + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0: + return EDP_LINK_TRAIN_800MV_0DB_IVB; + case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_3_5: + return EDP_LINK_TRAIN_800MV_3_5DB_IVB; + + default: + DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" + "0x%x\n", signal_levels); + return EDP_LINK_TRAIN_500MV_0DB_IVB; + } +} + static uint8_t intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) @@ -1599,7 +1684,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) DP_LINK_CONFIGURATION_SIZE); DP |= DP_PORT_EN; - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) DP &= ~DP_LINK_TRAIN_MASK_CPT; else DP &= ~DP_LINK_TRAIN_MASK; @@ -1613,7 +1699,11 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) uint8_t link_status[DP_LINK_STATUS_SIZE]; uint32_t signal_levels; - if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { + + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; + } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { @@ -1622,7 +1712,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) reg = DP | DP_LINK_TRAIN_PAT_1_CPT; else reg = DP | DP_LINK_TRAIN_PAT_1; @@ -1703,7 +1793,10 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) break; } - if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { + if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) { + signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); + DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; + } else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; } else { @@ -1711,7 +1804,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) reg = DP | DP_LINK_TRAIN_PAT_2_CPT; else reg = DP | DP_LINK_TRAIN_PAT_2; @@ -1752,7 +1845,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ++tries; } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) reg = DP | DP_LINK_TRAIN_OFF_CPT; else reg = DP | DP_LINK_TRAIN_OFF; @@ -1782,7 +1875,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) udelay(100); } - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) { + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) { DP &= ~DP_LINK_TRAIN_MASK_CPT; I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT); } else { @@ -1794,7 +1887,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) msleep(17); if (is_edp(intel_dp)) { - if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp)) + if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) DP |= DP_LINK_TRAIN_OFF_CPT; else DP |= DP_LINK_TRAIN_OFF; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bd9a604b73da..a1b4343814e8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -110,6 +110,7 @@ /* drm_display_mode->private_flags */ #define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0) #define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT) +#define INTEL_MODE_DP_FORCE_6BPC (0x10) static inline void intel_mode_set_pixel_multiplier(struct drm_display_mode *mode, diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 42f165a520de..e44191132ac4 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -715,6 +715,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Asus AT5NM10T-I", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"), + }, + }, { } /* terminating entry */ }; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 21f60b7d69a3..04d79fd1dc9d 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -178,13 +178,10 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { max >>= 16; } else { - if (IS_PINEVIEW(dev)) { + if (INTEL_INFO(dev)->gen < 4) max >>= 17; - } else { + else max >>= 16; - if (INTEL_INFO(dev)->gen < 4) - max &= ~1; - } if (is_backlight_combination_mode(dev)) max *= 0xff; @@ -203,13 +200,12 @@ u32 intel_panel_get_backlight(struct drm_device *dev) val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; - if (IS_PINEVIEW(dev)) + if (INTEL_INFO(dev)->gen < 4) val >>= 1; if (is_backlight_combination_mode(dev)) { u8 lbpc; - val &= ~1; pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); val *= lbpc; } @@ -246,11 +242,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level } tmp = I915_READ(BLC_PWM_CTL); - if (IS_PINEVIEW(dev)) { - tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); + if (INTEL_INFO(dev)->gen < 4) level <<= 1; - } else - tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; + tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; I915_WRITE(BLC_PWM_CTL, tmp | level); } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 3003fb25aefd..f7b9268df266 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -50,6 +50,7 @@ #define IS_TMDS(c) (c->output_flag & SDVO_TMDS_MASK) #define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK) #define IS_TV_OR_LVDS(c) (c->output_flag & (SDVO_TV_MASK | SDVO_LVDS_MASK)) +#define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK)) static const char *tv_format_names[] = { @@ -1086,8 +1087,12 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, } sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; } - if (intel_crtc->pipe == 1) - sdvox |= SDVO_PIPE_B_SELECT; + + if (INTEL_PCH_TYPE(dev) >= PCH_CPT) + sdvox |= TRANSCODER_CPT(intel_crtc->pipe); + else + sdvox |= TRANSCODER(intel_crtc->pipe); + if (intel_sdvo->has_hdmi_audio) sdvox |= SDVO_AUDIO_ENABLE; @@ -1314,6 +1319,18 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) return status; } +static bool +intel_sdvo_connector_matches_edid(struct intel_sdvo_connector *sdvo, + struct edid *edid) +{ + bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); + bool connector_is_digital = !!IS_DIGITAL(sdvo); + + DRM_DEBUG_KMS("connector_is_digital? %d, monitor_is_digital? %d\n", + connector_is_digital, monitor_is_digital); + return connector_is_digital == monitor_is_digital; +} + static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector, bool force) { @@ -1358,10 +1375,12 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) if (edid == NULL) edid = intel_sdvo_get_analog_edid(connector); if (edid != NULL) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) - ret = connector_status_disconnected; - else + if (intel_sdvo_connector_matches_edid(intel_sdvo_connector, + edid)) ret = connector_status_connected; + else + ret = connector_status_disconnected; + connector->display_info.raw_edid = NULL; kfree(edid); } else @@ -1402,11 +1421,8 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) edid = intel_sdvo_get_analog_edid(connector); if (edid != NULL) { - struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - bool monitor_is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL); - bool connector_is_digital = !!IS_TMDS(intel_sdvo_connector); - - if (connector_is_digital == monitor_is_digital) { + if (intel_sdvo_connector_matches_edid(to_intel_sdvo_connector(connector), + edid)) { drm_mode_connector_update_edid_property(connector, edid); drm_add_edid_modes(connector, edid); } diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index 7a48b1eb4233..5253d23361d9 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c @@ -59,7 +59,7 @@ static ssize_t jz4740_hwmon_read_adcin(struct device *dev, { struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); struct completion *completion = &hwmon->read_completion; - unsigned long t; + long t; unsigned long val; int ret; @@ -203,7 +203,7 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev) return 0; } -struct platform_driver jz4740_hwmon_driver = { +static struct platform_driver jz4740_hwmon_driver = { .probe = jz4740_hwmon_probe, .remove = __devexit_p(jz4740_hwmon_remove), .driver = { diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 46b6500c5478..6381604696d3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -558,7 +558,7 @@ static const struct i2c_algorithm tegra_i2c_algo = { .functionality = tegra_i2c_func, }; -static int tegra_i2c_probe(struct platform_device *pdev) +static int __devinit tegra_i2c_probe(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; @@ -636,7 +636,10 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->bus_clk_rate = be32_to_cpup(prop); } - if (pdev->id == 3) + if (pdev->dev.of_node) + i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, + "nvidia,tegra20-i2c-dvc"); + else if (pdev->id == 3) i2c_dev->is_dvc = 1; init_completion(&i2c_dev->msg_complete); @@ -690,7 +693,7 @@ err_iounmap: return ret; } -static int tegra_i2c_remove(struct platform_device *pdev) +static int __devexit tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adapter); @@ -742,6 +745,7 @@ static int tegra_i2c_resume(struct platform_device *pdev) /* Match table for of_platform binding */ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { { .compatible = "nvidia,tegra20-i2c", }, + { .compatible = "nvidia,tegra20-i2c-dvc", }, {}, }; MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index f689f49e3109..8a0060cd3982 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -21,6 +21,8 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #include <linux/sched.h> #include <plat/keypad.h> @@ -68,31 +70,26 @@ struct samsung_keypad { wait_queue_head_t wait; bool stopped; int irq; + enum samsung_keypad_type type; unsigned int row_shift; unsigned int rows; unsigned int cols; unsigned int row_state[SAMSUNG_MAX_COLS]; +#ifdef CONFIG_OF + int row_gpios[SAMSUNG_MAX_ROWS]; + int col_gpios[SAMSUNG_MAX_COLS]; +#endif unsigned short keycodes[]; }; -static int samsung_keypad_is_s5pv210(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - enum samsung_keypad_type type = - platform_get_device_id(pdev)->driver_data; - - return type == KEYPAD_TYPE_S5PV210; -} - static void samsung_keypad_scan(struct samsung_keypad *keypad, unsigned int *row_state) { - struct device *dev = keypad->input_dev->dev.parent; unsigned int col; unsigned int val; for (col = 0; col < keypad->cols; col++) { - if (samsung_keypad_is_s5pv210(dev)) { + if (keypad->type == KEYPAD_TYPE_S5PV210) { val = S5PV210_KEYIFCOLEN_MASK; val &= ~(1 << col) << 8; } else { @@ -235,6 +232,126 @@ static void samsung_keypad_close(struct input_dev *input_dev) samsung_keypad_stop(keypad); } +#ifdef CONFIG_OF +static struct samsung_keypad_platdata *samsung_keypad_parse_dt( + struct device *dev) +{ + struct samsung_keypad_platdata *pdata; + struct matrix_keymap_data *keymap_data; + uint32_t *keymap, num_rows = 0, num_cols = 0; + struct device_node *np = dev->of_node, *key_np; + unsigned int key_count = 0; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "could not allocate memory for platform data\n"); + return NULL; + } + + of_property_read_u32(np, "samsung,keypad-num-rows", &num_rows); + of_property_read_u32(np, "samsung,keypad-num-columns", &num_cols); + if (!num_rows || !num_cols) { + dev_err(dev, "number of keypad rows/columns not specified\n"); + return NULL; + } + pdata->rows = num_rows; + pdata->cols = num_cols; + + keymap_data = devm_kzalloc(dev, sizeof(*keymap_data), GFP_KERNEL); + if (!keymap_data) { + dev_err(dev, "could not allocate memory for keymap data\n"); + return NULL; + } + pdata->keymap_data = keymap_data; + + for_each_child_of_node(np, key_np) + key_count++; + + keymap_data->keymap_size = key_count; + keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); + if (!keymap) { + dev_err(dev, "could not allocate memory for keymap\n"); + return NULL; + } + keymap_data->keymap = keymap; + + for_each_child_of_node(np, key_np) { + u32 row, col, key_code; + of_property_read_u32(key_np, "keypad,row", &row); + of_property_read_u32(key_np, "keypad,column", &col); + of_property_read_u32(key_np, "linux,code", &key_code); + *keymap++ = KEY(row, col, key_code); + } + + if (of_get_property(np, "linux,input-no-autorepeat", NULL)) + pdata->no_autorepeat = true; + if (of_get_property(np, "linux,input-wakeup", NULL)) + pdata->wakeup = true; + + return pdata; +} + +static void samsung_keypad_parse_dt_gpio(struct device *dev, + struct samsung_keypad *keypad) +{ + struct device_node *np = dev->of_node; + int gpio, ret, row, col; + + for (row = 0; row < keypad->rows; row++) { + gpio = of_get_named_gpio(np, "row-gpios", row); + keypad->row_gpios[row] = gpio; + if (!gpio_is_valid(gpio)) { + dev_err(dev, "keypad row[%d]: invalid gpio %d\n", + row, gpio); + continue; + } + + ret = gpio_request(gpio, "keypad-row"); + if (ret) + dev_err(dev, "keypad row[%d] gpio request failed\n", + row); + } + + for (col = 0; col < keypad->cols; col++) { + gpio = of_get_named_gpio(np, "col-gpios", col); + keypad->col_gpios[col] = gpio; + if (!gpio_is_valid(gpio)) { + dev_err(dev, "keypad column[%d]: invalid gpio %d\n", + col, gpio); + continue; + } + + ret = gpio_request(gpio, "keypad-col"); + if (ret) + dev_err(dev, "keypad column[%d] gpio request failed\n", + col); + } +} + +static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) +{ + int cnt; + + for (cnt = 0; cnt < keypad->rows; cnt++) + if (gpio_is_valid(keypad->row_gpios[cnt])) + gpio_free(keypad->row_gpios[cnt]); + + for (cnt = 0; cnt < keypad->cols; cnt++) + if (gpio_is_valid(keypad->col_gpios[cnt])) + gpio_free(keypad->col_gpios[cnt]); +} +#else +static +struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) +{ + return NULL; +} + +static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) +{ +} +#endif + static int __devinit samsung_keypad_probe(struct platform_device *pdev) { const struct samsung_keypad_platdata *pdata; @@ -246,7 +363,10 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) unsigned int keymap_size; int error; - pdata = pdev->dev.platform_data; + if (pdev->dev.of_node) + pdata = samsung_keypad_parse_dt(&pdev->dev); + else + pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data defined\n"); return -EINVAL; @@ -303,6 +423,16 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) keypad->cols = pdata->cols; init_waitqueue_head(&keypad->wait); + if (pdev->dev.of_node) { +#ifdef CONFIG_OF + samsung_keypad_parse_dt_gpio(&pdev->dev, keypad); + keypad->type = of_device_is_compatible(pdev->dev.of_node, + "samsung,s5pv210-keypad"); +#endif + } else { + keypad->type = platform_get_device_id(pdev)->driver_data; + } + input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; @@ -343,12 +473,19 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, pdata->wakeup); platform_set_drvdata(pdev, keypad); + + if (pdev->dev.of_node) { + devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap); + devm_kfree(&pdev->dev, (void *)pdata->keymap_data); + devm_kfree(&pdev->dev, (void *)pdata); + } return 0; err_free_irq: free_irq(keypad->irq, keypad); err_put_clk: clk_put(keypad->clk); + samsung_keypad_dt_gpio_free(keypad); err_unmap_base: iounmap(keypad->base); err_free_mem: @@ -374,6 +511,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev) free_irq(keypad->irq, keypad); clk_put(keypad->clk); + samsung_keypad_dt_gpio_free(keypad); iounmap(keypad->base); kfree(keypad); @@ -447,6 +585,17 @@ static const struct dev_pm_ops samsung_keypad_pm_ops = { }; #endif +#ifdef CONFIG_OF +static const struct of_device_id samsung_keypad_dt_match[] = { + { .compatible = "samsung,s3c6410-keypad" }, + { .compatible = "samsung,s5pv210-keypad" }, + {}, +}; +MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match); +#else +#define samsung_keypad_dt_match NULL +#endif + static struct platform_device_id samsung_keypad_driver_ids[] = { { .name = "samsung-keypad", @@ -465,6 +614,7 @@ static struct platform_driver samsung_keypad_driver = { .driver = { .name = "samsung-keypad", .owner = THIS_MODULE, + .of_match_table = samsung_keypad_dt_match, #ifdef CONFIG_PM .pm = &samsung_keypad_pm_ops, #endif diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index f6328c0cded6..0a707bbbbea6 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c @@ -22,6 +22,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/gpio.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -192,8 +193,8 @@ static int zylonite_wm97xx_probe(struct platform_device *pdev) else gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); - wm->pen_irq = IRQ_GPIO(gpio_touch_irq); - irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); + wm->pen_irq = gpio_to_irq(gpio_touch_irq); + irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, WM97XX_GPIO_POL_HIGH, diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a004c3945c67..bdc447fd4766 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -405,6 +405,9 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_INTEL_IOMMU_DEFAULT_ON*/ +int intel_iommu_enabled = 0; +EXPORT_SYMBOL_GPL(intel_iommu_enabled); + static int dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; @@ -3647,6 +3650,8 @@ int __init intel_iommu_init(void) bus_register_notifier(&pci_bus_type, &device_nb); + intel_iommu_enabled = 1; + return 0; } diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 86e14583a082..3f565ef3e149 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -27,8 +27,9 @@ #include <linux/spinlock.h> #include <linux/gpio.h> #include <plat/usb.h> +#include <linux/pm_runtime.h> -#define USBHS_DRIVER_NAME "usbhs-omap" +#define USBHS_DRIVER_NAME "usbhs_omap" #define OMAP_EHCI_DEVICE "ehci-omap" #define OMAP_OHCI_DEVICE "ohci-omap3" @@ -147,9 +148,6 @@ struct usbhs_hcd_omap { - struct clk *usbhost_ick; - struct clk *usbhost_hs_fck; - struct clk *usbhost_fs_fck; struct clk *xclk60mhsp1_ck; struct clk *xclk60mhsp2_ck; struct clk *utmi_p1_fck; @@ -159,8 +157,7 @@ struct usbhs_hcd_omap { struct clk *usbhost_p2_fck; struct clk *usbtll_p2_fck; struct clk *init_60m_fclk; - struct clk *usbtll_fck; - struct clk *usbtll_ick; + struct clk *ehci_logic_fck; void __iomem *uhh_base; void __iomem *tll_base; @@ -169,7 +166,6 @@ struct usbhs_hcd_omap { u32 usbhs_rev; spinlock_t lock; - int count; }; /*-------------------------------------------------------------------------*/ @@ -319,269 +315,6 @@ err_end: return ret; } -/** - * usbhs_omap_probe - initialize TI-based HCDs - * - * Allocates basic resources for this USB host controller. - */ -static int __devinit usbhs_omap_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct usbhs_omap_platform_data *pdata = dev->platform_data; - struct usbhs_hcd_omap *omap; - struct resource *res; - int ret = 0; - int i; - - if (!pdata) { - dev_err(dev, "Missing platform data\n"); - ret = -ENOMEM; - goto end_probe; - } - - omap = kzalloc(sizeof(*omap), GFP_KERNEL); - if (!omap) { - dev_err(dev, "Memory allocation failed\n"); - ret = -ENOMEM; - goto end_probe; - } - - spin_lock_init(&omap->lock); - - for (i = 0; i < OMAP3_HS_USB_PORTS; i++) - omap->platdata.port_mode[i] = pdata->port_mode[i]; - - omap->platdata.ehci_data = pdata->ehci_data; - omap->platdata.ohci_data = pdata->ohci_data; - - omap->usbhost_ick = clk_get(dev, "usbhost_ick"); - if (IS_ERR(omap->usbhost_ick)) { - ret = PTR_ERR(omap->usbhost_ick); - dev_err(dev, "usbhost_ick failed error:%d\n", ret); - goto err_end; - } - - omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); - if (IS_ERR(omap->usbhost_hs_fck)) { - ret = PTR_ERR(omap->usbhost_hs_fck); - dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); - goto err_usbhost_ick; - } - - omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); - if (IS_ERR(omap->usbhost_fs_fck)) { - ret = PTR_ERR(omap->usbhost_fs_fck); - dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); - goto err_usbhost_hs_fck; - } - - omap->usbtll_fck = clk_get(dev, "usbtll_fck"); - if (IS_ERR(omap->usbtll_fck)) { - ret = PTR_ERR(omap->usbtll_fck); - dev_err(dev, "usbtll_fck failed error:%d\n", ret); - goto err_usbhost_fs_fck; - } - - omap->usbtll_ick = clk_get(dev, "usbtll_ick"); - if (IS_ERR(omap->usbtll_ick)) { - ret = PTR_ERR(omap->usbtll_ick); - dev_err(dev, "usbtll_ick failed error:%d\n", ret); - goto err_usbtll_fck; - } - - omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); - if (IS_ERR(omap->utmi_p1_fck)) { - ret = PTR_ERR(omap->utmi_p1_fck); - dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); - goto err_usbtll_ick; - } - - omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); - if (IS_ERR(omap->xclk60mhsp1_ck)) { - ret = PTR_ERR(omap->xclk60mhsp1_ck); - dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); - goto err_utmi_p1_fck; - } - - omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); - if (IS_ERR(omap->utmi_p2_fck)) { - ret = PTR_ERR(omap->utmi_p2_fck); - dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); - goto err_xclk60mhsp1_ck; - } - - omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); - if (IS_ERR(omap->xclk60mhsp2_ck)) { - ret = PTR_ERR(omap->xclk60mhsp2_ck); - dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); - goto err_utmi_p2_fck; - } - - omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); - if (IS_ERR(omap->usbhost_p1_fck)) { - ret = PTR_ERR(omap->usbhost_p1_fck); - dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); - goto err_xclk60mhsp2_ck; - } - - omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); - if (IS_ERR(omap->usbtll_p1_fck)) { - ret = PTR_ERR(omap->usbtll_p1_fck); - dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); - goto err_usbhost_p1_fck; - } - - omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); - if (IS_ERR(omap->usbhost_p2_fck)) { - ret = PTR_ERR(omap->usbhost_p2_fck); - dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); - goto err_usbtll_p1_fck; - } - - omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); - if (IS_ERR(omap->usbtll_p2_fck)) { - ret = PTR_ERR(omap->usbtll_p2_fck); - dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); - goto err_usbhost_p2_fck; - } - - omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); - if (IS_ERR(omap->init_60m_fclk)) { - ret = PTR_ERR(omap->init_60m_fclk); - dev_err(dev, "init_60m_fclk failed error:%d\n", ret); - goto err_usbtll_p2_fck; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); - if (!res) { - dev_err(dev, "UHH EHCI get resource failed\n"); - ret = -ENODEV; - goto err_init_60m_fclk; - } - - omap->uhh_base = ioremap(res->start, resource_size(res)); - if (!omap->uhh_base) { - dev_err(dev, "UHH ioremap failed\n"); - ret = -ENOMEM; - goto err_init_60m_fclk; - } - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); - if (!res) { - dev_err(dev, "UHH EHCI get resource failed\n"); - ret = -ENODEV; - goto err_tll; - } - - omap->tll_base = ioremap(res->start, resource_size(res)); - if (!omap->tll_base) { - dev_err(dev, "TLL ioremap failed\n"); - ret = -ENOMEM; - goto err_tll; - } - - platform_set_drvdata(pdev, omap); - - ret = omap_usbhs_alloc_children(pdev); - if (ret) { - dev_err(dev, "omap_usbhs_alloc_children failed\n"); - goto err_alloc; - } - - goto end_probe; - -err_alloc: - iounmap(omap->tll_base); - -err_tll: - iounmap(omap->uhh_base); - -err_init_60m_fclk: - clk_put(omap->init_60m_fclk); - -err_usbtll_p2_fck: - clk_put(omap->usbtll_p2_fck); - -err_usbhost_p2_fck: - clk_put(omap->usbhost_p2_fck); - -err_usbtll_p1_fck: - clk_put(omap->usbtll_p1_fck); - -err_usbhost_p1_fck: - clk_put(omap->usbhost_p1_fck); - -err_xclk60mhsp2_ck: - clk_put(omap->xclk60mhsp2_ck); - -err_utmi_p2_fck: - clk_put(omap->utmi_p2_fck); - -err_xclk60mhsp1_ck: - clk_put(omap->xclk60mhsp1_ck); - -err_utmi_p1_fck: - clk_put(omap->utmi_p1_fck); - -err_usbtll_ick: - clk_put(omap->usbtll_ick); - -err_usbtll_fck: - clk_put(omap->usbtll_fck); - -err_usbhost_fs_fck: - clk_put(omap->usbhost_fs_fck); - -err_usbhost_hs_fck: - clk_put(omap->usbhost_hs_fck); - -err_usbhost_ick: - clk_put(omap->usbhost_ick); - -err_end: - kfree(omap); - -end_probe: - return ret; -} - -/** - * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs - * @pdev: USB Host Controller being removed - * - * Reverses the effect of usbhs_omap_probe(). - */ -static int __devexit usbhs_omap_remove(struct platform_device *pdev) -{ - struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); - - if (omap->count != 0) { - dev_err(&pdev->dev, - "Either EHCI or OHCI is still using usbhs core\n"); - return -EBUSY; - } - - iounmap(omap->tll_base); - iounmap(omap->uhh_base); - clk_put(omap->init_60m_fclk); - clk_put(omap->usbtll_p2_fck); - clk_put(omap->usbhost_p2_fck); - clk_put(omap->usbtll_p1_fck); - clk_put(omap->usbhost_p1_fck); - clk_put(omap->xclk60mhsp2_ck); - clk_put(omap->utmi_p2_fck); - clk_put(omap->xclk60mhsp1_ck); - clk_put(omap->utmi_p1_fck); - clk_put(omap->usbtll_ick); - clk_put(omap->usbtll_fck); - clk_put(omap->usbhost_fs_fck); - clk_put(omap->usbhost_hs_fck); - clk_put(omap->usbhost_ick); - kfree(omap); - - return 0; -} - static bool is_ohci_port(enum usbhs_omap_port_mode pmode) { switch (pmode) { @@ -689,30 +422,85 @@ static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count) } } -static int usbhs_enable(struct device *dev) +static int usbhs_runtime_resume(struct device *dev) { struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); struct usbhs_omap_platform_data *pdata = &omap->platdata; - unsigned long flags = 0; - int ret = 0; - unsigned long timeout; - unsigned reg; + unsigned long flags; + + dev_dbg(dev, "usbhs_runtime_resume\n"); - dev_dbg(dev, "starting TI HSUSB Controller\n"); if (!pdata) { dev_dbg(dev, "missing platform_data\n"); return -ENODEV; } spin_lock_irqsave(&omap->lock, flags); - if (omap->count > 0) - goto end_count; - clk_enable(omap->usbhost_ick); - clk_enable(omap->usbhost_hs_fck); - clk_enable(omap->usbhost_fs_fck); - clk_enable(omap->usbtll_fck); - clk_enable(omap->usbtll_ick); + if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) + clk_enable(omap->ehci_logic_fck); + + if (is_ehci_tll_mode(pdata->port_mode[0])) { + clk_enable(omap->usbhost_p1_fck); + clk_enable(omap->usbtll_p1_fck); + } + if (is_ehci_tll_mode(pdata->port_mode[1])) { + clk_enable(omap->usbhost_p2_fck); + clk_enable(omap->usbtll_p2_fck); + } + clk_enable(omap->utmi_p1_fck); + clk_enable(omap->utmi_p2_fck); + + spin_unlock_irqrestore(&omap->lock, flags); + + return 0; +} + +static int usbhs_runtime_suspend(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; + unsigned long flags; + + dev_dbg(dev, "usbhs_runtime_suspend\n"); + + if (!pdata) { + dev_dbg(dev, "missing platform_data\n"); + return -ENODEV; + } + + spin_lock_irqsave(&omap->lock, flags); + + if (is_ehci_tll_mode(pdata->port_mode[0])) { + clk_disable(omap->usbhost_p1_fck); + clk_disable(omap->usbtll_p1_fck); + } + if (is_ehci_tll_mode(pdata->port_mode[1])) { + clk_disable(omap->usbhost_p2_fck); + clk_disable(omap->usbtll_p2_fck); + } + clk_disable(omap->utmi_p2_fck); + clk_disable(omap->utmi_p1_fck); + + if (omap->ehci_logic_fck && !IS_ERR(omap->ehci_logic_fck)) + clk_disable(omap->ehci_logic_fck); + + spin_unlock_irqrestore(&omap->lock, flags); + + return 0; +} + +static void omap_usbhs_init(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; + unsigned long flags; + unsigned reg; + + dev_dbg(dev, "starting TI HSUSB Controller\n"); + + pm_runtime_get_sync(dev); + spin_lock_irqsave(&omap->lock, flags); if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { @@ -736,50 +524,6 @@ static int usbhs_enable(struct device *dev) omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); - /* perform TLL soft reset, and wait until reset is complete */ - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, - OMAP_USBTLL_SYSCONFIG_SOFTRESET); - - /* Wait for TLL reset to complete */ - timeout = jiffies + msecs_to_jiffies(1000); - while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) - & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_dbg(dev, "operation timed out\n"); - ret = -EINVAL; - goto err_tll; - } - } - - dev_dbg(dev, "TLL RESET DONE\n"); - - /* (1<<3) = no idle mode only for initial debugging */ - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, - OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | - OMAP_USBTLL_SYSCONFIG_SIDLEMODE | - OMAP_USBTLL_SYSCONFIG_AUTOIDLE); - - /* Put UHH in NoIdle/NoStandby mode */ - reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); - if (is_omap_usbhs_rev1(omap)) { - reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP - | OMAP_UHH_SYSCONFIG_SIDLEMODE - | OMAP_UHH_SYSCONFIG_CACTIVITY - | OMAP_UHH_SYSCONFIG_MIDLEMODE); - reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; - - - } else if (is_omap_usbhs_rev2(omap)) { - reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; - reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; - reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; - reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; - } - - usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); - reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); /* setup ULPI bypass and burst configurations */ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN @@ -825,49 +569,6 @@ static int usbhs_enable(struct device *dev) reg &= ~OMAP4_P1_MODE_CLEAR; reg &= ~OMAP4_P2_MODE_CLEAR; - if (is_ehci_phy_mode(pdata->port_mode[0])) { - ret = clk_set_parent(omap->utmi_p1_fck, - omap->xclk60mhsp1_ck); - if (ret != 0) { - dev_err(dev, "xclk60mhsp1_ck set parent" - "failed error:%d\n", ret); - goto err_tll; - } - } else if (is_ehci_tll_mode(pdata->port_mode[0])) { - ret = clk_set_parent(omap->utmi_p1_fck, - omap->init_60m_fclk); - if (ret != 0) { - dev_err(dev, "init_60m_fclk set parent" - "failed error:%d\n", ret); - goto err_tll; - } - clk_enable(omap->usbhost_p1_fck); - clk_enable(omap->usbtll_p1_fck); - } - - if (is_ehci_phy_mode(pdata->port_mode[1])) { - ret = clk_set_parent(omap->utmi_p2_fck, - omap->xclk60mhsp2_ck); - if (ret != 0) { - dev_err(dev, "xclk60mhsp1_ck set parent" - "failed error:%d\n", ret); - goto err_tll; - } - } else if (is_ehci_tll_mode(pdata->port_mode[1])) { - ret = clk_set_parent(omap->utmi_p2_fck, - omap->init_60m_fclk); - if (ret != 0) { - dev_err(dev, "init_60m_fclk set parent" - "failed error:%d\n", ret); - goto err_tll; - } - clk_enable(omap->usbhost_p2_fck); - clk_enable(omap->usbtll_p2_fck); - } - - clk_enable(omap->utmi_p1_fck); - clk_enable(omap->utmi_p2_fck); - if (is_ehci_tll_mode(pdata->port_mode[0]) || (is_ohci_port(pdata->port_mode[0]))) reg |= OMAP4_P1_MODE_TLL; @@ -913,12 +614,15 @@ static int usbhs_enable(struct device *dev) (pdata->ehci_data->reset_gpio_port[1], 1); } -end_count: - omap->count++; spin_unlock_irqrestore(&omap->lock, flags); - return 0; + pm_runtime_put_sync(dev); +} + +static void omap_usbhs_deinit(struct device *dev) +{ + struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); + struct usbhs_omap_platform_data *pdata = &omap->platdata; -err_tll: if (pdata->ehci_data->phy_reset) { if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) gpio_free(pdata->ehci_data->reset_gpio_port[0]); @@ -926,123 +630,272 @@ err_tll: if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) gpio_free(pdata->ehci_data->reset_gpio_port[1]); } - - clk_disable(omap->usbtll_ick); - clk_disable(omap->usbtll_fck); - clk_disable(omap->usbhost_fs_fck); - clk_disable(omap->usbhost_hs_fck); - clk_disable(omap->usbhost_ick); - spin_unlock_irqrestore(&omap->lock, flags); - return ret; } -static void usbhs_disable(struct device *dev) + +/** + * usbhs_omap_probe - initialize TI-based HCDs + * + * Allocates basic resources for this USB host controller. + */ +static int __devinit usbhs_omap_probe(struct platform_device *pdev) { - struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); - struct usbhs_omap_platform_data *pdata = &omap->platdata; - unsigned long flags = 0; - unsigned long timeout; + struct device *dev = &pdev->dev; + struct usbhs_omap_platform_data *pdata = dev->platform_data; + struct usbhs_hcd_omap *omap; + struct resource *res; + int ret = 0; + int i; - dev_dbg(dev, "stopping TI HSUSB Controller\n"); + if (!pdata) { + dev_err(dev, "Missing platform data\n"); + ret = -ENOMEM; + goto end_probe; + } - spin_lock_irqsave(&omap->lock, flags); + omap = kzalloc(sizeof(*omap), GFP_KERNEL); + if (!omap) { + dev_err(dev, "Memory allocation failed\n"); + ret = -ENOMEM; + goto end_probe; + } - if (omap->count == 0) - goto end_disble; + spin_lock_init(&omap->lock); - omap->count--; + for (i = 0; i < OMAP3_HS_USB_PORTS; i++) + omap->platdata.port_mode[i] = pdata->port_mode[i]; + + omap->platdata.ehci_data = pdata->ehci_data; + omap->platdata.ohci_data = pdata->ohci_data; - if (omap->count != 0) - goto end_disble; + pm_runtime_enable(dev); - /* Reset OMAP modules for insmod/rmmod to work */ - usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, - is_omap_usbhs_rev2(omap) ? - OMAP4_UHH_SYSCONFIG_SOFTRESET : - OMAP_UHH_SYSCONFIG_SOFTRESET); - timeout = jiffies + msecs_to_jiffies(100); - while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) - & (1 << 0))) { - cpu_relax(); + for (i = 0; i < OMAP3_HS_USB_PORTS; i++) + if (is_ehci_phy_mode(i) || is_ehci_tll_mode(i) || + is_ehci_hsic_mode(i)) { + omap->ehci_logic_fck = clk_get(dev, "ehci_logic_fck"); + if (IS_ERR(omap->ehci_logic_fck)) { + ret = PTR_ERR(omap->ehci_logic_fck); + dev_warn(dev, "ehci_logic_fck failed:%d\n", + ret); + } + break; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); + if (IS_ERR(omap->utmi_p1_fck)) { + ret = PTR_ERR(omap->utmi_p1_fck); + dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); + goto err_end; } - while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) - & (1 << 1))) { - cpu_relax(); + omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); + if (IS_ERR(omap->xclk60mhsp1_ck)) { + ret = PTR_ERR(omap->xclk60mhsp1_ck); + dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); + goto err_utmi_p1_fck; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); + if (IS_ERR(omap->utmi_p2_fck)) { + ret = PTR_ERR(omap->utmi_p2_fck); + dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); + goto err_xclk60mhsp1_ck; } - while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) - & (1 << 2))) { - cpu_relax(); + omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); + if (IS_ERR(omap->xclk60mhsp2_ck)) { + ret = PTR_ERR(omap->xclk60mhsp2_ck); + dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); + goto err_utmi_p2_fck; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); + if (IS_ERR(omap->usbhost_p1_fck)) { + ret = PTR_ERR(omap->usbhost_p1_fck); + dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); + goto err_xclk60mhsp2_ck; } - usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); + omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); + if (IS_ERR(omap->usbtll_p1_fck)) { + ret = PTR_ERR(omap->usbtll_p1_fck); + dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); + goto err_usbhost_p1_fck; + } - while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) - & (1 << 0))) { - cpu_relax(); + omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); + if (IS_ERR(omap->usbhost_p2_fck)) { + ret = PTR_ERR(omap->usbhost_p2_fck); + dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); + goto err_usbtll_p1_fck; + } - if (time_after(jiffies, timeout)) - dev_dbg(dev, "operation timed out\n"); + omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); + if (IS_ERR(omap->usbtll_p2_fck)) { + ret = PTR_ERR(omap->usbtll_p2_fck); + dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); + goto err_usbhost_p2_fck; } - if (is_omap_usbhs_rev2(omap)) { - if (is_ehci_tll_mode(pdata->port_mode[0])) - clk_disable(omap->usbtll_p1_fck); - if (is_ehci_tll_mode(pdata->port_mode[1])) - clk_disable(omap->usbtll_p2_fck); - clk_disable(omap->utmi_p2_fck); - clk_disable(omap->utmi_p1_fck); + omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); + if (IS_ERR(omap->init_60m_fclk)) { + ret = PTR_ERR(omap->init_60m_fclk); + dev_err(dev, "init_60m_fclk failed error:%d\n", ret); + goto err_usbtll_p2_fck; } - clk_disable(omap->usbtll_ick); - clk_disable(omap->usbtll_fck); - clk_disable(omap->usbhost_fs_fck); - clk_disable(omap->usbhost_hs_fck); - clk_disable(omap->usbhost_ick); + if (is_ehci_phy_mode(pdata->port_mode[0])) { + /* for OMAP3 , the clk set paretn fails */ + ret = clk_set_parent(omap->utmi_p1_fck, + omap->xclk60mhsp1_ck); + if (ret != 0) + dev_err(dev, "xclk60mhsp1_ck set parent" + "failed error:%d\n", ret); + } else if (is_ehci_tll_mode(pdata->port_mode[0])) { + ret = clk_set_parent(omap->utmi_p1_fck, + omap->init_60m_fclk); + if (ret != 0) + dev_err(dev, "init_60m_fclk set parent" + "failed error:%d\n", ret); + } - /* The gpio_free migh sleep; so unlock the spinlock */ - spin_unlock_irqrestore(&omap->lock, flags); + if (is_ehci_phy_mode(pdata->port_mode[1])) { + ret = clk_set_parent(omap->utmi_p2_fck, + omap->xclk60mhsp2_ck); + if (ret != 0) + dev_err(dev, "xclk60mhsp2_ck set parent" + "failed error:%d\n", ret); + } else if (is_ehci_tll_mode(pdata->port_mode[1])) { + ret = clk_set_parent(omap->utmi_p2_fck, + omap->init_60m_fclk); + if (ret != 0) + dev_err(dev, "init_60m_fclk set parent" + "failed error:%d\n", ret); + } - if (pdata->ehci_data->phy_reset) { - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) - gpio_free(pdata->ehci_data->reset_gpio_port[0]); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); + if (!res) { + dev_err(dev, "UHH EHCI get resource failed\n"); + ret = -ENODEV; + goto err_init_60m_fclk; + } - if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) - gpio_free(pdata->ehci_data->reset_gpio_port[1]); + omap->uhh_base = ioremap(res->start, resource_size(res)); + if (!omap->uhh_base) { + dev_err(dev, "UHH ioremap failed\n"); + ret = -ENOMEM; + goto err_init_60m_fclk; } - return; -end_disble: - spin_unlock_irqrestore(&omap->lock, flags); -} + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); + if (!res) { + dev_err(dev, "UHH EHCI get resource failed\n"); + ret = -ENODEV; + goto err_tll; + } -int omap_usbhs_enable(struct device *dev) -{ - return usbhs_enable(dev->parent); + omap->tll_base = ioremap(res->start, resource_size(res)); + if (!omap->tll_base) { + dev_err(dev, "TLL ioremap failed\n"); + ret = -ENOMEM; + goto err_tll; + } + + platform_set_drvdata(pdev, omap); + + ret = omap_usbhs_alloc_children(pdev); + if (ret) { + dev_err(dev, "omap_usbhs_alloc_children failed\n"); + goto err_alloc; + } + + omap_usbhs_init(dev); + + goto end_probe; + +err_alloc: + iounmap(omap->tll_base); + +err_tll: + iounmap(omap->uhh_base); + +err_init_60m_fclk: + clk_put(omap->init_60m_fclk); + +err_usbtll_p2_fck: + clk_put(omap->usbtll_p2_fck); + +err_usbhost_p2_fck: + clk_put(omap->usbhost_p2_fck); + +err_usbtll_p1_fck: + clk_put(omap->usbtll_p1_fck); + +err_usbhost_p1_fck: + clk_put(omap->usbhost_p1_fck); + +err_xclk60mhsp2_ck: + clk_put(omap->xclk60mhsp2_ck); + +err_utmi_p2_fck: + clk_put(omap->utmi_p2_fck); + +err_xclk60mhsp1_ck: + clk_put(omap->xclk60mhsp1_ck); + +err_utmi_p1_fck: + clk_put(omap->utmi_p1_fck); + +err_end: + clk_put(omap->ehci_logic_fck); + pm_runtime_disable(dev); + kfree(omap); + +end_probe: + return ret; } -EXPORT_SYMBOL_GPL(omap_usbhs_enable); -void omap_usbhs_disable(struct device *dev) +/** + * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs + * @pdev: USB Host Controller being removed + * + * Reverses the effect of usbhs_omap_probe(). + */ +static int __devexit usbhs_omap_remove(struct platform_device *pdev) { - usbhs_disable(dev->parent); + struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); + + omap_usbhs_deinit(&pdev->dev); + iounmap(omap->tll_base); + iounmap(omap->uhh_base); + clk_put(omap->init_60m_fclk); + clk_put(omap->usbtll_p2_fck); + clk_put(omap->usbhost_p2_fck); + clk_put(omap->usbtll_p1_fck); + clk_put(omap->usbhost_p1_fck); + clk_put(omap->xclk60mhsp2_ck); + clk_put(omap->utmi_p2_fck); + clk_put(omap->xclk60mhsp1_ck); + clk_put(omap->utmi_p1_fck); + clk_put(omap->ehci_logic_fck); + pm_runtime_disable(&pdev->dev); + kfree(omap); + + return 0; } -EXPORT_SYMBOL_GPL(omap_usbhs_disable); + +static const struct dev_pm_ops usbhsomap_dev_pm_ops = { + .runtime_suspend = usbhs_runtime_suspend, + .runtime_resume = usbhs_runtime_resume, +}; static struct platform_driver usbhs_omap_driver = { .driver = { .name = (char *)usbhs_driver_name, .owner = THIS_MODULE, + .pm = &usbhsomap_dev_pm_ops, }, .remove = __exit_p(usbhs_omap_remove), }; diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index a1cb21f95302..1e0e27cbe987 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1606,6 +1606,14 @@ static const struct mmc_fixup blk_fixups[] = MMC_QUIRK_BLK_NO_CMD23), MMC_FIXUP("MMC32G", 0x11, CID_OEMID_ANY, add_quirk_mmc, MMC_QUIRK_BLK_NO_CMD23), + + /* + * Some Micron MMC cards needs longer data read timeout than + * indicated in CSD. + */ + MMC_FIXUP(CID_NAME_ANY, 0x13, 0x200, add_quirk_mmc, + MMC_QUIRK_LONG_READ_TIME), + END_FIXUP }; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 5278ffb20e74..950b97d7412a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -529,6 +529,18 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) data->timeout_clks = 0; } } + + /* + * Some cards require longer data read timeout than indicated in CSD. + * Address this by setting the read timeout to a "reasonably high" + * value. For the cards tested, 300ms has proven enough. If necessary, + * this value can be increased if other problematic cards require this. + */ + if (mmc_card_long_read_time(card) && data->flags & MMC_DATA_READ) { + data->timeout_ns = 300000000; + data->timeout_clks = 0; + } + /* * Some cards need very high timeouts if driven in SPI mode. * The worst observed timeout was 900ms after writing a @@ -1213,6 +1225,46 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) mmc_host_clk_release(host); } +static void mmc_poweroff_notify(struct mmc_host *host) +{ + struct mmc_card *card; + unsigned int timeout; + unsigned int notify_type = EXT_CSD_NO_POWER_NOTIFICATION; + int err = 0; + + card = host->card; + + /* + * Send power notify command only if card + * is mmc and notify state is powered ON + */ + if (card && mmc_card_mmc(card) && + (card->poweroff_notify_state == MMC_POWERED_ON)) { + + if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) { + notify_type = EXT_CSD_POWER_OFF_SHORT; + timeout = card->ext_csd.generic_cmd6_time; + card->poweroff_notify_state = MMC_POWEROFF_SHORT; + } else { + notify_type = EXT_CSD_POWER_OFF_LONG; + timeout = card->ext_csd.power_off_longtime; + card->poweroff_notify_state = MMC_POWEROFF_LONG; + } + + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_POWER_OFF_NOTIFICATION, + notify_type, timeout); + + if (err && err != -EBADMSG) + pr_err("Device failed to respond within %d poweroff " + "time. Forcefully powering down the device\n", + timeout); + + /* Set the card state to no notification after the poweroff */ + card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; + } +} + /* * Apply power to the MMC stack. This is a two-stage process. * First, we enable power to the card without the clock running. @@ -1269,42 +1321,12 @@ static void mmc_power_up(struct mmc_host *host) void mmc_power_off(struct mmc_host *host) { - struct mmc_card *card; - unsigned int notify_type; - unsigned int timeout; - int err; - mmc_host_clk_hold(host); - card = host->card; host->ios.clock = 0; host->ios.vdd = 0; - if (card && mmc_card_mmc(card) && - (card->poweroff_notify_state == MMC_POWERED_ON)) { - - if (host->power_notify_type == MMC_HOST_PW_NOTIFY_SHORT) { - notify_type = EXT_CSD_POWER_OFF_SHORT; - timeout = card->ext_csd.generic_cmd6_time; - card->poweroff_notify_state = MMC_POWEROFF_SHORT; - } else { - notify_type = EXT_CSD_POWER_OFF_LONG; - timeout = card->ext_csd.power_off_longtime; - card->poweroff_notify_state = MMC_POWEROFF_LONG; - } - - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_POWER_OFF_NOTIFICATION, - notify_type, timeout); - - if (err && err != -EBADMSG) - pr_err("Device failed to respond within %d poweroff " - "time. Forcefully powering down the device\n", - timeout); - - /* Set the card state to no notification after the poweroff */ - card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; - } + mmc_poweroff_notify(host); /* * Reset ocr mask to be the highest possible voltage supported for @@ -2196,7 +2218,7 @@ int mmc_card_sleep(struct mmc_host *host) mmc_bus_get(host); - if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) + if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep) err = host->bus_ops->sleep(host); mmc_bus_put(host); @@ -2302,8 +2324,17 @@ int mmc_suspend_host(struct mmc_host *host) * pre-claim the host. */ if (mmc_try_claim_host(host)) { - if (host->bus_ops->suspend) + if (host->bus_ops->suspend) { + /* + * For eMMC 4.5 device send notify command + * before sleep, because in sleep state eMMC 4.5 + * devices respond to only RESET and AWAKE cmd + */ + mmc_poweroff_notify(host); err = host->bus_ops->suspend(host); + } + mmc_do_release_host(host); + if (err == -ENOSYS || !host->bus_ops->resume) { /* * We simply "remove" the card in this case. @@ -2318,7 +2349,6 @@ int mmc_suspend_host(struct mmc_host *host) host->pm_flags = 0; err = 0; } - mmc_do_release_host(host); } else { err = -EBUSY; } diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index dbf421a6279c..d240427c1246 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -876,17 +876,21 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * set the notification byte in the ext_csd register of device */ if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) && - (card->poweroff_notify_state == MMC_NO_POWER_NOTIFICATION)) { + (card->ext_csd.rev >= 6)) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, EXT_CSD_POWER_ON, card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) goto free_card; - } - if (!err) - card->poweroff_notify_state = MMC_POWERED_ON; + /* + * The err can be -EBADMSG or 0, + * so check for success and update the flag + */ + if (!err) + card->poweroff_notify_state = MMC_POWERED_ON; + } /* * Activate high speed (if supported) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 325ea61e12d3..8e0fbe994047 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -732,6 +732,7 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) "failed to config DMA channel. Falling back to PIO\n"); dma_release_channel(host->dma); host->do_dma = 0; + host->dma = NULL; } } diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 101cd31c8220..d1fb561e089d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1010,6 +1010,7 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) host->data->sg_len, omap_hsmmc_get_dma_dir(host, host->data)); omap_free_dma(dma_ch); + host->data->host_cookie = 0; } host->data = NULL; } @@ -1575,8 +1576,10 @@ static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, struct mmc_data *data = mrq->data; if (host->use_dma) { - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - omap_hsmmc_get_dma_dir(host, data)); + if (data->host_cookie) + dma_unmap_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); data->host_cookie = 0; } } @@ -1988,6 +1991,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) if (mmc_slot(host).nonremovable) mmc->caps |= MMC_CAP_NONREMOVABLE; + mmc->pm_caps = mmc_slot(host).pm_caps; + omap_hsmmc_conf_bus_power(host); /* Select DMA lines */ @@ -2176,13 +2181,7 @@ static int omap_hsmmc_suspend(struct device *dev) cancel_work_sync(&host->mmc_carddetect_work); ret = mmc_suspend_host(host->mmc); - if (ret == 0) { - omap_hsmmc_disable_irq(host); - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); - if (host->got_dbclk) - clk_disable(host->dbclk); - } else { + if (ret) { host->suspended = 0; if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, @@ -2191,9 +2190,20 @@ static int omap_hsmmc_suspend(struct device *dev) dev_dbg(mmc_dev(host->mmc), "Unmask interrupt failed\n"); } + goto err; } - pm_runtime_put_sync(host->dev); + + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { + omap_hsmmc_disable_irq(host); + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); + } + if (host->got_dbclk) + clk_disable(host->dbclk); + } +err: + pm_runtime_put_sync(host->dev); return ret; } @@ -2213,7 +2223,8 @@ static int omap_hsmmc_resume(struct device *dev) if (host->got_dbclk) clk_enable(host->dbclk); - omap_hsmmc_conf_bus_power(host); + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) + omap_hsmmc_conf_bus_power(host); if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, host->slot_id); diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 4b920b7621cf..87b6f079b6e0 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c @@ -15,6 +15,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/mmc/host.h> +#include <linux/module.h> #include <mach/cns3xxx.h> #include "sdhci-pltfm.h" diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 3d00e722efc9..6b3f3664edeb 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -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; } @@ -644,8 +641,6 @@ static int sdhci_s3c_resume(struct platform_device *dev) static struct platform_driver sdhci_s3c_driver = { .probe = sdhci_s3c_probe, .remove = __devexit_p(sdhci_s3c_remove), - .suspend = sdhci_s3c_suspend, - .resume = sdhci_s3c_resume, .driver = { .owner = THIS_MODULE, .name = "s3c-sdhci", diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 369366c8e205..d5505f3fe2a1 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -908,7 +908,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->power) { pm_runtime_put(&host->pd->dev); host->power = false; - if (p->down_pwr) + if (p->down_pwr && ios->power_mode == MMC_POWER_OFF) p->down_pwr(host->pd); } host->state = STATE_IDLE; diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index d85a60cda167..4208b3958069 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -798,7 +798,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* start bus clock */ tmio_mmc_clk_start(host); } else if (ios->power_mode != MMC_POWER_UP) { - if (host->set_pwr) + if (host->set_pwr && ios->power_mode == MMC_POWER_OFF) host->set_pwr(host->pdev, 0); if ((pdata->flags & TMIO_MMC_HAS_COLD_CD) && pdata->power) { diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index be5dde040261..94b7f287d6c5 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ obj-$(CONFIG_NET_VENDOR_AMD) += amd/ obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ -obj-$(CONFIG_NET_ATMEL) += cadence/ +obj-$(CONFIG_NET_CADENCE) += cadence/ obj-$(CONFIG_NET_BFIN) += adi/ obj-$(CONFIG_NET_VENDOR_BROADCOM) += broadcom/ obj-$(CONFIG_NET_VENDOR_BROCADE) += brocade/ diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index b48378a41e49..db931916da08 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig @@ -5,8 +5,8 @@ config HAVE_NET_MACB bool -config NET_ATMEL - bool "Atmel devices" +config NET_CADENCE + bool "Cadence devices" default y depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200) ---help--- @@ -21,7 +21,7 @@ config NET_ATMEL the remaining Atmel network card questions. If you say Y, you will be asked for your specific card in the following questions. -if NET_ATMEL +if NET_CADENCE config ARM_AT91_ETHER tristate "AT91RM9200 Ethernet support" @@ -33,14 +33,16 @@ config ARM_AT91_ETHER ethernet support, then you should always answer Y to this. config MACB - tristate "Atmel MACB support" + tristate "Cadence MACB/GEM support" depends on HAVE_NET_MACB select PHYLIB ---help--- - The Atmel MACB ethernet interface is found on many AT32 and AT91 - parts. Say Y to include support for the MACB chip. + The Cadence MACB ethernet interface is found on many Atmel AT32 and + AT91 parts. This driver also supports the Cadence GEM (Gigabit + Ethernet MAC found in some ARM SoC devices). Note: the Gigabit mode + is not yet supported. Say Y to include support for the MACB/GEM chip. To compile this driver as a module, choose M here: the module will be called macb. -endif # NET_ATMEL +endif # NET_CADENCE diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c index 56624d303487..1a5b6efa0120 100644 --- a/drivers/net/ethernet/cadence/at91_ether.c +++ b/drivers/net/ethernet/cadence/at91_ether.c @@ -26,6 +26,7 @@ #include <linux/skbuff.h> #include <linux/dma-mapping.h> #include <linux/ethtool.h> +#include <linux/platform_data/macb.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/gfp.h> @@ -255,8 +256,7 @@ static void enable_phyirq(struct net_device *dev) unsigned int dsintr, irq_number; int status; - irq_number = lp->board_data.phy_irq_pin; - if (!irq_number) { + if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { /* * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), * or board does not have it connected. @@ -265,6 +265,7 @@ static void enable_phyirq(struct net_device *dev) return; } + irq_number = lp->board_data.phy_irq_pin; status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev); if (status) { printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status); @@ -319,8 +320,7 @@ static void disable_phyirq(struct net_device *dev) unsigned int dsintr; unsigned int irq_number; - irq_number = lp->board_data.phy_irq_pin; - if (!irq_number) { + if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { del_timer_sync(&lp->check_timer); return; } @@ -365,6 +365,7 @@ static void disable_phyirq(struct net_device *dev) disable_mdi(); spin_unlock_irq(&lp->lock); + irq_number = lp->board_data.phy_irq_pin; free_irq(irq_number, dev); /* Free interrupt handler */ } @@ -984,7 +985,7 @@ static const struct net_device_ops at91ether_netdev_ops = { static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev, struct clk *ether_clk) { - struct at91_eth_data *board_data = pdev->dev.platform_data; + struct macb_platform_data *board_data = pdev->dev.platform_data; struct net_device *dev; struct at91_private *lp; unsigned int val; @@ -1077,7 +1078,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add netif_carrier_off(dev); /* will be enabled in open() */ /* If board has no PHY IRQ, use a timer to poll the PHY */ - if (!lp->board_data.phy_irq_pin) { + if (!gpio_is_valid(lp->board_data.phy_irq_pin)) { init_timer(&lp->check_timer); lp->check_timer.data = (unsigned long)dev; lp->check_timer.function = at91ether_check_link; @@ -1169,7 +1170,8 @@ static int __devexit at91ether_remove(struct platform_device *pdev) struct net_device *dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(dev); - if (lp->board_data.phy_irq_pin >= 32) + if (gpio_is_valid(lp->board_data.phy_irq_pin) && + lp->board_data.phy_irq_pin >= 32) gpio_free(lp->board_data.phy_irq_pin); unregister_netdev(dev); @@ -1188,11 +1190,12 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) { struct net_device *net_dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(net_dev); - int phy_irq = lp->board_data.phy_irq_pin; if (netif_running(net_dev)) { - if (phy_irq) + if (gpio_is_valid(lp->board_data.phy_irq_pin)) { + int phy_irq = lp->board_data.phy_irq_pin; disable_irq(phy_irq); + } netif_stop_queue(net_dev); netif_device_detach(net_dev); @@ -1206,7 +1209,6 @@ static int at91ether_resume(struct platform_device *pdev) { struct net_device *net_dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(net_dev); - int phy_irq = lp->board_data.phy_irq_pin; if (netif_running(net_dev)) { clk_enable(lp->ether_clk); @@ -1214,8 +1216,10 @@ static int at91ether_resume(struct platform_device *pdev) netif_device_attach(net_dev); netif_start_queue(net_dev); - if (phy_irq) + if (gpio_is_valid(lp->board_data.phy_irq_pin)) { + int phy_irq = lp->board_data.phy_irq_pin; enable_irq(phy_irq); + } } return 0; } diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h index 353f4dab62be..3725fbb0defe 100644 --- a/drivers/net/ethernet/cadence/at91_ether.h +++ b/drivers/net/ethernet/cadence/at91_ether.h @@ -85,7 +85,9 @@ struct recv_desc_bufs struct at91_private { struct mii_if_info mii; /* ethtool support */ - struct at91_eth_data board_data; /* board-specific configuration */ + struct macb_platform_data board_data; /* board-specific + * configuration (shared with + * macb for common data */ struct clk *ether_clk; /* clock */ /* PHY */ diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index a437b46e5490..f3d5c65d99cf 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1,5 +1,5 @@ /* - * Atmel MACB Ethernet Controller driver + * Cadence MACB/GEM Ethernet Controller driver * * Copyright (C) 2004-2006 Atmel Corporation * @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/clk.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -19,11 +20,12 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/dma-mapping.h> +#include <linux/platform_data/macb.h> #include <linux/platform_device.h> #include <linux/phy.h> - -#include <mach/board.h> -#include <mach/cpu.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_net.h> #include "macb.h" @@ -60,9 +62,9 @@ static void __macb_set_hwaddr(struct macb *bp) u16 top; bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); - macb_writel(bp, SA1B, bottom); + macb_or_gem_writel(bp, SA1B, bottom); top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); - macb_writel(bp, SA1T, top); + macb_or_gem_writel(bp, SA1T, top); } static void __init macb_get_hwaddr(struct macb *bp) @@ -71,8 +73,8 @@ static void __init macb_get_hwaddr(struct macb *bp) u16 top; u8 addr[6]; - bottom = macb_readl(bp, SA1B); - top = macb_readl(bp, SA1T); + bottom = macb_or_gem_readl(bp, SA1B); + top = macb_or_gem_readl(bp, SA1T); addr[0] = bottom & 0xff; addr[1] = (bottom >> 8) & 0xff; @@ -84,7 +86,7 @@ static void __init macb_get_hwaddr(struct macb *bp) if (is_valid_ether_addr(addr)) { memcpy(bp->dev->dev_addr, addr, sizeof(addr)); } else { - dev_info(&bp->pdev->dev, "invalid hw address, using random\n"); + netdev_info(bp->dev, "invalid hw address, using random\n"); random_ether_addr(bp->dev->dev_addr); } } @@ -178,11 +180,12 @@ static void macb_handle_link_change(struct net_device *dev) if (status_change) { if (phydev->link) - printk(KERN_INFO "%s: link up (%d/%s)\n", - dev->name, phydev->speed, - DUPLEX_FULL == phydev->duplex ? "Full":"Half"); + netdev_info(dev, "link up (%d/%s)\n", + phydev->speed, + phydev->duplex == DUPLEX_FULL ? + "Full" : "Half"); else - printk(KERN_INFO "%s: link down\n", dev->name); + netdev_info(dev, "link down\n"); } } @@ -191,25 +194,21 @@ static int macb_mii_probe(struct net_device *dev) { struct macb *bp = netdev_priv(dev); struct phy_device *phydev; - struct eth_platform_data *pdata; int ret; phydev = phy_find_first(bp->mii_bus); if (!phydev) { - printk (KERN_ERR "%s: no PHY found\n", dev->name); + netdev_err(dev, "no PHY found\n"); return -1; } - pdata = bp->pdev->dev.platform_data; /* TODO : add pin_irq */ /* attach the mac to the phy */ ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0, - pdata && pdata->is_rmii ? - PHY_INTERFACE_MODE_RMII : - PHY_INTERFACE_MODE_MII); + bp->phy_interface); if (ret) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + netdev_err(dev, "Could not attach to PHY\n"); return ret; } @@ -228,7 +227,7 @@ static int macb_mii_probe(struct net_device *dev) static int macb_mii_init(struct macb *bp) { - struct eth_platform_data *pdata; + struct macb_platform_data *pdata; int err = -ENXIO, i; /* Enable management port */ @@ -285,8 +284,8 @@ err_out: static void macb_update_stats(struct macb *bp) { u32 __iomem *reg = bp->regs + MACB_PFR; - u32 *p = &bp->hw_stats.rx_pause_frames; - u32 *end = &bp->hw_stats.tx_pause_frames + 1; + u32 *p = &bp->hw_stats.macb.rx_pause_frames; + u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1; WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); @@ -303,14 +302,13 @@ static void macb_tx(struct macb *bp) status = macb_readl(bp, TSR); macb_writel(bp, TSR, status); - dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n", - (unsigned long)status); + netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status); if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) { int i; - printk(KERN_ERR "%s: TX %s, resetting buffers\n", - bp->dev->name, status & MACB_BIT(UND) ? - "underrun" : "retry limit exceeded"); + netdev_err(bp->dev, "TX %s, resetting buffers\n", + status & MACB_BIT(UND) ? + "underrun" : "retry limit exceeded"); /* Transfer ongoing, disable transmitter, to avoid confusion */ if (status & MACB_BIT(TGO)) @@ -369,8 +367,8 @@ static void macb_tx(struct macb *bp) if (!(bufstat & MACB_BIT(TX_USED))) break; - dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n", - tail, skb->data); + netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n", + tail, skb->data); dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, DMA_TO_DEVICE); bp->stats.tx_packets++; @@ -395,8 +393,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl); - dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n", - first_frag, last_frag, len); + netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n", + first_frag, last_frag, len); skb = dev_alloc_skb(len + RX_OFFSET); if (!skb) { @@ -437,8 +435,8 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, bp->stats.rx_packets++; bp->stats.rx_bytes += len; - dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n", - skb->len, skb->csum); + netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n", + skb->len, skb->csum); netif_receive_skb(skb); return 0; @@ -515,8 +513,8 @@ static int macb_poll(struct napi_struct *napi, int budget) work_done = 0; - dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n", - (unsigned long)status, budget); + netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n", + (unsigned long)status, budget); work_done = macb_rx(bp, budget); if (work_done < budget) { @@ -565,8 +563,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) macb_writel(bp, IDR, MACB_RX_INT_FLAGS); if (napi_schedule_prep(&bp->napi)) { - dev_dbg(&bp->pdev->dev, - "scheduling RX softirq\n"); + netdev_dbg(bp->dev, "scheduling RX softirq\n"); __napi_schedule(&bp->napi); } } @@ -582,16 +579,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (status & MACB_BIT(ISR_ROVR)) { /* We missed at least one packet */ - bp->hw_stats.rx_overruns++; + if (macb_is_gem(bp)) + bp->hw_stats.gem.rx_overruns++; + else + bp->hw_stats.macb.rx_overruns++; } if (status & MACB_BIT(HRESP)) { /* - * TODO: Reset the hardware, and maybe move the printk - * to a lower-priority context as well (work queue?) + * TODO: Reset the hardware, and maybe move the + * netdev_err to a lower-priority context as well + * (work queue?) */ - printk(KERN_ERR "%s: DMA bus error: HRESP not OK\n", - dev->name); + netdev_err(dev, "DMA bus error: HRESP not OK\n"); } status = macb_readl(bp, ISR); @@ -626,16 +626,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; #ifdef DEBUG - int i; - dev_dbg(&bp->pdev->dev, - "start_xmit: len %u head %p data %p tail %p end %p\n", - skb->len, skb->head, skb->data, - skb_tail_pointer(skb), skb_end_pointer(skb)); - dev_dbg(&bp->pdev->dev, - "data:"); - for (i = 0; i < 16; i++) - printk(" %02x", (unsigned int)skb->data[i]); - printk("\n"); + netdev_dbg(bp->dev, + "start_xmit: len %u head %p data %p tail %p end %p\n", + skb->len, skb->head, skb->data, + skb_tail_pointer(skb), skb_end_pointer(skb)); + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, 16, true); #endif len = skb->len; @@ -645,21 +641,20 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) if (TX_BUFFS_AVAIL(bp) < 1) { netif_stop_queue(dev); spin_unlock_irqrestore(&bp->lock, flags); - dev_err(&bp->pdev->dev, - "BUG! Tx Ring full when queue awake!\n"); - dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n", - bp->tx_head, bp->tx_tail); + netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n"); + netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n", + bp->tx_head, bp->tx_tail); return NETDEV_TX_BUSY; } entry = bp->tx_head; - dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry); + netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry); mapping = dma_map_single(&bp->pdev->dev, skb->data, len, DMA_TO_DEVICE); bp->tx_skb[entry].skb = skb; bp->tx_skb[entry].mapping = mapping; - dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n", - skb->data, (unsigned long)mapping); + netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n", + skb->data, (unsigned long)mapping); ctrl = MACB_BF(TX_FRMLEN, len); ctrl |= MACB_BIT(TX_LAST); @@ -723,27 +718,27 @@ static int macb_alloc_consistent(struct macb *bp) &bp->rx_ring_dma, GFP_KERNEL); if (!bp->rx_ring) goto out_err; - dev_dbg(&bp->pdev->dev, - "Allocated RX ring of %d bytes at %08lx (mapped %p)\n", - size, (unsigned long)bp->rx_ring_dma, bp->rx_ring); + netdev_dbg(bp->dev, + "Allocated RX ring of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_ring_dma, bp->rx_ring); size = TX_RING_BYTES; bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size, &bp->tx_ring_dma, GFP_KERNEL); if (!bp->tx_ring) goto out_err; - dev_dbg(&bp->pdev->dev, - "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", - size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); + netdev_dbg(bp->dev, + "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); size = RX_RING_SIZE * RX_BUFFER_SIZE; bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, &bp->rx_buffers_dma, GFP_KERNEL); if (!bp->rx_buffers) goto out_err; - dev_dbg(&bp->pdev->dev, - "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", - size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); + netdev_dbg(bp->dev, + "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); return 0; @@ -797,6 +792,84 @@ static void macb_reset_hw(struct macb *bp) macb_readl(bp, ISR); } +static u32 gem_mdc_clk_div(struct macb *bp) +{ + u32 config; + unsigned long pclk_hz = clk_get_rate(bp->pclk); + + if (pclk_hz <= 20000000) + config = GEM_BF(CLK, GEM_CLK_DIV8); + else if (pclk_hz <= 40000000) + config = GEM_BF(CLK, GEM_CLK_DIV16); + else if (pclk_hz <= 80000000) + config = GEM_BF(CLK, GEM_CLK_DIV32); + else if (pclk_hz <= 120000000) + config = GEM_BF(CLK, GEM_CLK_DIV48); + else if (pclk_hz <= 160000000) + config = GEM_BF(CLK, GEM_CLK_DIV64); + else + config = GEM_BF(CLK, GEM_CLK_DIV96); + + return config; +} + +static u32 macb_mdc_clk_div(struct macb *bp) +{ + u32 config; + unsigned long pclk_hz; + + if (macb_is_gem(bp)) + return gem_mdc_clk_div(bp); + + pclk_hz = clk_get_rate(bp->pclk); + if (pclk_hz <= 20000000) + config = MACB_BF(CLK, MACB_CLK_DIV8); + else if (pclk_hz <= 40000000) + config = MACB_BF(CLK, MACB_CLK_DIV16); + else if (pclk_hz <= 80000000) + config = MACB_BF(CLK, MACB_CLK_DIV32); + else + config = MACB_BF(CLK, MACB_CLK_DIV64); + + return config; +} + +/* + * Get the DMA bus width field of the network configuration register that we + * should program. We find the width from decoding the design configuration + * register to find the maximum supported data bus width. + */ +static u32 macb_dbw(struct macb *bp) +{ + if (!macb_is_gem(bp)) + return 0; + + switch (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1))) { + case 4: + return GEM_BF(DBW, GEM_DBW128); + case 2: + return GEM_BF(DBW, GEM_DBW64); + case 1: + default: + return GEM_BF(DBW, GEM_DBW32); + } +} + +/* + * Configure the receive DMA engine to use the correct receive buffer size. + * This is a configurable parameter for GEM. + */ +static void macb_configure_dma(struct macb *bp) +{ + u32 dmacfg; + + if (macb_is_gem(bp)) { + dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L); + dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64); + gem_writel(bp, DMACFG, dmacfg); + } +} + static void macb_init_hw(struct macb *bp) { u32 config; @@ -804,7 +877,7 @@ static void macb_init_hw(struct macb *bp) macb_reset_hw(bp); __macb_set_hwaddr(bp); - config = macb_readl(bp, NCFGR) & MACB_BF(CLK, -1L); + config = macb_mdc_clk_div(bp); config |= MACB_BIT(PAE); /* PAuse Enable */ config |= MACB_BIT(DRFCS); /* Discard Rx FCS */ config |= MACB_BIT(BIG); /* Receive oversized frames */ @@ -812,8 +885,11 @@ static void macb_init_hw(struct macb *bp) config |= MACB_BIT(CAF); /* Copy All Frames */ if (!(bp->dev->flags & IFF_BROADCAST)) config |= MACB_BIT(NBC); /* No BroadCast */ + config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); + macb_configure_dma(bp); + /* Initialize TX and RX buffers */ macb_writel(bp, RBQP, bp->rx_ring_dma); macb_writel(bp, TBQP, bp->tx_ring_dma); @@ -909,8 +985,8 @@ static void macb_sethashtable(struct net_device *dev) mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); } - macb_writel(bp, HRB, mc_filter[0]); - macb_writel(bp, HRT, mc_filter[1]); + macb_or_gem_writel(bp, HRB, mc_filter[0]); + macb_or_gem_writel(bp, HRT, mc_filter[1]); } /* @@ -932,8 +1008,8 @@ static void macb_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_ALLMULTI) { /* Enable all multicast mode */ - macb_writel(bp, HRB, -1); - macb_writel(bp, HRT, -1); + macb_or_gem_writel(bp, HRB, -1); + macb_or_gem_writel(bp, HRT, -1); cfg |= MACB_BIT(NCFGR_MTI); } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */ @@ -941,8 +1017,8 @@ static void macb_set_rx_mode(struct net_device *dev) cfg |= MACB_BIT(NCFGR_MTI); } else if (dev->flags & (~IFF_ALLMULTI)) { /* Disable all multicast mode */ - macb_writel(bp, HRB, 0); - macb_writel(bp, HRT, 0); + macb_or_gem_writel(bp, HRB, 0); + macb_or_gem_writel(bp, HRT, 0); cfg &= ~MACB_BIT(NCFGR_MTI); } @@ -954,7 +1030,7 @@ static int macb_open(struct net_device *dev) struct macb *bp = netdev_priv(dev); int err; - dev_dbg(&bp->pdev->dev, "open\n"); + netdev_dbg(bp->dev, "open\n"); /* if the phy is not yet register, retry later*/ if (!bp->phy_dev) @@ -965,9 +1041,8 @@ static int macb_open(struct net_device *dev) err = macb_alloc_consistent(bp); if (err) { - printk(KERN_ERR - "%s: Unable to allocate DMA memory (error %d)\n", - dev->name, err); + netdev_err(dev, "Unable to allocate DMA memory (error %d)\n", + err); return err; } @@ -1005,11 +1080,62 @@ static int macb_close(struct net_device *dev) return 0; } +static void gem_update_stats(struct macb *bp) +{ + u32 __iomem *reg = bp->regs + GEM_OTX; + u32 *p = &bp->hw_stats.gem.tx_octets_31_0; + u32 *end = &bp->hw_stats.gem.rx_udp_checksum_errors + 1; + + for (; p < end; p++, reg++) + *p += __raw_readl(reg); +} + +static struct net_device_stats *gem_get_stats(struct macb *bp) +{ + struct gem_stats *hwstat = &bp->hw_stats.gem; + struct net_device_stats *nstat = &bp->stats; + + gem_update_stats(bp); + + nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors + + hwstat->rx_alignment_errors + + hwstat->rx_resource_errors + + hwstat->rx_overruns + + hwstat->rx_oversize_frames + + hwstat->rx_jabbers + + hwstat->rx_undersized_frames + + hwstat->rx_length_field_frame_errors); + nstat->tx_errors = (hwstat->tx_late_collisions + + hwstat->tx_excessive_collisions + + hwstat->tx_underrun + + hwstat->tx_carrier_sense_errors); + nstat->multicast = hwstat->rx_multicast_frames; + nstat->collisions = (hwstat->tx_single_collision_frames + + hwstat->tx_multiple_collision_frames + + hwstat->tx_excessive_collisions); + nstat->rx_length_errors = (hwstat->rx_oversize_frames + + hwstat->rx_jabbers + + hwstat->rx_undersized_frames + + hwstat->rx_length_field_frame_errors); + nstat->rx_over_errors = hwstat->rx_resource_errors; + nstat->rx_crc_errors = hwstat->rx_frame_check_sequence_errors; + nstat->rx_frame_errors = hwstat->rx_alignment_errors; + nstat->rx_fifo_errors = hwstat->rx_overruns; + nstat->tx_aborted_errors = hwstat->tx_excessive_collisions; + nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors; + nstat->tx_fifo_errors = hwstat->tx_underrun; + + return nstat; +} + static struct net_device_stats *macb_get_stats(struct net_device *dev) { struct macb *bp = netdev_priv(dev); struct net_device_stats *nstat = &bp->stats; - struct macb_stats *hwstat = &bp->hw_stats; + struct macb_stats *hwstat = &bp->hw_stats.macb; + + if (macb_is_gem(bp)) + return gem_get_stats(bp); /* read stats from hardware */ macb_update_stats(bp); @@ -1117,14 +1243,59 @@ static const struct net_device_ops macb_netdev_ops = { #endif }; +#if defined(CONFIG_OF) +static const struct of_device_id macb_dt_ids[] = { + { .compatible = "cdns,at32ap7000-macb" }, + { .compatible = "cdns,at91sam9260-macb" }, + { .compatible = "cdns,macb" }, + { .compatible = "cdns,pc302-gem" }, + { .compatible = "cdns,gem" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, macb_dt_ids); + +static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + + if (np) + return of_get_phy_mode(np); + + return -ENODEV; +} + +static int __devinit macb_get_hwaddr_dt(struct macb *bp) +{ + struct device_node *np = bp->pdev->dev.of_node; + if (np) { + const char *mac = of_get_mac_address(np); + if (mac) { + memcpy(bp->dev->dev_addr, mac, ETH_ALEN); + return 0; + } + } + + return -ENODEV; +} +#else +static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev) +{ + return -ENODEV; +} +static int __devinit macb_get_hwaddr_dt(struct macb *bp) +{ + return -ENODEV; +} +#endif + static int __init macb_probe(struct platform_device *pdev) { - struct eth_platform_data *pdata; + struct macb_platform_data *pdata; struct resource *regs; struct net_device *dev; struct macb *bp; struct phy_device *phydev; - unsigned long pclk_hz; u32 config; int err = -ENXIO; @@ -1152,28 +1323,19 @@ static int __init macb_probe(struct platform_device *pdev) spin_lock_init(&bp->lock); -#if defined(CONFIG_ARCH_AT91) - bp->pclk = clk_get(&pdev->dev, "macb_clk"); + bp->pclk = clk_get(&pdev->dev, "pclk"); if (IS_ERR(bp->pclk)) { dev_err(&pdev->dev, "failed to get macb_clk\n"); goto err_out_free_dev; } clk_enable(bp->pclk); -#else - bp->pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(bp->pclk)) { - dev_err(&pdev->dev, "failed to get pclk\n"); - goto err_out_free_dev; - } + bp->hclk = clk_get(&pdev->dev, "hclk"); if (IS_ERR(bp->hclk)) { dev_err(&pdev->dev, "failed to get hclk\n"); goto err_out_put_pclk; } - - clk_enable(bp->pclk); clk_enable(bp->hclk); -#endif bp->regs = ioremap(regs->start, resource_size(regs)); if (!bp->regs) { @@ -1185,9 +1347,8 @@ static int __init macb_probe(struct platform_device *pdev) dev->irq = platform_get_irq(pdev, 0); err = request_irq(dev->irq, macb_interrupt, 0, dev->name, dev); if (err) { - printk(KERN_ERR - "%s: Unable to request IRQ %d (error %d)\n", - dev->name, dev->irq, err); + dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", + dev->irq, err); goto err_out_iounmap; } @@ -1198,31 +1359,37 @@ static int __init macb_probe(struct platform_device *pdev) dev->base_addr = regs->start; /* Set MII management clock divider */ - pclk_hz = clk_get_rate(bp->pclk); - if (pclk_hz <= 20000000) - config = MACB_BF(CLK, MACB_CLK_DIV8); - else if (pclk_hz <= 40000000) - config = MACB_BF(CLK, MACB_CLK_DIV16); - else if (pclk_hz <= 80000000) - config = MACB_BF(CLK, MACB_CLK_DIV32); - else - config = MACB_BF(CLK, MACB_CLK_DIV64); + config = macb_mdc_clk_div(bp); + config |= macb_dbw(bp); macb_writel(bp, NCFGR, config); - macb_get_hwaddr(bp); - pdata = pdev->dev.platform_data; + err = macb_get_hwaddr_dt(bp); + if (err < 0) + macb_get_hwaddr(bp); + + err = macb_get_phy_mode_dt(pdev); + if (err < 0) { + pdata = pdev->dev.platform_data; + if (pdata && pdata->is_rmii) + bp->phy_interface = PHY_INTERFACE_MODE_RMII; + else + bp->phy_interface = PHY_INTERFACE_MODE_MII; + } else { + bp->phy_interface = err; + } - if (pdata && pdata->is_rmii) + if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) #if defined(CONFIG_ARCH_AT91) - macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) ); + macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) | + MACB_BIT(CLKEN))); #else - macb_writel(bp, USRIO, 0); + macb_or_gem_writel(bp, USRIO, 0); #endif else #if defined(CONFIG_ARCH_AT91) - macb_writel(bp, USRIO, MACB_BIT(CLKEN)); + macb_or_gem_writel(bp, USRIO, MACB_BIT(CLKEN)); #else - macb_writel(bp, USRIO, MACB_BIT(MII)); + macb_or_gem_writel(bp, USRIO, MACB_BIT(MII)); #endif bp->tx_pending = DEF_TX_RING_PENDING; @@ -1239,13 +1406,13 @@ static int __init macb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d (%pM)\n", - dev->name, dev->base_addr, dev->irq, dev->dev_addr); + netdev_info(dev, "Cadence %s at 0x%08lx irq %d (%pM)\n", + macb_is_gem(bp) ? "GEM" : "MACB", dev->base_addr, + dev->irq, dev->dev_addr); phydev = bp->phy_dev; - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, - phydev->drv->name, dev_name(&phydev->dev), phydev->irq); + netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; @@ -1256,14 +1423,10 @@ err_out_free_irq: err_out_iounmap: iounmap(bp->regs); err_out_disable_clocks: -#ifndef CONFIG_ARCH_AT91 clk_disable(bp->hclk); clk_put(bp->hclk); -#endif clk_disable(bp->pclk); -#ifndef CONFIG_ARCH_AT91 err_out_put_pclk: -#endif clk_put(bp->pclk); err_out_free_dev: free_netdev(dev); @@ -1289,10 +1452,8 @@ static int __exit macb_remove(struct platform_device *pdev) unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(bp->regs); -#ifndef CONFIG_ARCH_AT91 clk_disable(bp->hclk); clk_put(bp->hclk); -#endif clk_disable(bp->pclk); clk_put(bp->pclk); free_netdev(dev); @@ -1310,9 +1471,7 @@ static int macb_suspend(struct platform_device *pdev, pm_message_t state) netif_device_detach(netdev); -#ifndef CONFIG_ARCH_AT91 clk_disable(bp->hclk); -#endif clk_disable(bp->pclk); return 0; @@ -1324,9 +1483,7 @@ static int macb_resume(struct platform_device *pdev) struct macb *bp = netdev_priv(netdev); clk_enable(bp->pclk); -#ifndef CONFIG_ARCH_AT91 clk_enable(bp->hclk); -#endif netif_device_attach(netdev); @@ -1344,6 +1501,7 @@ static struct platform_driver macb_driver = { .driver = { .name = "macb", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(macb_dt_ids), }, }; @@ -1361,6 +1519,6 @@ module_init(macb_init); module_exit(macb_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atmel MACB Ethernet driver"); +MODULE_DESCRIPTION("Cadence MACB/GEM Ethernet driver"); MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); MODULE_ALIAS("platform:macb"); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index d3212f6db703..335e288f5314 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -59,6 +59,24 @@ #define MACB_TPQ 0x00bc #define MACB_USRIO 0x00c0 #define MACB_WOL 0x00c4 +#define MACB_MID 0x00fc + +/* GEM register offsets. */ +#define GEM_NCFGR 0x0004 +#define GEM_USRIO 0x000c +#define GEM_DMACFG 0x0010 +#define GEM_HRB 0x0080 +#define GEM_HRT 0x0084 +#define GEM_SA1B 0x0088 +#define GEM_SA1T 0x008C +#define GEM_OTX 0x0100 +#define GEM_DCFG1 0x0280 +#define GEM_DCFG2 0x0284 +#define GEM_DCFG3 0x0288 +#define GEM_DCFG4 0x028c +#define GEM_DCFG5 0x0290 +#define GEM_DCFG6 0x0294 +#define GEM_DCFG7 0x0298 /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 @@ -126,6 +144,21 @@ #define MACB_IRXFCS_OFFSET 19 #define MACB_IRXFCS_SIZE 1 +/* GEM specific NCFGR bitfields. */ +#define GEM_CLK_OFFSET 18 +#define GEM_CLK_SIZE 3 +#define GEM_DBW_OFFSET 21 +#define GEM_DBW_SIZE 2 + +/* Constants for data bus width. */ +#define GEM_DBW32 0 +#define GEM_DBW64 1 +#define GEM_DBW128 2 + +/* Bitfields in DMACFG. */ +#define GEM_RXBS_OFFSET 16 +#define GEM_RXBS_SIZE 8 + /* Bitfields in NSR */ #define MACB_NSR_LINK_OFFSET 0 #define MACB_NSR_LINK_SIZE 1 @@ -228,12 +261,30 @@ #define MACB_WOL_MTI_OFFSET 19 #define MACB_WOL_MTI_SIZE 1 +/* Bitfields in MID */ +#define MACB_IDNUM_OFFSET 16 +#define MACB_IDNUM_SIZE 16 +#define MACB_REV_OFFSET 0 +#define MACB_REV_SIZE 16 + +/* Bitfields in DCFG1. */ +#define GEM_DBWDEF_OFFSET 25 +#define GEM_DBWDEF_SIZE 3 + /* Constants for CLK */ #define MACB_CLK_DIV8 0 #define MACB_CLK_DIV16 1 #define MACB_CLK_DIV32 2 #define MACB_CLK_DIV64 3 +/* GEM specific constants for CLK. */ +#define GEM_CLK_DIV8 0 +#define GEM_CLK_DIV16 1 +#define GEM_CLK_DIV32 2 +#define GEM_CLK_DIV48 3 +#define GEM_CLK_DIV64 4 +#define GEM_CLK_DIV96 5 + /* Constants for MAN register */ #define MACB_MAN_SOF 1 #define MACB_MAN_WRITE 1 @@ -254,11 +305,52 @@ << MACB_##name##_OFFSET)) \ | MACB_BF(name,value)) +#define GEM_BIT(name) \ + (1 << GEM_##name##_OFFSET) +#define GEM_BF(name, value) \ + (((value) & ((1 << GEM_##name##_SIZE) - 1)) \ + << GEM_##name##_OFFSET) +#define GEM_BFEXT(name, value)\ + (((value) >> GEM_##name##_OFFSET) \ + & ((1 << GEM_##name##_SIZE) - 1)) +#define GEM_BFINS(name, value, old) \ + (((old) & ~(((1 << GEM_##name##_SIZE) - 1) \ + << GEM_##name##_OFFSET)) \ + | GEM_BF(name, value)) + /* Register access macros */ #define macb_readl(port,reg) \ __raw_readl((port)->regs + MACB_##reg) #define macb_writel(port,reg,value) \ __raw_writel((value), (port)->regs + MACB_##reg) +#define gem_readl(port, reg) \ + __raw_readl((port)->regs + GEM_##reg) +#define gem_writel(port, reg, value) \ + __raw_writel((value), (port)->regs + GEM_##reg) + +/* + * Conditional GEM/MACB macros. These perform the operation to the correct + * register dependent on whether the device is a GEM or a MACB. For registers + * and bitfields that are common across both devices, use macb_{read,write}l + * to avoid the cost of the conditional. + */ +#define macb_or_gem_writel(__bp, __reg, __value) \ + ({ \ + if (macb_is_gem((__bp))) \ + gem_writel((__bp), __reg, __value); \ + else \ + macb_writel((__bp), __reg, __value); \ + }) + +#define macb_or_gem_readl(__bp, __reg) \ + ({ \ + u32 __v; \ + if (macb_is_gem((__bp))) \ + __v = gem_readl((__bp), __reg); \ + else \ + __v = macb_readl((__bp), __reg); \ + __v; \ + }) struct dma_desc { u32 addr; @@ -358,6 +450,54 @@ struct macb_stats { u32 tx_pause_frames; }; +struct gem_stats { + u32 tx_octets_31_0; + u32 tx_octets_47_32; + u32 tx_frames; + u32 tx_broadcast_frames; + u32 tx_multicast_frames; + u32 tx_pause_frames; + u32 tx_64_byte_frames; + u32 tx_65_127_byte_frames; + u32 tx_128_255_byte_frames; + u32 tx_256_511_byte_frames; + u32 tx_512_1023_byte_frames; + u32 tx_1024_1518_byte_frames; + u32 tx_greater_than_1518_byte_frames; + u32 tx_underrun; + u32 tx_single_collision_frames; + u32 tx_multiple_collision_frames; + u32 tx_excessive_collisions; + u32 tx_late_collisions; + u32 tx_deferred_frames; + u32 tx_carrier_sense_errors; + u32 rx_octets_31_0; + u32 rx_octets_47_32; + u32 rx_frames; + u32 rx_broadcast_frames; + u32 rx_multicast_frames; + u32 rx_pause_frames; + u32 rx_64_byte_frames; + u32 rx_65_127_byte_frames; + u32 rx_128_255_byte_frames; + u32 rx_256_511_byte_frames; + u32 rx_512_1023_byte_frames; + u32 rx_1024_1518_byte_frames; + u32 rx_greater_than_1518_byte_frames; + u32 rx_undersized_frames; + u32 rx_oversize_frames; + u32 rx_jabbers; + u32 rx_frame_check_sequence_errors; + u32 rx_length_field_frame_errors; + u32 rx_symbol_errors; + u32 rx_alignment_errors; + u32 rx_resource_errors; + u32 rx_overruns; + u32 rx_ip_header_checksum_errors; + u32 rx_tcp_checksum_errors; + u32 rx_udp_checksum_errors; +}; + struct macb { void __iomem *regs; @@ -376,7 +516,10 @@ struct macb { struct net_device *dev; struct napi_struct napi; struct net_device_stats stats; - struct macb_stats hw_stats; + union { + struct macb_stats macb; + struct gem_stats gem; + } hw_stats; dma_addr_t rx_ring_dma; dma_addr_t tx_ring_dma; @@ -389,6 +532,13 @@ struct macb { unsigned int link; unsigned int speed; unsigned int duplex; + + phy_interface_t phy_interface; }; +static inline bool macb_is_gem(struct macb *bp) +{ + return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2; +} + #endif /* _MACB_H */ diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 1124ce0a1594..c136230d50bb 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -232,6 +232,7 @@ struct fec_enet_private { struct platform_device *pdev; int opened; + int dev_id; /* Phylib and MDIO interface */ struct mii_bus *mii_bus; @@ -837,7 +838,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev) /* Adjust MAC if using macaddr */ if (iap == macaddr) - ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id; + ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id; } /* ------------------------------------------------------------------------- */ @@ -953,7 +954,7 @@ static int fec_enet_mii_probe(struct net_device *ndev) char mdio_bus_id[MII_BUS_ID_SIZE]; char phy_name[MII_BUS_ID_SIZE + 3]; int phy_id; - int dev_id = fep->pdev->id; + int dev_id = fep->dev_id; fep->phy_dev = NULL; @@ -1031,7 +1032,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) * mdio interface in board design, and need to be configured by * fec0 mii_bus. */ - if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id > 0) { + if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { /* fec1 uses fec0 mii_bus */ fep->mii_bus = fec0_mii_bus; return 0; @@ -1063,7 +1064,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1); + snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id + 1); fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; @@ -1521,6 +1522,7 @@ fec_probe(struct platform_device *pdev) int i, irq, ret = 0; struct resource *r; const struct of_device_id *of_id; + static int dev_id; of_id = of_match_device(fec_dt_ids, &pdev->dev); if (of_id) @@ -1548,6 +1550,7 @@ fec_probe(struct platform_device *pdev) fep->hwp = ioremap(r->start, resource_size(r)); fep->pdev = pdev; + fep->dev_id = dev_id++; if (!fep->hwp) { ret = -ENOMEM; diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 52f4e8ad48e7..4d9f84b8ab97 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -183,28 +183,10 @@ void fsl_pq_mdio_bus_name(char *name, struct device_node *np) } EXPORT_SYMBOL_GPL(fsl_pq_mdio_bus_name); -/* Scan the bus in reverse, looking for an empty spot */ -static int fsl_pq_mdio_find_free(struct mii_bus *new_bus) -{ - int i; - - for (i = PHY_MAX_ADDR; i > 0; i--) { - u32 phy_id; - - if (get_phy_id(new_bus, i, &phy_id)) - return -1; - - if (phy_id == 0xffffffff) - break; - } - - return i; -} - -#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct device_node *np) { +#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) struct gfar __iomem *enet_regs; /* @@ -220,15 +202,15 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs, struct devi } else if (of_device_is_compatible(np, "fsl,etsec2-mdio") || of_device_is_compatible(np, "fsl,etsec2-tbi")) { return of_iomap(np, 1); - } else - return NULL; -} + } #endif + return NULL; +} -#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) { +#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) struct device_node *np = NULL; int err = 0; @@ -261,9 +243,10 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id) return err; else return -EINVAL; -} +#else + return -ENODEV; #endif - +} static int fsl_pq_mdio_probe(struct platform_device *ofdev) { @@ -339,19 +322,13 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) of_device_is_compatible(np, "fsl,etsec2-mdio") || of_device_is_compatible(np, "fsl,etsec2-tbi") || of_device_is_compatible(np, "gianfar")) { -#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) tbipa = get_gfar_tbipa(regs, np); if (!tbipa) { err = -EINVAL; goto err_free_irqs; } -#else - err = -ENODEV; - goto err_free_irqs; -#endif } else if (of_device_is_compatible(np, "fsl,ucc-mdio") || of_device_is_compatible(np, "ucc_geth_phy")) { -#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) u32 id; static u32 mii_mng_master; @@ -364,10 +341,6 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) mii_mng_master = id; ucc_set_qe_mux_mii_mng(id - 1); } -#else - err = -ENODEV; - goto err_free_irqs; -#endif } else { err = -ENODEV; goto err_free_irqs; @@ -386,16 +359,6 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) } if (tbiaddr == -1) { - out_be32(tbipa, 0); - - tbiaddr = fsl_pq_mdio_find_free(new_bus); - } - - /* - * We define TBIPA at 0 to be illegal, opting to fail for boards that - * have PHYs at 1-31, rather than change tbipa and rescan. - */ - if (tbiaddr == 0) { err = -EBUSY; goto err_free_irqs; diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 89f829f5f725..f8a6853b692e 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -423,10 +423,8 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, lock_sock(sk); opt->src_addr = sp->sa_addr.pptp; - if (add_chan(po)) { - release_sock(sk); + if (add_chan(po)) error = -EBUSY; - } release_sock(sk); return error; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 93fbe6f40898..d2348a5a7809 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -286,7 +286,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath_start_ani(common); } - if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) { + if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { struct ath_hw_antcomb_conf div_ant_conf; u8 lna_conf; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 592a10ac5929..3b585aadabfc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -569,7 +569,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, } case ERFSLEEP:{ if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 72852900df84..e49cf2244c75 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -548,7 +548,7 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 3ac7af1c5509..0883349e1c83 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -3374,7 +3374,7 @@ bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index f27171af979c..f10ac1ad9087 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -602,7 +602,7 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, } case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - break; + return false; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c index 0b4f946cf13a..31ab6ddf52c9 100644 --- a/drivers/pcmcia/pxa2xx_cm_x255.c +++ b/drivers/pcmcia/pxa2xx_cm_x255.c @@ -16,8 +16,6 @@ #include <linux/gpio.h> #include <linux/export.h> -#include <asm/mach-types.h> - #include "soc_common.h" #define GPIO_PCMCIA_SKTSEL (54) @@ -27,15 +25,15 @@ #define GPIO_PCMCIA_S1_RDYINT (8) #define GPIO_PCMCIA_RESET (9) -#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID) -#define PCMCIA_S1_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S1_CD_VALID) -#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT) -#define PCMCIA_S1_RDYINT IRQ_GPIO(GPIO_PCMCIA_S1_RDYINT) +#define PCMCIA_S0_CD_VALID gpio_to_irq(GPIO_PCMCIA_S0_CD_VALID) +#define PCMCIA_S1_CD_VALID gpio_to_irq(GPIO_PCMCIA_S1_CD_VALID) +#define PCMCIA_S0_RDYINT gpio_to_irq(GPIO_PCMCIA_S0_RDYINT) +#define PCMCIA_S1_RDYINT gpio_to_irq(GPIO_PCMCIA_S1_RDYINT) static struct pcmcia_irqs irqs[] = { - { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" }, - { 1, PCMCIA_S1_CD_VALID, "PCMCIA1 CD" }, + { .sock = 0, .str = "PCMCIA0 CD" }, + { .sock = 1, .str = "PCMCIA1 CD" }, }; static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -46,6 +44,8 @@ static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt) gpio_direction_output(GPIO_PCMCIA_RESET, 0); skt->socket.pci_irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT; + irqs[0].irq = PCMCIA_S0_CD_VALID; + irqs[1].irq = PCMCIA_S1_CD_VALID; ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); if (!ret) gpio_free(GPIO_PCMCIA_RESET); diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c index 923f315926ef..3dc7621a0767 100644 --- a/drivers/pcmcia/pxa2xx_cm_x270.c +++ b/drivers/pcmcia/pxa2xx_cm_x270.c @@ -16,20 +16,18 @@ #include <linux/gpio.h> #include <linux/export.h> -#include <asm/mach-types.h> - #include "soc_common.h" #define GPIO_PCMCIA_S0_CD_VALID (84) #define GPIO_PCMCIA_S0_RDYINT (82) #define GPIO_PCMCIA_RESET (53) -#define PCMCIA_S0_CD_VALID IRQ_GPIO(GPIO_PCMCIA_S0_CD_VALID) -#define PCMCIA_S0_RDYINT IRQ_GPIO(GPIO_PCMCIA_S0_RDYINT) +#define PCMCIA_S0_CD_VALID gpio_to_irq(GPIO_PCMCIA_S0_CD_VALID) +#define PCMCIA_S0_RDYINT gpio_to_irq(GPIO_PCMCIA_S0_RDYINT) static struct pcmcia_irqs irqs[] = { - { 0, PCMCIA_S0_CD_VALID, "PCMCIA0 CD" }, + { .sock = 0, .str = "PCMCIA0 CD" }, }; static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) @@ -40,6 +38,7 @@ static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) gpio_direction_output(GPIO_PCMCIA_RESET, 0); skt->socket.pci_irq = PCMCIA_S0_RDYINT; + irqs[0].irq = PCMCIA_S0_CD_VALID; ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); if (!ret) gpio_free(GPIO_PCMCIA_RESET); diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c index 8bfbd4dca131..17cd2ce7428f 100644 --- a/drivers/pcmcia/pxa2xx_e740.c +++ b/drivers/pcmcia/pxa2xx_e740.c @@ -26,20 +26,23 @@ static struct pcmcia_irqs cd_irqs[] = { { .sock = 0, - .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD0), .str = "CF card detect" }, { .sock = 1, - .irq = IRQ_GPIO(GPIO_E740_PCMCIA_CD1), .str = "Wifi switch" }, }; static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0) : - IRQ_GPIO(GPIO_E740_PCMCIA_RDY1); + if (skt->nr == 0) + skt->socket.pci_irq = gpio_to_irq(GPIO_E740_PCMCIA_RDY0); + else + skt->socket.pci_irq = gpio_to_irq(GPIO_E740_PCMCIA_RDY1); + + cd_irqs[0].irq = gpio_to_irq(GPIO_E740_PCMCIA_CD0); + cd_irqs[1].irq = gpio_to_irq(GPIO_E740_PCMCIA_CD1); return soc_pcmcia_request_irqs(skt, &cd_irqs[skt->nr], 1); } diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c index d589ad1dcd4c..6a8e011a8c13 100644 --- a/drivers/pcmcia/pxa2xx_palmld.c +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -33,7 +33,7 @@ static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios)); - skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY); + skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMLD_PCMCIA_READY); return ret; } diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c index 9c6a04b2f71b..9e38de769ba3 100644 --- a/drivers/pcmcia/pxa2xx_palmtc.c +++ b/drivers/pcmcia/pxa2xx_palmtc.c @@ -37,7 +37,7 @@ static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ret = gpio_request_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios)); - skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY); + skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTC_PCMCIA_READY); return ret; } diff --git a/drivers/pcmcia/pxa2xx_stargate2.c b/drivers/pcmcia/pxa2xx_stargate2.c index 939622251dfb..6c2366b74a35 100644 --- a/drivers/pcmcia/pxa2xx_stargate2.c +++ b/drivers/pcmcia/pxa2xx_stargate2.c @@ -34,7 +34,7 @@ #define SG2_S0_GPIO_READY 81 static struct pcmcia_irqs irqs[] = { - { 0, IRQ_GPIO(SG2_S0_GPIO_DETECT), "PCMCIA0 CD" }, + {.sock = 0, .str = "PCMCIA0 CD" }, }; static struct gpio sg2_pcmcia_gpios[] = { @@ -44,7 +44,9 @@ static struct gpio sg2_pcmcia_gpios[] = { static int sg2_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { - skt->socket.pci_irq = IRQ_GPIO(SG2_S0_GPIO_READY); + skt->socket.pci_irq = gpio_to_irq(SG2_S0_GPIO_READY); + irqs[0].irq = gpio_to_irq(SG2_S0_GPIO_DETECT); + return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); } diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c index 57ddb969d888..7c33f898135a 100644 --- a/drivers/pcmcia/pxa2xx_trizeps4.c +++ b/drivers/pcmcia/pxa2xx_trizeps4.c @@ -30,7 +30,7 @@ extern void board_pcmcia_power(int power); static struct pcmcia_irqs irqs[] = { - { 0, IRQ_GPIO(GPIO_PCD), "cs0_cd" } + { .sock = 0, .str = "cs0_cd" } /* on other baseboards we can have more inputs */ }; @@ -53,7 +53,8 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt) gpio_free(GPIO_PRDY); return -EINVAL; } - skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY); + skt->socket.pci_irq = gpio_to_irq(GPIO_PRDY); + irqs[0].irq = gpio_to_irq(GPIO_PCD); break; default: break; diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index 66ab92cf3105..61b17d235dbe 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -38,12 +38,10 @@ static struct gpio vpac270_cf_gpios[] = { static struct pcmcia_irqs cd_irqs[] = { { .sock = 0, - .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD), .str = "PCMCIA CD" }, { .sock = 1, - .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD), .str = "CF CD" }, }; @@ -57,6 +55,7 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ARRAY_SIZE(vpac270_pcmcia_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); + cd_irqs[0].irq = gpio_to_irq(GPIO84_VPAC270_PCMCIA_CD); if (!ret) ret = soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); @@ -65,6 +64,7 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ARRAY_SIZE(vpac270_cf_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); + cd_irqs[1].irq = gpio_to_irq(GPIO17_VPAC270_CF_CD); if (!ret) ret = soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 5b979d9cc332..175067a17c46 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -25,6 +25,7 @@ #include <linux/clk.h> #include <linux/log2.h> #include <linux/slab.h> +#include <linux/of.h> #include <mach/hardware.h> #include <asm/uaccess.h> @@ -507,7 +508,13 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) goto err_nortc; } - s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; +#ifdef CONFIG_OF + if (pdev->dev.of_node) + s3c_rtc_cpu_type = of_device_is_compatible(pdev->dev.of_node, + "samsung,s3c6410-rtc") ? TYPE_S3C64XX : TYPE_S3C2410; + else +#endif + s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data; /* Check RTC Time */ @@ -629,6 +636,17 @@ static int s3c_rtc_resume(struct platform_device *pdev) #define s3c_rtc_resume NULL #endif +#ifdef CONFIG_OF +static const struct of_device_id s3c_rtc_dt_match[] = { + { .compatible = "samsung,s3c2410-rtc" }, + { .compatible = "samsung,s3c6410-rtc" }, + {}, +}; +MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); +#else +#define s3c_rtc_dt_match NULL +#endif + static struct platform_device_id s3c_rtc_driver_ids[] = { { .name = "s3c2410-rtc", @@ -651,6 +669,7 @@ static struct platform_driver s3c_rtc_driver = { .driver = { .name = "s3c-rtc", .owner = THIS_MODULE, + .of_match_table = s3c_rtc_dt_match, }, }; diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 5f94d22c491e..542668292900 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -233,13 +233,9 @@ int bbc_i2c_write_buf(struct bbc_i2c_client *client, int ret = 0; while (len > 0) { - int err = bbc_i2c_writeb(client, *buf, off); - - if (err < 0) { - ret = err; + ret = bbc_i2c_writeb(client, *buf, off); + if (ret < 0) break; - } - len--; buf++; off++; @@ -253,11 +249,9 @@ int bbc_i2c_read_buf(struct bbc_i2c_client *client, int ret = 0; while (len > 0) { - int err = bbc_i2c_readb(client, buf, off); - if (err < 0) { - ret = err; + ret = bbc_i2c_readb(client, buf, off); + if (ret < 0) break; - } len--; buf++; off++; @@ -422,17 +416,6 @@ static struct platform_driver bbc_i2c_driver = { .remove = __devexit_p(bbc_i2c_remove), }; -static int __init bbc_i2c_init(void) -{ - return platform_driver_register(&bbc_i2c_driver); -} - -static void __exit bbc_i2c_exit(void) -{ - platform_driver_unregister(&bbc_i2c_driver); -} - -module_init(bbc_i2c_init); -module_exit(bbc_i2c_exit); +module_platform_driver(bbc_i2c_driver); MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 965a1fccd66a..4b9939726c34 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -275,15 +275,4 @@ static struct platform_driver d7s_driver = { .remove = __devexit_p(d7s_remove), }; -static int __init d7s_init(void) -{ - return platform_driver_register(&d7s_driver); -} - -static void __exit d7s_exit(void) -{ - platform_driver_unregister(&d7s_driver); -} - -module_init(d7s_init); -module_exit(d7s_exit); +module_platform_driver(d7s_driver); diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index be7b4e56154f..339fd6f65eda 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -1138,16 +1138,6 @@ static struct platform_driver envctrl_driver = { .remove = __devexit_p(envctrl_remove), }; -static int __init envctrl_init(void) -{ - return platform_driver_register(&envctrl_driver); -} - -static void __exit envctrl_exit(void) -{ - platform_driver_unregister(&envctrl_driver); -} +module_platform_driver(envctrl_driver); -module_init(envctrl_init); -module_exit(envctrl_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 73dd4e7afaaa..826157f38694 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -216,16 +216,6 @@ static struct platform_driver flash_driver = { .remove = __devexit_p(flash_remove), }; -static int __init flash_init(void) -{ - return platform_driver_register(&flash_driver); -} - -static void __exit flash_cleanup(void) -{ - platform_driver_unregister(&flash_driver); -} +module_platform_driver(flash_driver); -module_init(flash_init); -module_exit(flash_cleanup); MODULE_LICENSE("GPL"); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index ebce9639a26a..0b31658ccde5 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -435,16 +435,6 @@ static struct platform_driver uctrl_driver = { }; -static int __init uctrl_init(void) -{ - return platform_driver_register(&uctrl_driver); -} - -static void __exit uctrl_exit(void) -{ - platform_driver_unregister(&uctrl_driver); -} +module_platform_driver(uctrl_driver); -module_init(uctrl_init); -module_exit(uctrl_exit); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 019a7163572f..dcf7e1006426 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -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; } diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 84c934c0a545..520e8286db28 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -517,10 +517,14 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) { - ssb_pcicore_fix_sprom_core_index(pc); + struct ssb_device *pdev = pc->dev; + struct ssb_bus *bus = pdev->bus; + + if (bus->bustype == SSB_BUSTYPE_PCI) + ssb_pcicore_fix_sprom_core_index(pc); /* Disable PCI interrupts. */ - ssb_write32(pc->dev, SSB_INTVEC, 0); + ssb_write32(pdev, SSB_INTVEC, 0); /* Additional PCIe always once-executed workarounds */ if (pc->dev->id.coreid == SSB_DEV_PCIE) { diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index fb2e89c3056c..5385da2e9cdb 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -89,6 +89,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { {USB_DEVICE(0x0DF6, 0x0045)}, {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */ {USB_DEVICE(0x0DF6, 0x004B)}, + {USB_DEVICE(0x0DF6, 0x005D)}, {USB_DEVICE(0x0DF6, 0x0063)}, /* Sweex */ {USB_DEVICE(0x177F, 0x0154)}, diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index 3d1279c424a8..7eb56178fb64 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c @@ -54,6 +54,7 @@ /* Bridge GPT id (1 - 4), DM Timer id (5 - 8) */ #define DMT_ID(id) ((id) + 4) +#define DM_TIMER_CLOCKS 4 /* Bridge MCBSP id (6 - 10), OMAP Mcbsp id (0 - 4) */ #define MCBSP_ID(id) ((id) - 6) @@ -114,8 +115,13 @@ static s8 get_clk_type(u8 id) */ void dsp_clk_exit(void) { + int i; + dsp_clock_disable_all(dsp_clocks); + for (i = 0; i < DM_TIMER_CLOCKS; i++) + omap_dm_timer_free(timer[i]); + clk_put(iva2_clk); clk_put(ssi.sst_fck); clk_put(ssi.ssr_fck); @@ -130,9 +136,13 @@ void dsp_clk_exit(void) void dsp_clk_init(void) { static struct platform_device dspbridge_device; + int i, id; dspbridge_device.dev.bus = &platform_bus_type; + for (i = 0, id = 5; i < DM_TIMER_CLOCKS; i++, id++) + timer[i] = omap_dm_timer_request_specific(id); + iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); if (IS_ERR(iva2_clk)) dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); @@ -204,8 +214,7 @@ int dsp_clk_enable(enum dsp_clk_id clk_id) clk_enable(iva2_clk); break; case GPT_CLK: - timer[clk_id - 1] = - omap_dm_timer_request_specific(DMT_ID(clk_id)); + status = omap_dm_timer_start(timer[clk_id - 1]); break; #ifdef CONFIG_OMAP_MCBSP case MCBSP_CLK: @@ -281,7 +290,7 @@ int dsp_clk_disable(enum dsp_clk_id clk_id) clk_disable(iva2_clk); break; case GPT_CLK: - omap_dm_timer_free(timer[clk_id - 1]); + status = omap_dm_timer_stop(timer[clk_id - 1]); break; #ifdef CONFIG_OMAP_MCBSP case MCBSP_CLK: diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index c43c7e3421c8..76cfc6edecd9 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -24,11 +24,7 @@ #include <linux/types.h> #include <linux/platform_device.h> #include <linux/pm.h> - -#ifdef MODULE #include <linux/module.h> -#endif - #include <linux/device.h> #include <linux/init.h> #include <linux/moduleparam.h> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 925a1e547a83..fb89b85d0d81 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -457,7 +457,7 @@ config SERIAL_SAMSUNG config SERIAL_SAMSUNG_UARTS_4 bool depends on ARM && PLAT_SAMSUNG - default y if CPU_S3C2443 + default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442) help Internal node for the common case of 4 Samsung compatible UARTs @@ -465,7 +465,7 @@ config SERIAL_SAMSUNG_UARTS int depends on ARM && PLAT_SAMSUNG default 6 if ARCH_S5P6450 - default 4 if SERIAL_SAMSUNG_UARTS_4 + default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 default 3 help Select the number of available UART ports for the Samsung S3C @@ -495,47 +495,6 @@ config SERIAL_SAMSUNG_CONSOLE your boot loader about how to pass options to the kernel at boot time.) -config SERIAL_S3C2410 - tristate "Samsung S3C2410 Serial port support" - depends on SERIAL_SAMSUNG && CPU_S3C2410 - default y if CPU_S3C2410 - help - Serial port support for the Samsung S3C2410 SoC - -config SERIAL_S3C2412 - tristate "Samsung S3C2412/S3C2413 Serial port support" - depends on SERIAL_SAMSUNG && CPU_S3C2412 - default y if CPU_S3C2412 - help - Serial port support for the Samsung S3C2412 and S3C2413 SoC - -config SERIAL_S3C2440 - tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416) - default y if CPU_S3C2440 - default y if CPU_S3C2442 - select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416 - help - Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC - -config SERIAL_S3C6400 - tristate "Samsung S3C6400/S3C6410/S5P6440/S5P6450/S5PC100 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5P6450 || CPU_S5PC100) - select SERIAL_SAMSUNG_UARTS_4 - default y - help - Serial port support for the Samsung S3C6400, S3C6410, S5P6440, S5P6450 - and S5PC100 SoCs - -config SERIAL_S5PV210 - tristate "Samsung S5PV210 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) - select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) - default y - help - Serial port support for Samsung's S5P Family of SoC's - - config SERIAL_MAX3100 tristate "MAX3100 support" depends on SPI diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index e10cf5b54b6d..84bc2e5a57be 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -39,11 +39,6 @@ obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o -obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o -obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o -obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o -obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o -obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX3107) += max3107.o obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o diff --git a/drivers/tty/serial/s3c2410.c b/drivers/tty/serial/s3c2410.c deleted file mode 100644 index b1d7e7c1849d..000000000000 --- a/drivers/tty/serial/s3c2410.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Driver for Samsung S3C2410 SoC onboard UARTs. - * - * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/serial.h> - -#include <asm/irq.h> -#include <mach/hardware.h> - -#include <plat/regs-serial.h> -#include <mach/regs-gpio.h> - -#include "samsung.h" - -static int s3c2410_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - if (strcmp(clk->name, "uclk") == 0) - ucon |= S3C2410_UCON_UCLK; - else - ucon &= ~S3C2410_UCON_UCLK; - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - -static int s3c2410_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - clk->divisor = 1; - clk->name = (ucon & S3C2410_UCON_UCLK) ? "uclk" : "pclk"; - - return 0; -} - -static int s3c2410_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n", - port, port->mapbase, cfg); - - wr_regl(port, S3C2410_UCON, cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c2410_uart_inf = { - .name = "Samsung S3C2410 UART", - .type = PORT_S3C2410, - .fifosize = 16, - .rx_fifomask = S3C2410_UFSTAT_RXMASK, - .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2410_UFSTAT_RXFULL, - .tx_fifofull = S3C2410_UFSTAT_TXFULL, - .tx_fifomask = S3C2410_UFSTAT_TXMASK, - .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, - .get_clksrc = s3c2410_serial_getsource, - .set_clksrc = s3c2410_serial_setsource, - .reset_port = s3c2410_serial_resetport, -}; - -static int s3c2410_serial_probe(struct platform_device *dev) -{ - return s3c24xx_serial_probe(dev, &s3c2410_uart_inf); -} - -static struct platform_driver s3c2410_serial_driver = { - .probe = s3c2410_serial_probe, - .remove = __devexit_p(s3c24xx_serial_remove), - .driver = { - .name = "s3c2410-uart", - .owner = THIS_MODULE, - }, -}; - -static int __init s3c2410_serial_init(void) -{ - return s3c24xx_serial_init(&s3c2410_serial_driver, &s3c2410_uart_inf); -} - -static void __exit s3c2410_serial_exit(void) -{ - platform_driver_unregister(&s3c2410_serial_driver); -} - -module_init(s3c2410_serial_init); -module_exit(s3c2410_serial_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -MODULE_DESCRIPTION("Samsung S3C2410 SoC Serial port driver"); -MODULE_ALIAS("platform:s3c2410-uart"); diff --git a/drivers/tty/serial/s3c2412.c b/drivers/tty/serial/s3c2412.c deleted file mode 100644 index 2234bf9ced45..000000000000 --- a/drivers/tty/serial/s3c2412.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Driver for Samsung S3C2412 and S3C2413 SoC onboard UARTs. - * - * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/serial.h> - -#include <asm/irq.h> -#include <mach/hardware.h> - -#include <plat/regs-serial.h> -#include <mach/regs-gpio.h> - -#include "samsung.h" - -static int s3c2412_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - ucon &= ~S3C2412_UCON_CLKMASK; - - if (strcmp(clk->name, "uclk") == 0) - ucon |= S3C2440_UCON_UCLK; - else if (strcmp(clk->name, "pclk") == 0) - ucon |= S3C2440_UCON_PCLK; - else if (strcmp(clk->name, "usysclk") == 0) - ucon |= S3C2412_UCON_USYSCLK; - else { - printk(KERN_ERR "unknown clock source %s\n", clk->name); - return -EINVAL; - } - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - - -static int s3c2412_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - switch (ucon & S3C2412_UCON_CLKMASK) { - case S3C2412_UCON_UCLK: - clk->divisor = 1; - clk->name = "uclk"; - break; - - case S3C2412_UCON_PCLK: - case S3C2412_UCON_PCLK2: - clk->divisor = 1; - clk->name = "pclk"; - break; - - case S3C2412_UCON_USYSCLK: - clk->divisor = 1; - clk->name = "usysclk"; - break; - } - - return 0; -} - -static int s3c2412_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - dbg("%s: port=%p (%08lx), cfg=%p\n", - __func__, port, port->mapbase, cfg); - - /* ensure we don't change the clock settings... */ - - ucon &= S3C2412_UCON_CLKMASK; - - wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c2412_uart_inf = { - .name = "Samsung S3C2412 UART", - .type = PORT_S3C2412, - .fifosize = 64, - .has_divslot = 1, - .rx_fifomask = S3C2440_UFSTAT_RXMASK, - .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2440_UFSTAT_RXFULL, - .tx_fifofull = S3C2440_UFSTAT_TXFULL, - .tx_fifomask = S3C2440_UFSTAT_TXMASK, - .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, - .get_clksrc = s3c2412_serial_getsource, - .set_clksrc = s3c2412_serial_setsource, - .reset_port = s3c2412_serial_resetport, -}; - -/* device management */ - -static int s3c2412_serial_probe(struct platform_device *dev) -{ - dbg("s3c2440_serial_probe: dev=%p\n", dev); - return s3c24xx_serial_probe(dev, &s3c2412_uart_inf); -} - -static struct platform_driver s3c2412_serial_driver = { - .probe = s3c2412_serial_probe, - .remove = __devexit_p(s3c24xx_serial_remove), - .driver = { - .name = "s3c2412-uart", - .owner = THIS_MODULE, - }, -}; - -static inline int s3c2412_serial_init(void) -{ - return s3c24xx_serial_init(&s3c2412_serial_driver, &s3c2412_uart_inf); -} - -static inline void s3c2412_serial_exit(void) -{ - platform_driver_unregister(&s3c2412_serial_driver); -} - -module_init(s3c2412_serial_init); -module_exit(s3c2412_serial_exit); - -MODULE_DESCRIPTION("Samsung S3C2412,S3C2413 SoC Serial port driver"); -MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:s3c2412-uart"); diff --git a/drivers/tty/serial/s3c2440.c b/drivers/tty/serial/s3c2440.c deleted file mode 100644 index 1d0c324b813f..000000000000 --- a/drivers/tty/serial/s3c2440.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Driver for Samsung S3C2440 and S3C2442 SoC onboard UARTs. - * - * Ben Dooks, Copyright (c) 2003-2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/serial.h> - -#include <asm/irq.h> -#include <mach/hardware.h> - -#include <plat/regs-serial.h> -#include <mach/regs-gpio.h> - -#include "samsung.h" - - -static int s3c2440_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - /* todo - proper fclk<>nonfclk switch. */ - - ucon &= ~S3C2440_UCON_CLKMASK; - - if (strcmp(clk->name, "uclk") == 0) - ucon |= S3C2440_UCON_UCLK; - else if (strcmp(clk->name, "pclk") == 0) - ucon |= S3C2440_UCON_PCLK; - else if (strcmp(clk->name, "fclk") == 0) - ucon |= S3C2440_UCON_FCLK; - else { - printk(KERN_ERR "unknown clock source %s\n", clk->name); - return -EINVAL; - } - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - - -static int s3c2440_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - unsigned long ucon0, ucon1, ucon2; - - switch (ucon & S3C2440_UCON_CLKMASK) { - case S3C2440_UCON_UCLK: - clk->divisor = 1; - clk->name = "uclk"; - break; - - case S3C2440_UCON_PCLK: - case S3C2440_UCON_PCLK2: - clk->divisor = 1; - clk->name = "pclk"; - break; - - case S3C2440_UCON_FCLK: - /* the fun of calculating the uart divisors on - * the s3c2440 */ - - ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); - ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); - ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); - - printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2); - - ucon0 &= S3C2440_UCON0_DIVMASK; - ucon1 &= S3C2440_UCON1_DIVMASK; - ucon2 &= S3C2440_UCON2_DIVMASK; - - if (ucon0 != 0) { - clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT; - clk->divisor += 6; - } else if (ucon1 != 0) { - clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT; - clk->divisor += 21; - } else if (ucon2 != 0) { - clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT; - clk->divisor += 36; - } else { - /* manual calims 44, seems to be 9 */ - clk->divisor = 9; - } - - clk->name = "fclk"; - break; - } - - return 0; -} - -static int s3c2440_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n", - port, port->mapbase, cfg); - - /* ensure we don't change the clock settings... */ - - ucon &= (S3C2440_UCON0_DIVMASK | (3<<10)); - - wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c2440_uart_inf = { - .name = "Samsung S3C2440 UART", - .type = PORT_S3C2440, - .fifosize = 64, - .rx_fifomask = S3C2440_UFSTAT_RXMASK, - .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2440_UFSTAT_RXFULL, - .tx_fifofull = S3C2440_UFSTAT_TXFULL, - .tx_fifomask = S3C2440_UFSTAT_TXMASK, - .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, - .get_clksrc = s3c2440_serial_getsource, - .set_clksrc = s3c2440_serial_setsource, - .reset_port = s3c2440_serial_resetport, -}; - -/* device management */ - -static int s3c2440_serial_probe(struct platform_device *dev) -{ - dbg("s3c2440_serial_probe: dev=%p\n", dev); - return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); -} - -static struct platform_driver s3c2440_serial_driver = { - .probe = s3c2440_serial_probe, - .remove = __devexit_p(s3c24xx_serial_remove), - .driver = { - .name = "s3c2440-uart", - .owner = THIS_MODULE, - }, -}; - -static int __init s3c2440_serial_init(void) -{ - return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf); -} - -static void __exit s3c2440_serial_exit(void) -{ - platform_driver_unregister(&s3c2440_serial_driver); -} - -module_init(s3c2440_serial_init); -module_exit(s3c2440_serial_exit); - -MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver"); -MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:s3c2440-uart"); diff --git a/drivers/tty/serial/s3c6400.c b/drivers/tty/serial/s3c6400.c deleted file mode 100644 index e2f6913d84d5..000000000000 --- a/drivers/tty/serial/s3c6400.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Driver for Samsung S3C6400 and S3C6410 SoC onboard UARTs. - * - * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * http://armlinux.simtec.co.uk/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/serial.h> - -#include <asm/irq.h> -#include <mach/hardware.h> - -#include <plat/regs-serial.h> - -#include "samsung.h" - -static int s3c6400_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - if (strcmp(clk->name, "uclk0") == 0) { - ucon &= ~S3C6400_UCON_CLKMASK; - ucon |= S3C6400_UCON_UCLK0; - } else if (strcmp(clk->name, "uclk1") == 0) - ucon |= S3C6400_UCON_UCLK1; - else if (strcmp(clk->name, "pclk") == 0) { - /* See notes about transitioning from UCLK to PCLK */ - ucon &= ~S3C6400_UCON_UCLK0; - } else { - printk(KERN_ERR "unknown clock source %s\n", clk->name); - return -EINVAL; - } - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - - -static int s3c6400_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - u32 ucon = rd_regl(port, S3C2410_UCON); - - clk->divisor = 1; - - switch (ucon & S3C6400_UCON_CLKMASK) { - case S3C6400_UCON_UCLK0: - clk->name = "uclk0"; - break; - - case S3C6400_UCON_UCLK1: - clk->name = "uclk1"; - break; - - case S3C6400_UCON_PCLK: - case S3C6400_UCON_PCLK2: - clk->name = "pclk"; - break; - } - - return 0; -} - -static int s3c6400_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - dbg("s3c6400_serial_resetport: port=%p (%08lx), cfg=%p\n", - port, port->mapbase, cfg); - - /* ensure we don't change the clock settings... */ - - ucon &= S3C6400_UCON_CLKMASK; - - wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - return 0; -} - -static struct s3c24xx_uart_info s3c6400_uart_inf = { - .name = "Samsung S3C6400 UART", - .type = PORT_S3C6400, - .fifosize = 64, - .has_divslot = 1, - .rx_fifomask = S3C2440_UFSTAT_RXMASK, - .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, - .rx_fifofull = S3C2440_UFSTAT_RXFULL, - .tx_fifofull = S3C2440_UFSTAT_TXFULL, - .tx_fifomask = S3C2440_UFSTAT_TXMASK, - .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, - .get_clksrc = s3c6400_serial_getsource, - .set_clksrc = s3c6400_serial_setsource, - .reset_port = s3c6400_serial_resetport, -}; - -/* device management */ - -static int s3c6400_serial_probe(struct platform_device *dev) -{ - dbg("s3c6400_serial_probe: dev=%p\n", dev); - return s3c24xx_serial_probe(dev, &s3c6400_uart_inf); -} - -static struct platform_driver s3c6400_serial_driver = { - .probe = s3c6400_serial_probe, - .remove = __devexit_p(s3c24xx_serial_remove), - .driver = { - .name = "s3c6400-uart", - .owner = THIS_MODULE, - }, -}; - -static int __init s3c6400_serial_init(void) -{ - return s3c24xx_serial_init(&s3c6400_serial_driver, &s3c6400_uart_inf); -} - -static void __exit s3c6400_serial_exit(void) -{ - platform_driver_unregister(&s3c6400_serial_driver); -} - -module_init(s3c6400_serial_init); -module_exit(s3c6400_serial_exit); - -MODULE_DESCRIPTION("Samsung S3C6400,S3C6410 SoC Serial port driver"); -MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:s3c6400-uart"); diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c deleted file mode 100644 index 8b0b888a1b76..000000000000 --- a/drivers/tty/serial/s5pv210.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Based on drivers/serial/s3c6400.c - * - * Driver for Samsung S5PV210 SoC UARTs. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include <linux/module.h> -#include <linux/ioport.h> -#include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/serial_core.h> -#include <linux/serial.h> -#include <linux/delay.h> - -#include <asm/irq.h> -#include <mach/hardware.h> -#include <plat/regs-serial.h> -#include "samsung.h" - -static int s5pv210_serial_setsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - struct s3c2410_uartcfg *cfg = port->dev->platform_data; - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - if (cfg->flags & NO_NEED_CHECK_CLKSRC) - return 0; - - if (strcmp(clk->name, "pclk") == 0) - ucon &= ~S5PV210_UCON_CLKMASK; - else if (strcmp(clk->name, "uclk1") == 0) - ucon |= S5PV210_UCON_CLKMASK; - else { - printk(KERN_ERR "unknown clock source %s\n", clk->name); - return -EINVAL; - } - - wr_regl(port, S3C2410_UCON, ucon); - return 0; -} - - -static int s5pv210_serial_getsource(struct uart_port *port, - struct s3c24xx_uart_clksrc *clk) -{ - struct s3c2410_uartcfg *cfg = port->dev->platform_data; - u32 ucon = rd_regl(port, S3C2410_UCON); - - clk->divisor = 1; - - if (cfg->flags & NO_NEED_CHECK_CLKSRC) - return 0; - - switch (ucon & S5PV210_UCON_CLKMASK) { - case S5PV210_UCON_PCLK: - clk->name = "pclk"; - break; - case S5PV210_UCON_UCLK: - clk->name = "uclk1"; - break; - } - - return 0; -} - -static int s5pv210_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) -{ - unsigned long ucon = rd_regl(port, S3C2410_UCON); - - ucon &= S5PV210_UCON_CLKMASK; - wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); - wr_regl(port, S3C2410_ULCON, cfg->ulcon); - - /* reset both fifos */ - wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); - wr_regl(port, S3C2410_UFCON, cfg->ufcon); - - /* It is need to delay When reset FIFO register */ - udelay(1); - - return 0; -} - -#define S5PV210_UART_DEFAULT_INFO(fifo_size) \ - .name = "Samsung S5PV210 UART0", \ - .type = PORT_S3C6400, \ - .fifosize = fifo_size, \ - .has_divslot = 1, \ - .rx_fifomask = S5PV210_UFSTAT_RXMASK, \ - .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, \ - .rx_fifofull = S5PV210_UFSTAT_RXFULL, \ - .tx_fifofull = S5PV210_UFSTAT_TXFULL, \ - .tx_fifomask = S5PV210_UFSTAT_TXMASK, \ - .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, \ - .get_clksrc = s5pv210_serial_getsource, \ - .set_clksrc = s5pv210_serial_setsource, \ - .reset_port = s5pv210_serial_resetport - -static struct s3c24xx_uart_info s5p_port_fifo256 = { - S5PV210_UART_DEFAULT_INFO(256), -}; - -static struct s3c24xx_uart_info s5p_port_fifo64 = { - S5PV210_UART_DEFAULT_INFO(64), -}; - -static struct s3c24xx_uart_info s5p_port_fifo16 = { - S5PV210_UART_DEFAULT_INFO(16), -}; - -static struct s3c24xx_uart_info *s5p_uart_inf[] = { - [0] = &s5p_port_fifo256, - [1] = &s5p_port_fifo64, - [2] = &s5p_port_fifo16, - [3] = &s5p_port_fifo16, -}; - -/* device management */ -static int s5p_serial_probe(struct platform_device *pdev) -{ - return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); -} - -static struct platform_driver s5p_serial_driver = { - .probe = s5p_serial_probe, - .remove = __devexit_p(s3c24xx_serial_remove), - .driver = { - .name = "s5pv210-uart", - .owner = THIS_MODULE, - }, -}; - -static int __init s5p_serial_init(void) -{ - return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf); -} - -static void __exit s5p_serial_exit(void) -{ - platform_driver_unregister(&s5p_serial_driver); -} - -module_init(s5p_serial_init); -module_exit(s5p_serial_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:s5pv210-uart"); -MODULE_DESCRIPTION("Samsung S5PV210 UART Driver support"); -MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com>"); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index b31f1c3a2c4c..f96f37b5fec6 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -42,6 +42,7 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/cpufreq.h> +#include <linux/of.h> #include <asm/irq.h> @@ -49,6 +50,7 @@ #include <mach/map.h> #include <plat/regs-serial.h> +#include <plat/clock.h> #include "samsung.h" @@ -190,10 +192,13 @@ static inline struct s3c24xx_uart_info *s3c24xx_port_to_info(struct uart_port *p static inline struct s3c2410_uartcfg *s3c24xx_port_to_cfg(struct uart_port *port) { + struct s3c24xx_uart_port *ourport; + if (port->dev == NULL) return NULL; - return (struct s3c2410_uartcfg *)port->dev->platform_data; + ourport = container_of(port, struct s3c24xx_uart_port, port); + return ourport->cfg; } static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, @@ -202,7 +207,7 @@ static int s3c24xx_serial_rx_fifocnt(struct s3c24xx_uart_port *ourport, struct s3c24xx_uart_info *info = ourport->info; if (ufstat & info->rx_fifofull) - return info->fifosize; + return ourport->port.fifosize; return (ufstat & info->rx_fifomask) >> info->rx_fifoshift; } @@ -555,154 +560,98 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, * */ +#define MAX_CLK_NAME_LENGTH 15 -#define MAX_CLKS (8) - -static struct s3c24xx_uart_clksrc tmp_clksrc = { - .name = "pclk", - .min_baud = 0, - .max_baud = 0, - .divisor = 1, -}; - -static inline int -s3c24xx_serial_getsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) +static inline int s3c24xx_serial_getsource(struct uart_port *port) { struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + unsigned int ucon; - return (info->get_clksrc)(port, c); -} - -static inline int -s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) -{ - struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + if (info->num_clks == 1) + return 0; - return (info->set_clksrc)(port, c); + ucon = rd_regl(port, S3C2410_UCON); + ucon &= info->clksel_mask; + return ucon >> info->clksel_shift; } -struct baud_calc { - struct s3c24xx_uart_clksrc *clksrc; - unsigned int calc; - unsigned int divslot; - unsigned int quot; - struct clk *src; -}; - -static int s3c24xx_serial_calcbaud(struct baud_calc *calc, - struct uart_port *port, - struct s3c24xx_uart_clksrc *clksrc, - unsigned int baud) +static void s3c24xx_serial_setsource(struct uart_port *port, + unsigned int clk_sel) { - struct s3c24xx_uart_port *ourport = to_ourport(port); - unsigned long rate; - - calc->src = clk_get(port->dev, clksrc->name); - if (calc->src == NULL || IS_ERR(calc->src)) - return 0; - - rate = clk_get_rate(calc->src); - rate /= clksrc->divisor; + struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + unsigned int ucon; - calc->clksrc = clksrc; + if (info->num_clks == 1) + return; - if (ourport->info->has_divslot) { - unsigned long div = rate / baud; - - /* The UDIVSLOT register on the newer UARTs allows us to - * get a divisor adjustment of 1/16th on the baud clock. - * - * We don't keep the UDIVSLOT value (the 16ths we calculated - * by not multiplying the baud by 16) as it is easy enough - * to recalculate. - */ - - calc->quot = div / 16; - calc->calc = rate / div; - } else { - calc->quot = (rate + (8 * baud)) / (16 * baud); - calc->calc = (rate / (calc->quot * 16)); - } + ucon = rd_regl(port, S3C2410_UCON); + if ((ucon & info->clksel_mask) >> info->clksel_shift == clk_sel) + return; - calc->quot--; - return 1; + ucon &= ~info->clksel_mask; + ucon |= clk_sel << info->clksel_shift; + wr_regl(port, S3C2410_UCON, ucon); } -static unsigned int s3c24xx_serial_getclk(struct uart_port *port, - struct s3c24xx_uart_clksrc **clksrc, - struct clk **clk, - unsigned int baud) +static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, + unsigned int req_baud, struct clk **best_clk, + unsigned int *clk_num) { - struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); - struct s3c24xx_uart_clksrc *clkp; - struct baud_calc res[MAX_CLKS]; - struct baud_calc *resptr, *best, *sptr; - int i; - - clkp = cfg->clocks; - best = NULL; - - if (cfg->clocks_size < 2) { - if (cfg->clocks_size == 0) - clkp = &tmp_clksrc; - - /* check to see if we're sourcing fclk, and if so we're - * going to have to update the clock source - */ - - if (strcmp(clkp->name, "fclk") == 0) { - struct s3c24xx_uart_clksrc src; - - s3c24xx_serial_getsource(port, &src); - - /* check that the port already using fclk, and if - * not, then re-select fclk + struct s3c24xx_uart_info *info = ourport->info; + struct clk *clk; + unsigned long rate; + unsigned int cnt, baud, quot, clk_sel, best_quot = 0; + char clkname[MAX_CLK_NAME_LENGTH]; + int calc_deviation, deviation = (1 << 30) - 1; + + *best_clk = NULL; + clk_sel = (ourport->cfg->clk_sel) ? ourport->cfg->clk_sel : + ourport->info->def_clk_sel; + for (cnt = 0; cnt < info->num_clks; cnt++) { + if (!(clk_sel & (1 << cnt))) + continue; + + sprintf(clkname, "clk_uart_baud%d", cnt); + clk = clk_get(ourport->port.dev, clkname); + if (IS_ERR_OR_NULL(clk)) + continue; + + rate = clk_get_rate(clk); + if (!rate) + continue; + + if (ourport->info->has_divslot) { + unsigned long div = rate / req_baud; + + /* The UDIVSLOT register on the newer UARTs allows us to + * get a divisor adjustment of 1/16th on the baud clock. + * + * We don't keep the UDIVSLOT value (the 16ths we + * calculated by not multiplying the baud by 16) as it + * is easy enough to recalculate. */ - if (strcmp(src.name, clkp->name) == 0) { - s3c24xx_serial_setsource(port, clkp); - s3c24xx_serial_getsource(port, &src); - } - - clkp->divisor = src.divisor; - } - - s3c24xx_serial_calcbaud(res, port, clkp, baud); - best = res; - resptr = best + 1; - } else { - resptr = res; - - for (i = 0; i < cfg->clocks_size; i++, clkp++) { - if (s3c24xx_serial_calcbaud(resptr, port, clkp, baud)) - resptr++; + quot = div / 16; + baud = rate / div; + } else { + quot = (rate + (8 * req_baud)) / (16 * req_baud); + baud = rate / (quot * 16); } - } - - /* ok, we now need to select the best clock we found */ - - if (!best) { - unsigned int deviation = (1<<30)|((1<<30)-1); - int calc_deviation; + quot--; - for (sptr = res; sptr < resptr; sptr++) { - calc_deviation = baud - sptr->calc; - if (calc_deviation < 0) - calc_deviation = -calc_deviation; + calc_deviation = req_baud - baud; + if (calc_deviation < 0) + calc_deviation = -calc_deviation; - if (calc_deviation < deviation) { - best = sptr; - deviation = calc_deviation; - } + if (calc_deviation < deviation) { + *best_clk = clk; + best_quot = quot; + *clk_num = cnt; + deviation = calc_deviation; } } - /* store results to pass back */ - - *clksrc = best->clksrc; - *clk = best->src; - - return best->quot; + return best_quot; } /* udivslot_table[] @@ -735,10 +684,9 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); - struct s3c24xx_uart_clksrc *clksrc = NULL; struct clk *clk = NULL; unsigned long flags; - unsigned int baud, quot; + unsigned int baud, quot, clk_sel = 0; unsigned int ulcon; unsigned int umcon; unsigned int udivslot = 0; @@ -754,17 +702,16 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, */ baud = uart_get_baud_rate(port, termios, old, 0, 115200*8); - + quot = s3c24xx_serial_getclk(ourport, baud, &clk, &clk_sel); if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) quot = port->custom_divisor; - else - quot = s3c24xx_serial_getclk(port, &clksrc, &clk, baud); + if (!clk) + return; /* check to see if we need to change clock source */ - if (ourport->clksrc != clksrc || ourport->baudclk != clk) { - dbg("selecting clock %p\n", clk); - s3c24xx_serial_setsource(port, clksrc); + if (ourport->baudclk != clk) { + s3c24xx_serial_setsource(port, clk_sel); if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { clk_disable(ourport->baudclk); @@ -773,7 +720,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, clk_enable(clk); - ourport->clksrc = clksrc; ourport->baudclk = clk; ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; } @@ -1020,16 +966,29 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS /* s3c24xx_serial_resetport * - * wrapper to call the specific reset for this port (reset the fifos - * and the settings) + * reset the fifos and other the settings. */ -static inline int s3c24xx_serial_resetport(struct uart_port *port, - struct s3c2410_uartcfg *cfg) +static void s3c24xx_serial_resetport(struct uart_port *port, + struct s3c2410_uartcfg *cfg) { struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); + unsigned long ucon = rd_regl(port, S3C2410_UCON); + unsigned int ucon_mask; + + ucon_mask = info->clksel_mask; + if (info->type == PORT_S3C2440) + ucon_mask |= S3C2440_UCON0_DIVMASK; - return (info->reset_port)(port, cfg); + ucon &= ucon_mask; + wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); + + /* reset both fifos */ + wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); + wr_regl(port, S3C2410_UFCON, cfg->ufcon); + + /* some delay is required after fifo reset */ + udelay(1); } @@ -1121,11 +1080,10 @@ static inline void s3c24xx_serial_cpufreq_deregister(struct s3c24xx_uart_port *p */ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, - struct s3c24xx_uart_info *info, struct platform_device *platdev) { struct uart_port *port = &ourport->port; - struct s3c2410_uartcfg *cfg; + struct s3c2410_uartcfg *cfg = ourport->cfg; struct resource *res; int ret; @@ -1134,30 +1092,16 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, if (platdev == NULL) return -ENODEV; - cfg = s3c24xx_dev_to_cfg(&platdev->dev); - if (port->mapbase != 0) return 0; - if (cfg->hwport > CONFIG_SERIAL_SAMSUNG_UARTS) { - printk(KERN_ERR "%s: port %d bigger than %d\n", __func__, - cfg->hwport, CONFIG_SERIAL_SAMSUNG_UARTS); - return -ERANGE; - } - /* setup info for port */ port->dev = &platdev->dev; - ourport->info = info; /* Startup sequence is different for s3c64xx and higher SoC's */ if (s3c24xx_serial_has_interrupt_mask(port)) s3c24xx_serial_ops.startup = s3c64xx_serial_startup; - /* copy the info in from provided structure */ - ourport->port.fifosize = info->fifosize; - - dbg("s3c24xx_serial_init_port: %p (hw %d)...\n", port, cfg->hwport); - port->uartclk = 1; if (cfg->uart_flags & UPF_CONS_FLOW) { @@ -1215,43 +1159,74 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev, struct uart_port *port = s3c24xx_dev_to_port(dev); struct s3c24xx_uart_port *ourport = to_ourport(port); - return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->clksrc->name); + return snprintf(buf, PAGE_SIZE, "* %s\n", ourport->baudclk->name); } static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL); + /* Device driver serial port probe */ +static const struct of_device_id s3c24xx_uart_dt_match[]; static int probe_index; -int s3c24xx_serial_probe(struct platform_device *dev, - struct s3c24xx_uart_info *info) +static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data( + struct platform_device *pdev) +{ +#ifdef CONFIG_OF + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(s3c24xx_uart_dt_match, pdev->dev.of_node); + return (struct s3c24xx_serial_drv_data *)match->data; + } +#endif + return (struct s3c24xx_serial_drv_data *) + platform_get_device_id(pdev)->driver_data; +} + +static int s3c24xx_serial_probe(struct platform_device *pdev) { struct s3c24xx_uart_port *ourport; int ret; - dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index); + dbg("s3c24xx_serial_probe(%p) %d\n", pdev, probe_index); ourport = &s3c24xx_serial_ports[probe_index]; + + ourport->drv_data = s3c24xx_get_driver_data(pdev); + if (!ourport->drv_data) { + dev_err(&pdev->dev, "could not find driver data\n"); + return -ENODEV; + } + + ourport->info = ourport->drv_data->info; + ourport->cfg = (pdev->dev.platform_data) ? + (struct s3c2410_uartcfg *)pdev->dev.platform_data : + ourport->drv_data->def_cfg; + + ourport->port.fifosize = (ourport->info->fifosize) ? + ourport->info->fifosize : + ourport->drv_data->fifosize[probe_index]; + probe_index++; dbg("%s: initialising port %p...\n", __func__, ourport); - ret = s3c24xx_serial_init_port(ourport, info, dev); + ret = s3c24xx_serial_init_port(ourport, pdev); if (ret < 0) goto probe_err; dbg("%s: adding port\n", __func__); uart_add_one_port(&s3c24xx_uart_drv, &ourport->port); - platform_set_drvdata(dev, &ourport->port); + platform_set_drvdata(pdev, &ourport->port); - ret = device_create_file(&dev->dev, &dev_attr_clock_source); + ret = device_create_file(&pdev->dev, &dev_attr_clock_source); if (ret < 0) - printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__); + dev_err(&pdev->dev, "failed to add clock source attr.\n"); ret = s3c24xx_serial_cpufreq_register(ourport); if (ret < 0) - dev_err(&dev->dev, "failed to add cpufreq notifier\n"); + dev_err(&pdev->dev, "failed to add cpufreq notifier\n"); return 0; @@ -1259,9 +1234,7 @@ int s3c24xx_serial_probe(struct platform_device *dev, return ret; } -EXPORT_SYMBOL_GPL(s3c24xx_serial_probe); - -int __devexit s3c24xx_serial_remove(struct platform_device *dev) +static int __devexit s3c24xx_serial_remove(struct platform_device *dev) { struct uart_port *port = s3c24xx_dev_to_port(&dev->dev); @@ -1274,8 +1247,6 @@ int __devexit s3c24xx_serial_remove(struct platform_device *dev) return 0; } -EXPORT_SYMBOL_GPL(s3c24xx_serial_remove); - /* UART power management code */ #ifdef CONFIG_PM_SLEEP static int s3c24xx_serial_suspend(struct device *dev) @@ -1315,41 +1286,6 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = { #define SERIAL_SAMSUNG_PM_OPS NULL #endif /* CONFIG_PM_SLEEP */ -int s3c24xx_serial_init(struct platform_driver *drv, - struct s3c24xx_uart_info *info) -{ - dbg("s3c24xx_serial_init(%p,%p)\n", drv, info); - - drv->driver.pm = SERIAL_SAMSUNG_PM_OPS; - - return platform_driver_register(drv); -} - -EXPORT_SYMBOL_GPL(s3c24xx_serial_init); - -/* module initialisation code */ - -static int __init s3c24xx_serial_modinit(void) -{ - int ret; - - ret = uart_register_driver(&s3c24xx_uart_drv); - if (ret < 0) { - printk(KERN_ERR "failed to register UART driver\n"); - return -1; - } - - return 0; -} - -static void __exit s3c24xx_serial_modexit(void) -{ - uart_unregister_driver(&s3c24xx_uart_drv); -} - -module_init(s3c24xx_serial_modinit); -module_exit(s3c24xx_serial_modexit); - /* Console code */ #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE @@ -1395,12 +1331,13 @@ static void __init s3c24xx_serial_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { - struct s3c24xx_uart_clksrc clksrc; struct clk *clk; unsigned int ulcon; unsigned int ucon; unsigned int ubrdiv; unsigned long rate; + unsigned int clk_sel; + char clk_name[MAX_CLK_NAME_LENGTH]; ulcon = rd_regl(port, S3C2410_ULCON); ucon = rd_regl(port, S3C2410_UCON); @@ -1445,44 +1382,21 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, /* now calculate the baud rate */ - s3c24xx_serial_getsource(port, &clksrc); + clk_sel = s3c24xx_serial_getsource(port); + sprintf(clk_name, "clk_uart_baud%d", clk_sel); - clk = clk_get(port->dev, clksrc.name); + clk = clk_get(port->dev, clk_name); if (!IS_ERR(clk) && clk != NULL) - rate = clk_get_rate(clk) / clksrc.divisor; + rate = clk_get_rate(clk); else rate = 1; - *baud = rate / (16 * (ubrdiv + 1)); dbg("calculated baud %d\n", *baud); } } -/* s3c24xx_serial_init_ports - * - * initialise the serial ports from the machine provided initialisation - * data. -*/ - -static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info) -{ - struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; - struct platform_device **platdev_ptr; - int i; - - dbg("s3c24xx_serial_init_ports: initialising ports...\n"); - - platdev_ptr = s3c24xx_uart_devs; - - for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { - s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr); - } - - return 0; -} - static int __init s3c24xx_serial_console_setup(struct console *co, char *options) { @@ -1526,11 +1440,6 @@ s3c24xx_serial_console_setup(struct console *co, char *options) return uart_set_options(port, co, baud, parity, bits, flow); } -/* s3c24xx_serial_initconsole - * - * initialise the console from one of the uart drivers -*/ - static struct console s3c24xx_serial_console = { .name = S3C24XX_SERIAL_NAME, .device = uart_console_device, @@ -1540,34 +1449,250 @@ static struct console s3c24xx_serial_console = { .setup = s3c24xx_serial_console_setup, .data = &s3c24xx_uart_drv, }; +#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ -int s3c24xx_serial_initconsole(struct platform_driver *drv, - struct s3c24xx_uart_info **info) +#ifdef CONFIG_CPU_S3C2410 +static struct s3c24xx_serial_drv_data s3c2410_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { + .name = "Samsung S3C2410 UART", + .type = PORT_S3C2410, + .fifosize = 16, + .rx_fifomask = S3C2410_UFSTAT_RXMASK, + .rx_fifoshift = S3C2410_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2410_UFSTAT_RXFULL, + .tx_fifofull = S3C2410_UFSTAT_TXFULL, + .tx_fifomask = S3C2410_UFSTAT_TXMASK, + .tx_fifoshift = S3C2410_UFSTAT_TXSHIFT, + .def_clk_sel = S3C2410_UCON_CLKSEL0, + .num_clks = 2, + .clksel_mask = S3C2410_UCON_CLKMASK, + .clksel_shift = S3C2410_UCON_CLKSHIFT, + }, + .def_cfg = &(struct s3c2410_uartcfg) { + .ucon = S3C2410_UCON_DEFAULT, + .ufcon = S3C2410_UFCON_DEFAULT, + }, +}; +#define S3C2410_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2410_serial_drv_data) +#else +#define S3C2410_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#endif -{ - struct platform_device *dev = s3c24xx_uart_devs[0]; +#ifdef CONFIG_CPU_S3C2412 +static struct s3c24xx_serial_drv_data s3c2412_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { + .name = "Samsung S3C2412 UART", + .type = PORT_S3C2412, + .fifosize = 64, + .has_divslot = 1, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .def_clk_sel = S3C2410_UCON_CLKSEL2, + .num_clks = 4, + .clksel_mask = S3C2412_UCON_CLKMASK, + .clksel_shift = S3C2412_UCON_CLKSHIFT, + }, + .def_cfg = &(struct s3c2410_uartcfg) { + .ucon = S3C2410_UCON_DEFAULT, + .ufcon = S3C2410_UFCON_DEFAULT, + }, +}; +#define S3C2412_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2412_serial_drv_data) +#else +#define S3C2412_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#endif - dbg("s3c24xx_serial_initconsole\n"); +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2416) || \ + defined(CONFIG_CPU_S3C2443) +static struct s3c24xx_serial_drv_data s3c2440_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { + .name = "Samsung S3C2440 UART", + .type = PORT_S3C2440, + .fifosize = 64, + .has_divslot = 1, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .def_clk_sel = S3C2410_UCON_CLKSEL2, + .num_clks = 4, + .clksel_mask = S3C2412_UCON_CLKMASK, + .clksel_shift = S3C2412_UCON_CLKSHIFT, + }, + .def_cfg = &(struct s3c2410_uartcfg) { + .ucon = S3C2410_UCON_DEFAULT, + .ufcon = S3C2410_UFCON_DEFAULT, + }, +}; +#define S3C2440_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c2440_serial_drv_data) +#else +#define S3C2440_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#endif - /* select driver based on the cpu */ +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410) || \ + defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450) || \ + defined(CONFIG_CPU_S5PC100) +static struct s3c24xx_serial_drv_data s3c6400_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { + .name = "Samsung S3C6400 UART", + .type = PORT_S3C6400, + .fifosize = 64, + .has_divslot = 1, + .rx_fifomask = S3C2440_UFSTAT_RXMASK, + .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, + .rx_fifofull = S3C2440_UFSTAT_RXFULL, + .tx_fifofull = S3C2440_UFSTAT_TXFULL, + .tx_fifomask = S3C2440_UFSTAT_TXMASK, + .tx_fifoshift = S3C2440_UFSTAT_TXSHIFT, + .def_clk_sel = S3C2410_UCON_CLKSEL2, + .num_clks = 4, + .clksel_mask = S3C6400_UCON_CLKMASK, + .clksel_shift = S3C6400_UCON_CLKSHIFT, + }, + .def_cfg = &(struct s3c2410_uartcfg) { + .ucon = S3C2410_UCON_DEFAULT, + .ufcon = S3C2410_UFCON_DEFAULT, + }, +}; +#define S3C6400_SERIAL_DRV_DATA ((kernel_ulong_t)&s3c6400_serial_drv_data) +#else +#define S3C6400_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#endif - if (dev == NULL) { - printk(KERN_ERR "s3c24xx: no devices for console init\n"); - return 0; - } +#ifdef CONFIG_CPU_S5PV210 +static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { + .name = "Samsung S5PV210 UART", + .type = PORT_S3C6400, + .has_divslot = 1, + .rx_fifomask = S5PV210_UFSTAT_RXMASK, + .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, + .rx_fifofull = S5PV210_UFSTAT_RXFULL, + .tx_fifofull = S5PV210_UFSTAT_TXFULL, + .tx_fifomask = S5PV210_UFSTAT_TXMASK, + .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, + .def_clk_sel = S3C2410_UCON_CLKSEL0, + .num_clks = 2, + .clksel_mask = S5PV210_UCON_CLKMASK, + .clksel_shift = S5PV210_UCON_CLKSHIFT, + }, + .def_cfg = &(struct s3c2410_uartcfg) { + .ucon = S5PV210_UCON_DEFAULT, + .ufcon = S5PV210_UFCON_DEFAULT, + }, + .fifosize = { 256, 64, 16, 16 }, +}; +#define S5PV210_SERIAL_DRV_DATA ((kernel_ulong_t)&s5pv210_serial_drv_data) +#else +#define S5PV210_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#endif - if (strcmp(dev->name, drv->driver.name) != 0) - return 0; +#ifdef CONFIG_CPU_EXYNOS4210 +static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = { + .info = &(struct s3c24xx_uart_info) { + .name = "Samsung Exynos4 UART", + .type = PORT_S3C6400, + .has_divslot = 1, + .rx_fifomask = S5PV210_UFSTAT_RXMASK, + .rx_fifoshift = S5PV210_UFSTAT_RXSHIFT, + .rx_fifofull = S5PV210_UFSTAT_RXFULL, + .tx_fifofull = S5PV210_UFSTAT_TXFULL, + .tx_fifomask = S5PV210_UFSTAT_TXMASK, + .tx_fifoshift = S5PV210_UFSTAT_TXSHIFT, + .def_clk_sel = S3C2410_UCON_CLKSEL0, + .num_clks = 1, + .clksel_mask = 0, + .clksel_shift = 0, + }, + .def_cfg = &(struct s3c2410_uartcfg) { + .ucon = S5PV210_UCON_DEFAULT, + .ufcon = S5PV210_UFCON_DEFAULT, + .has_fracval = 1, + }, + .fifosize = { 256, 64, 16, 16 }, +}; +#define EXYNOS4210_SERIAL_DRV_DATA ((kernel_ulong_t)&exynos4210_serial_drv_data) +#else +#define EXYNOS4210_SERIAL_DRV_DATA (kernel_ulong_t)NULL +#endif - s3c24xx_serial_console.data = &s3c24xx_uart_drv; - s3c24xx_serial_init_ports(info); +static struct platform_device_id s3c24xx_serial_driver_ids[] = { + { + .name = "s3c2410-uart", + .driver_data = S3C2410_SERIAL_DRV_DATA, + }, { + .name = "s3c2412-uart", + .driver_data = S3C2412_SERIAL_DRV_DATA, + }, { + .name = "s3c2440-uart", + .driver_data = S3C2440_SERIAL_DRV_DATA, + }, { + .name = "s3c6400-uart", + .driver_data = S3C6400_SERIAL_DRV_DATA, + }, { + .name = "s5pv210-uart", + .driver_data = S5PV210_SERIAL_DRV_DATA, + }, { + .name = "exynos4210-uart", + .driver_data = EXYNOS4210_SERIAL_DRV_DATA, + }, + { }, +}; +MODULE_DEVICE_TABLE(platform, s3c24xx_serial_driver_ids); - register_console(&s3c24xx_serial_console); - return 0; +#ifdef CONFIG_OF +static const struct of_device_id s3c24xx_uart_dt_match[] = { + { .compatible = "samsung,exynos4210-uart", + .data = (void *)EXYNOS4210_SERIAL_DRV_DATA }, + {}, +}; +MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match); +#else +#define s3c24xx_uart_dt_match NULL +#endif + +static struct platform_driver samsung_serial_driver = { + .probe = s3c24xx_serial_probe, + .remove = __devexit_p(s3c24xx_serial_remove), + .id_table = s3c24xx_serial_driver_ids, + .driver = { + .name = "samsung-uart", + .owner = THIS_MODULE, + .pm = SERIAL_SAMSUNG_PM_OPS, + .of_match_table = s3c24xx_uart_dt_match, + }, +}; + +/* module initialisation code */ + +static int __init s3c24xx_serial_modinit(void) +{ + int ret; + + ret = uart_register_driver(&s3c24xx_uart_drv); + if (ret < 0) { + printk(KERN_ERR "failed to register UART driver\n"); + return -1; + } + + return platform_driver_register(&samsung_serial_driver); } -#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */ +static void __exit s3c24xx_serial_modexit(void) +{ + uart_unregister_driver(&s3c24xx_uart_drv); +} + +module_init(s3c24xx_serial_modinit); +module_exit(s3c24xx_serial_modexit); +MODULE_ALIAS("platform:samsung-uart"); MODULE_DESCRIPTION("Samsung SoC Serial port driver"); MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index 8e87b788e5c6..1a4bca3e4179 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h @@ -19,20 +19,25 @@ struct s3c24xx_uart_info { unsigned long tx_fifomask; unsigned long tx_fifoshift; unsigned long tx_fifofull; + unsigned int def_clk_sel; + unsigned long num_clks; + unsigned long clksel_mask; + unsigned long clksel_shift; /* uart port features */ unsigned int has_divslot:1; - /* clock source control */ - - int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); - int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); - /* uart controls */ int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *); }; +struct s3c24xx_serial_drv_data { + struct s3c24xx_uart_info *info; + struct s3c2410_uartcfg *def_cfg; + unsigned int fifosize[CONFIG_SERIAL_SAMSUNG_UARTS]; +}; + struct s3c24xx_uart_port { unsigned char rx_claimed; unsigned char tx_claimed; @@ -43,10 +48,13 @@ struct s3c24xx_uart_port { unsigned int tx_irq; struct s3c24xx_uart_info *info; - struct s3c24xx_uart_clksrc *clksrc; struct clk *clk; struct clk *baudclk; struct uart_port port; + struct s3c24xx_serial_drv_data *drv_data; + + /* reference to platform data */ + struct s3c2410_uartcfg *cfg; #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; @@ -56,7 +64,6 @@ struct s3c24xx_uart_port { /* conversion functions */ #define s3c24xx_dev_to_port(__dev) (struct uart_port *)dev_get_drvdata(__dev) -#define s3c24xx_dev_to_cfg(__dev) (struct s3c2410_uartcfg *)((__dev)->platform_data) /* register access controls */ @@ -69,17 +76,6 @@ struct s3c24xx_uart_port { #define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg)) #define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg)) -extern int s3c24xx_serial_probe(struct platform_device *dev, - struct s3c24xx_uart_info *uart); - -extern int __devexit s3c24xx_serial_remove(struct platform_device *dev); - -extern int s3c24xx_serial_initconsole(struct platform_driver *drv, - struct s3c24xx_uart_info **uart); - -extern int s3c24xx_serial_init(struct platform_driver *drv, - struct s3c24xx_uart_info *info); - #ifdef CONFIG_SERIAL_SAMSUNG_DEBUG extern void printascii(const char *); diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 791f11bed606..75823a1abeb6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -48,6 +48,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_DAVINCI_DA8XX default y if ARCH_CNS3XXX default y if PLAT_SPEAR + default y if ARCH_EXYNOS # PPC: default y if STB03xxx default y if PPC_MPC52xx diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e8c564a53346..a8078d0638fa 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1458,6 +1458,16 @@ static const struct usb_device_id acm_ids[] = { }, { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ }, + /* Motorola H24 HSPA module: */ + { USB_DEVICE(0x22b8, 0x2d91) }, /* modem */ + { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */ + { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */ + { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */ + { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */ + { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */ + { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */ + { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */ + { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on data interface instead of diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index c39d58860fa0..1a6f415c0d02 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2975,6 +2975,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) fsg_common_put(common); usb_free_descriptors(fsg->function.descriptors); usb_free_descriptors(fsg->function.hs_descriptors); + usb_free_descriptors(fsg->function.ss_descriptors); kfree(fsg); } diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 060e0e2b1ae6..eea85dc16826 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -371,6 +371,12 @@ config USB_OHCI_SH Enables support for the on-chip OHCI controller on the SuperH. If you use the PCI OHCI controller, this option is not necessary. +config USB_OHCI_EXYNOS + boolean "OHCI support for Samsung EXYNOS SoC Series" + depends on USB_OHCI_HCD && ARCH_EXYNOS + help + Enable support for the Samsung Exynos SOC's on-chip OHCI controller. + config USB_CNS3XXX_OHCI bool "Cavium CNS3XXX OHCI Module" depends on USB_OHCI_HCD && ARCH_CNS3XXX diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index e39b0297bad1..568cefbd63a2 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -41,6 +41,7 @@ #include <linux/usb/ulpi.h> #include <plat/usb.h> #include <linux/regulator/consumer.h> +#include <linux/pm_runtime.h> /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) @@ -190,11 +191,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) } } - ret = omap_usbhs_enable(dev); - if (ret) { - dev_err(dev, "failed to start usbhs with err %d\n", ret); - goto err_enable; - } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); /* * An undocumented "feature" in the OMAP3 EHCI controller, @@ -240,11 +238,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) return 0; err_add_hcd: - omap_usbhs_disable(dev); - -err_enable: disable_put_regulator(pdata); - usb_put_hcd(hcd); + pm_runtime_put_sync(dev); err_io: iounmap(regs); @@ -266,10 +261,12 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) struct usb_hcd *hcd = dev_get_drvdata(dev); usb_remove_hcd(hcd); - omap_usbhs_disable(dev); disable_put_regulator(dev->platform_data); iounmap(hcd->regs); usb_put_hcd(hcd); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return 0; } diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c new file mode 100644 index 000000000000..55aa35aa3d7b --- /dev/null +++ b/drivers/usb/host/ohci-exynos.c @@ -0,0 +1,274 @@ +/* + * SAMSUNG EXYNOS USB HOST OHCI Controller + * + * Copyright (C) 2011 Samsung Electronics Co.Ltd + * Author: Jingoo Han <jg1.han@samsung.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <mach/ohci.h> +#include <plat/usb-phy.h> + +struct exynos_ohci_hcd { + struct device *dev; + struct usb_hcd *hcd; + struct clk *clk; +}; + +static int ohci_exynos_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); + + ret = ohci_init(ohci); + if (ret < 0) + return ret; + + ret = ohci_run(ohci); + if (ret < 0) { + err("can't start %s", hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } + + return 0; +} + +static const struct hc_driver exynos_ohci_hc_driver = { + .description = hcd_name, + .product_desc = "EXYNOS OHCI Host Controller", + .hcd_priv_size = sizeof(struct ohci_hcd), + + .irq = ohci_irq, + .flags = HCD_MEMORY|HCD_USB11, + + .start = ohci_exynos_start, + .stop = ohci_stop, + .shutdown = ohci_shutdown, + + .get_frame_number = ohci_get_frame, + + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + +static int __devinit exynos_ohci_probe(struct platform_device *pdev) +{ + struct exynos4_ohci_platdata *pdata; + struct exynos_ohci_hcd *exynos_ohci; + struct usb_hcd *hcd; + struct ohci_hcd *ohci; + struct resource *res; + int irq; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "No platform data defined\n"); + return -EINVAL; + } + + exynos_ohci = kzalloc(sizeof(struct exynos_ohci_hcd), GFP_KERNEL); + if (!exynos_ohci) + return -ENOMEM; + + exynos_ohci->dev = &pdev->dev; + + hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, + dev_name(&pdev->dev)); + if (!hcd) { + dev_err(&pdev->dev, "Unable to create HCD\n"); + err = -ENOMEM; + goto fail_hcd; + } + + exynos_ohci->hcd = hcd; + exynos_ohci->clk = clk_get(&pdev->dev, "usbhost"); + + if (IS_ERR(exynos_ohci->clk)) { + dev_err(&pdev->dev, "Failed to get usbhost clock\n"); + err = PTR_ERR(exynos_ohci->clk); + goto fail_clk; + } + + err = clk_enable(exynos_ohci->clk); + if (err) + goto fail_clken; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Failed to get I/O memory\n"); + err = -ENXIO; + goto fail_io; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->regs = ioremap(res->start, resource_size(res)); + if (!hcd->regs) { + dev_err(&pdev->dev, "Failed to remap I/O memory\n"); + err = -ENOMEM; + goto fail_io; + } + + irq = platform_get_irq(pdev, 0); + if (!irq) { + dev_err(&pdev->dev, "Failed to get IRQ\n"); + err = -ENODEV; + goto fail; + } + + if (pdata->phy_init) + pdata->phy_init(pdev, S5P_USB_PHY_HOST); + + ohci = hcd_to_ohci(hcd); + ohci_hcd_init(ohci); + + err = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (err) { + dev_err(&pdev->dev, "Failed to add USB HCD\n"); + goto fail; + } + + platform_set_drvdata(pdev, exynos_ohci); + + return 0; + +fail: + iounmap(hcd->regs); +fail_io: + clk_disable(exynos_ohci->clk); +fail_clken: + clk_put(exynos_ohci->clk); +fail_clk: + usb_put_hcd(hcd); +fail_hcd: + kfree(exynos_ohci); + return err; +} + +static int __devexit exynos_ohci_remove(struct platform_device *pdev) +{ + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); + struct usb_hcd *hcd = exynos_ohci->hcd; + + usb_remove_hcd(hcd); + + if (pdata && pdata->phy_exit) + pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + + iounmap(hcd->regs); + + clk_disable(exynos_ohci->clk); + clk_put(exynos_ohci->clk); + + usb_put_hcd(hcd); + kfree(exynos_ohci); + + return 0; +} + +static void exynos_ohci_shutdown(struct platform_device *pdev) +{ + struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); + struct usb_hcd *hcd = exynos_ohci->hcd; + + if (hcd->driver->shutdown) + hcd->driver->shutdown(hcd); +} + +#ifdef CONFIG_PM +static int exynos_ohci_suspend(struct device *dev) +{ + struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); + struct usb_hcd *hcd = exynos_ohci->hcd; + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + struct platform_device *pdev = to_platform_device(dev); + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + unsigned long flags; + int rc = 0; + + /* + * Root hub was already suspended. Disable irq emission and + * mark HW unaccessible, bail out if RH has been resumed. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + * + * This is still racy as hcd->state is manipulated outside of + * any locks =P But that will be a different fix. + */ + spin_lock_irqsave(&ohci->lock, flags); + if (hcd->state != HC_STATE_SUSPENDED && hcd->state != HC_STATE_HALT) { + rc = -EINVAL; + goto fail; + } + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + if (pdata && pdata->phy_exit) + pdata->phy_exit(pdev, S5P_USB_PHY_HOST); +fail: + spin_unlock_irqrestore(&ohci->lock, flags); + + return rc; +} + +static int exynos_ohci_resume(struct device *dev) +{ + struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); + struct usb_hcd *hcd = exynos_ohci->hcd; + struct platform_device *pdev = to_platform_device(dev); + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + + if (pdata && pdata->phy_init) + pdata->phy_init(pdev, S5P_USB_PHY_HOST); + + /* Mark hardware accessible again as we are out of D3 state by now */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + ohci_finish_controller_resume(hcd); + + return 0; +} +#else +#define exynos_ohci_suspend NULL +#define exynos_ohci_resume NULL +#endif + +static const struct dev_pm_ops exynos_ohci_pm_ops = { + .suspend = exynos_ohci_suspend, + .resume = exynos_ohci_resume, +}; + +static struct platform_driver exynos_ohci_driver = { + .probe = exynos_ohci_probe, + .remove = __devexit_p(exynos_ohci_remove), + .shutdown = exynos_ohci_shutdown, + .driver = { + .name = "exynos-ohci", + .owner = THIS_MODULE, + .pm = &exynos_ohci_pm_ops, + } +}; + +MODULE_ALIAS("platform:exynos-ohci"); +MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index b2639191549e..a1006ff79384 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1005,6 +1005,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif +#ifdef CONFIG_USB_OHCI_EXYNOS +#include "ohci-exynos.c" +#define PLATFORM_DRIVER exynos_ohci_driver +#endif + #ifdef CONFIG_USB_OHCI_HCD_OMAP1 #include "ohci-omap.c" #define OMAP1_PLATFORM_DRIVER ohci_hcd_omap_driver diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 516ebc4d6cc2..1b8133b6e451 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -31,6 +31,7 @@ #include <linux/platform_device.h> #include <plat/usb.h> +#include <linux/pm_runtime.h> /*-------------------------------------------------------------------------*/ @@ -134,7 +135,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) int irq; if (usb_disabled()) - goto err_end; + return -ENODEV; if (!dev->parent) { dev_err(dev, "Missing parent device\n"); @@ -172,11 +173,8 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) hcd->rsrc_len = resource_size(res); hcd->regs = regs; - ret = omap_usbhs_enable(dev); - if (ret) { - dev_dbg(dev, "failed to start ohci\n"); - goto err_end; - } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -189,9 +187,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) return 0; err_add_hcd: - omap_usbhs_disable(dev); - -err_end: + pm_runtime_put_sync(dev); usb_put_hcd(hcd); err_io: @@ -220,9 +216,9 @@ static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev) iounmap(hcd->regs); usb_remove_hcd(hcd); - omap_usbhs_disable(dev); + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); usb_put_hcd(hcd); - return 0; } diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 053f86d70009..ad96a3896729 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -349,7 +349,7 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod) if (mod->irq_attch) intenb1 |= ATTCHE; - if (mod->irq_attch) + if (mod->irq_dtch) intenb1 |= DTCHE; if (mod->irq_sign) diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index bade761a1e52..7955de589951 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1267,6 +1267,7 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv) dev_err(dev, "Failed to create hcd\n"); return -ENOMEM; } + hcd->has_tt = 1; /* for low/full speed */ pipe_info = kzalloc(sizeof(*pipe_info) * pipe_size, GFP_KERNEL); if (!pipe_info) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e3426602dc82..6dd64534fad0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -663,7 +663,12 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 8e964b91c447..284798aaf8b1 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -166,7 +166,7 @@ retry: /* * Get IO TLB memory from any location. */ - xen_io_tlb_start = alloc_bootmem(bytes); + xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); if (!xen_io_tlb_start) { m = "Cannot allocate Xen-SWIOTLB buffer!\n"; goto error; @@ -179,7 +179,7 @@ retry: bytes, xen_io_tlb_nslabs); if (rc) { - free_bootmem(__pa(xen_io_tlb_start), bytes); + free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); m = "Failed to get contiguous memory for DMA from Xen!\n"\ "You either: don't have the permissions, do not have"\ " enough free memory under 4GB, or the hypervisor memory"\ diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 7ec14097fef1..cb97174e2366 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -64,6 +64,8 @@ struct btrfs_worker_thread { int idle; }; +static int __btrfs_start_workers(struct btrfs_workers *workers); + /* * btrfs_start_workers uses kthread_run, which can block waiting for memory * for a very long time. It will actually throttle on page writeback, @@ -88,27 +90,10 @@ static void start_new_worker_func(struct btrfs_work *work) { struct worker_start *start; start = container_of(work, struct worker_start, work); - btrfs_start_workers(start->queue, 1); + __btrfs_start_workers(start->queue); kfree(start); } -static int start_new_worker(struct btrfs_workers *queue) -{ - struct worker_start *start; - int ret; - - start = kzalloc(sizeof(*start), GFP_NOFS); - if (!start) - return -ENOMEM; - - start->work.func = start_new_worker_func; - start->queue = queue; - ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work); - if (ret) - kfree(start); - return ret; -} - /* * helper function to move a thread onto the idle list after it * has finished some requests. @@ -153,12 +138,20 @@ static void check_busy_worker(struct btrfs_worker_thread *worker) static void check_pending_worker_creates(struct btrfs_worker_thread *worker) { struct btrfs_workers *workers = worker->workers; + struct worker_start *start; unsigned long flags; rmb(); if (!workers->atomic_start_pending) return; + start = kzalloc(sizeof(*start), GFP_NOFS); + if (!start) + return; + + start->work.func = start_new_worker_func; + start->queue = workers; + spin_lock_irqsave(&workers->lock, flags); if (!workers->atomic_start_pending) goto out; @@ -170,10 +163,11 @@ static void check_pending_worker_creates(struct btrfs_worker_thread *worker) workers->num_workers_starting += 1; spin_unlock_irqrestore(&workers->lock, flags); - start_new_worker(workers); + btrfs_queue_worker(workers->atomic_worker_start, &start->work); return; out: + kfree(start); spin_unlock_irqrestore(&workers->lock, flags); } @@ -331,7 +325,7 @@ again: run_ordered_completions(worker->workers, work); check_pending_worker_creates(worker); - + cond_resched(); } spin_lock_irq(&worker->lock); @@ -462,56 +456,55 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, * starts new worker threads. This does not enforce the max worker * count in case you need to temporarily go past it. */ -static int __btrfs_start_workers(struct btrfs_workers *workers, - int num_workers) +static int __btrfs_start_workers(struct btrfs_workers *workers) { struct btrfs_worker_thread *worker; int ret = 0; - int i; - for (i = 0; i < num_workers; i++) { - worker = kzalloc(sizeof(*worker), GFP_NOFS); - if (!worker) { - ret = -ENOMEM; - goto fail; - } + worker = kzalloc(sizeof(*worker), GFP_NOFS); + if (!worker) { + ret = -ENOMEM; + goto fail; + } - INIT_LIST_HEAD(&worker->pending); - INIT_LIST_HEAD(&worker->prio_pending); - INIT_LIST_HEAD(&worker->worker_list); - spin_lock_init(&worker->lock); - - atomic_set(&worker->num_pending, 0); - atomic_set(&worker->refs, 1); - worker->workers = workers; - worker->task = kthread_run(worker_loop, worker, - "btrfs-%s-%d", workers->name, - workers->num_workers + i); - if (IS_ERR(worker->task)) { - ret = PTR_ERR(worker->task); - kfree(worker); - goto fail; - } - spin_lock_irq(&workers->lock); - list_add_tail(&worker->worker_list, &workers->idle_list); - worker->idle = 1; - workers->num_workers++; - workers->num_workers_starting--; - WARN_ON(workers->num_workers_starting < 0); - spin_unlock_irq(&workers->lock); + INIT_LIST_HEAD(&worker->pending); + INIT_LIST_HEAD(&worker->prio_pending); + INIT_LIST_HEAD(&worker->worker_list); + spin_lock_init(&worker->lock); + + atomic_set(&worker->num_pending, 0); + atomic_set(&worker->refs, 1); + worker->workers = workers; + worker->task = kthread_run(worker_loop, worker, + "btrfs-%s-%d", workers->name, + workers->num_workers + 1); + if (IS_ERR(worker->task)) { + ret = PTR_ERR(worker->task); + kfree(worker); + goto fail; } + spin_lock_irq(&workers->lock); + list_add_tail(&worker->worker_list, &workers->idle_list); + worker->idle = 1; + workers->num_workers++; + workers->num_workers_starting--; + WARN_ON(workers->num_workers_starting < 0); + spin_unlock_irq(&workers->lock); + return 0; fail: - btrfs_stop_workers(workers); + spin_lock_irq(&workers->lock); + workers->num_workers_starting--; + spin_unlock_irq(&workers->lock); return ret; } -int btrfs_start_workers(struct btrfs_workers *workers, int num_workers) +int btrfs_start_workers(struct btrfs_workers *workers) { spin_lock_irq(&workers->lock); - workers->num_workers_starting += num_workers; + workers->num_workers_starting++; spin_unlock_irq(&workers->lock); - return __btrfs_start_workers(workers, num_workers); + return __btrfs_start_workers(workers); } /* @@ -568,6 +561,7 @@ static struct btrfs_worker_thread *find_worker(struct btrfs_workers *workers) struct btrfs_worker_thread *worker; unsigned long flags; struct list_head *fallback; + int ret; again: spin_lock_irqsave(&workers->lock, flags); @@ -584,7 +578,9 @@ again: workers->num_workers_starting++; spin_unlock_irqrestore(&workers->lock, flags); /* we're below the limit, start another worker */ - __btrfs_start_workers(workers, 1); + ret = __btrfs_start_workers(workers); + if (ret) + goto fallback; goto again; } } @@ -665,7 +661,7 @@ void btrfs_set_work_high_prio(struct btrfs_work *work) /* * places a struct btrfs_work into the pending queue of one of the kthreads */ -int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) +void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) { struct btrfs_worker_thread *worker; unsigned long flags; @@ -673,7 +669,7 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) /* don't requeue something already on a list */ if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags)) - goto out; + return; worker = find_worker(workers); if (workers->ordered) { @@ -712,7 +708,4 @@ int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work) if (wake) wake_up_process(worker->task); spin_unlock_irqrestore(&worker->lock, flags); - -out: - return 0; } diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h index 5077746cf85e..f34cc31fa3c9 100644 --- a/fs/btrfs/async-thread.h +++ b/fs/btrfs/async-thread.h @@ -109,8 +109,8 @@ struct btrfs_workers { char *name; }; -int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); -int btrfs_start_workers(struct btrfs_workers *workers, int num_workers); +void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work); +int btrfs_start_workers(struct btrfs_workers *workers); int btrfs_stop_workers(struct btrfs_workers *workers); void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max, struct btrfs_workers *async_starter); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 50634abef9b4..67385033323d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2692,7 +2692,8 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); int btrfs_readpage(struct file *file, struct page *page); void btrfs_evict_inode(struct inode *inode); int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc); -void btrfs_dirty_inode(struct inode *inode, int flags); +int btrfs_dirty_inode(struct inode *inode); +int btrfs_update_time(struct file *file); struct inode *btrfs_alloc_inode(struct super_block *sb); void btrfs_destroy_inode(struct inode *inode); int btrfs_drop_inode(struct inode *inode); diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 5b163572e0ca..9c1eccc2c503 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -640,8 +640,8 @@ static int btrfs_delayed_inode_reserve_metadata( * Now if src_rsv == delalloc_block_rsv we'll let it just steal since * we're accounted for. */ - if (!trans->bytes_reserved && - src_rsv != &root->fs_info->delalloc_block_rsv) { + if (!src_rsv || (!trans->bytes_reserved && + src_rsv != &root->fs_info->delalloc_block_rsv)) { ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes); /* * Since we're under a transaction reserve_metadata_bytes could diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 632f8f3cc9db..f44b3928dc2d 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2194,19 +2194,27 @@ struct btrfs_root *open_ctree(struct super_block *sb, fs_info->endio_meta_write_workers.idle_thresh = 2; fs_info->readahead_workers.idle_thresh = 2; - btrfs_start_workers(&fs_info->workers, 1); - btrfs_start_workers(&fs_info->generic_worker, 1); - btrfs_start_workers(&fs_info->submit_workers, 1); - btrfs_start_workers(&fs_info->delalloc_workers, 1); - btrfs_start_workers(&fs_info->fixup_workers, 1); - btrfs_start_workers(&fs_info->endio_workers, 1); - btrfs_start_workers(&fs_info->endio_meta_workers, 1); - btrfs_start_workers(&fs_info->endio_meta_write_workers, 1); - btrfs_start_workers(&fs_info->endio_write_workers, 1); - btrfs_start_workers(&fs_info->endio_freespace_worker, 1); - btrfs_start_workers(&fs_info->delayed_workers, 1); - btrfs_start_workers(&fs_info->caching_workers, 1); - btrfs_start_workers(&fs_info->readahead_workers, 1); + /* + * btrfs_start_workers can really only fail because of ENOMEM so just + * return -ENOMEM if any of these fail. + */ + ret = btrfs_start_workers(&fs_info->workers); + ret |= btrfs_start_workers(&fs_info->generic_worker); + ret |= btrfs_start_workers(&fs_info->submit_workers); + ret |= btrfs_start_workers(&fs_info->delalloc_workers); + ret |= btrfs_start_workers(&fs_info->fixup_workers); + ret |= btrfs_start_workers(&fs_info->endio_workers); + ret |= btrfs_start_workers(&fs_info->endio_meta_workers); + ret |= btrfs_start_workers(&fs_info->endio_meta_write_workers); + ret |= btrfs_start_workers(&fs_info->endio_write_workers); + ret |= btrfs_start_workers(&fs_info->endio_freespace_worker); + ret |= btrfs_start_workers(&fs_info->delayed_workers); + ret |= btrfs_start_workers(&fs_info->caching_workers); + ret |= btrfs_start_workers(&fs_info->readahead_workers); + if (ret) { + ret = -ENOMEM; + goto fail_sb_buffer; + } fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2ad813674d77..f5fbe576d2ba 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2822,7 +2822,7 @@ out_free: btrfs_release_path(path); out: spin_lock(&block_group->lock); - if (!ret) + if (!ret && dcs == BTRFS_DC_SETUP) block_group->cache_generation = trans->transid; block_group->disk_cache_state = dcs; spin_unlock(&block_group->lock); @@ -4204,12 +4204,17 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; u64 to_reserve = 0; + u64 csum_bytes; unsigned nr_extents = 0; + int extra_reserve = 0; int flush = 1; int ret; + /* Need to be holding the i_mutex here if we aren't free space cache */ if (btrfs_is_free_space_inode(root, inode)) flush = 0; + else + WARN_ON(!mutex_is_locked(&inode->i_mutex)); if (flush && btrfs_transaction_in_commit(root->fs_info)) schedule_timeout(1); @@ -4220,11 +4225,9 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) BTRFS_I(inode)->outstanding_extents++; if (BTRFS_I(inode)->outstanding_extents > - BTRFS_I(inode)->reserved_extents) { + BTRFS_I(inode)->reserved_extents) nr_extents = BTRFS_I(inode)->outstanding_extents - BTRFS_I(inode)->reserved_extents; - BTRFS_I(inode)->reserved_extents += nr_extents; - } /* * Add an item to reserve for updating the inode when we complete the @@ -4232,11 +4235,12 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) */ if (!BTRFS_I(inode)->delalloc_meta_reserved) { nr_extents++; - BTRFS_I(inode)->delalloc_meta_reserved = 1; + extra_reserve = 1; } to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); + csum_bytes = BTRFS_I(inode)->csum_bytes; spin_unlock(&BTRFS_I(inode)->lock); ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); @@ -4246,22 +4250,35 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) spin_lock(&BTRFS_I(inode)->lock); dropped = drop_outstanding_extent(inode); - to_free = calc_csum_metadata_size(inode, num_bytes, 0); - spin_unlock(&BTRFS_I(inode)->lock); - to_free += btrfs_calc_trans_metadata_size(root, dropped); - /* - * Somebody could have come in and twiddled with the - * reservation, so if we have to free more than we would have - * reserved from this reservation go ahead and release those - * bytes. + * If the inodes csum_bytes is the same as the original + * csum_bytes then we know we haven't raced with any free()ers + * so we can just reduce our inodes csum bytes and carry on. + * Otherwise we have to do the normal free thing to account for + * the case that the free side didn't free up its reserve + * because of this outstanding reservation. */ - to_free -= to_reserve; + if (BTRFS_I(inode)->csum_bytes == csum_bytes) + calc_csum_metadata_size(inode, num_bytes, 0); + else + to_free = calc_csum_metadata_size(inode, num_bytes, 0); + spin_unlock(&BTRFS_I(inode)->lock); + if (dropped) + to_free += btrfs_calc_trans_metadata_size(root, dropped); + if (to_free) btrfs_block_rsv_release(root, block_rsv, to_free); return ret; } + spin_lock(&BTRFS_I(inode)->lock); + if (extra_reserve) { + BTRFS_I(inode)->delalloc_meta_reserved = 1; + nr_extents--; + } + BTRFS_I(inode)->reserved_extents += nr_extents; + spin_unlock(&BTRFS_I(inode)->lock); + block_rsv_add_bytes(block_rsv, to_reserve, 1); return 0; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index dafdfa059bf6..97fbe939c050 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1167,6 +1167,8 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / (sizeof(struct page *))); + nrptrs = min(nrptrs, current->nr_dirtied_pause - current->nr_dirtied); + nrptrs = max(nrptrs, 8); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); if (!pages) return -ENOMEM; @@ -1387,7 +1389,11 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, goto out; } - file_update_time(file); + err = btrfs_update_time(file); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } BTRFS_I(inode)->sequence++; start_pos = round_down(pos, root->sectorsize); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2c984f7d4c2a..0a6b928813a4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -38,6 +38,7 @@ #include <linux/falloc.h> #include <linux/slab.h> #include <linux/ratelimit.h> +#include <linux/mount.h> #include "compat.h" #include "ctree.h" #include "disk-io.h" @@ -2031,7 +2032,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode) /* insert an orphan item to track this unlinked/truncated file */ if (insert >= 1) { ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); - BUG_ON(ret); + BUG_ON(ret && ret != -EEXIST); } /* insert an orphan item to track subvolume contains orphan files */ @@ -2158,6 +2159,38 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) if (ret && ret != -ESTALE) goto out; + if (ret == -ESTALE && root == root->fs_info->tree_root) { + struct btrfs_root *dead_root; + struct btrfs_fs_info *fs_info = root->fs_info; + int is_dead_root = 0; + + /* + * this is an orphan in the tree root. Currently these + * could come from 2 sources: + * a) a snapshot deletion in progress + * b) a free space cache inode + * We need to distinguish those two, as the snapshot + * orphan must not get deleted. + * find_dead_roots already ran before us, so if this + * is a snapshot deletion, we should find the root + * in the dead_roots list + */ + spin_lock(&fs_info->trans_lock); + list_for_each_entry(dead_root, &fs_info->dead_roots, + root_list) { + if (dead_root->root_key.objectid == + found_key.objectid) { + is_dead_root = 1; + break; + } + } + spin_unlock(&fs_info->trans_lock); + if (is_dead_root) { + /* prevent this orphan from being found again */ + key.offset = found_key.objectid - 1; + continue; + } + } /* * Inode is already gone but the orphan item is still there, * kill the orphan item. @@ -2191,7 +2224,14 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) continue; } nr_truncate++; + /* + * Need to hold the imutex for reservation purposes, not + * a huge deal here but I have a WARN_ON in + * btrfs_delalloc_reserve_space to catch offenders. + */ + mutex_lock(&inode->i_mutex); ret = btrfs_truncate(inode); + mutex_unlock(&inode->i_mutex); } else { nr_unlink++; } @@ -3327,7 +3367,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) u64 hint_byte = 0; hole_size = last_byte - cur_offset; - trans = btrfs_start_transaction(root, 2); + trans = btrfs_start_transaction(root, 3); if (IS_ERR(trans)) { err = PTR_ERR(trans); break; @@ -3337,6 +3377,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) cur_offset + hole_size, &hint_byte, 1); if (err) { + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); break; } @@ -3346,6 +3387,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) 0, hole_size, 0, hole_size, 0, 0, 0); if (err) { + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); break; } @@ -3353,6 +3395,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) btrfs_drop_extent_cache(inode, hole_start, last_byte - 1, 0); + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); } free_extent_map(em); @@ -3370,6 +3413,8 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) static int btrfs_setsize(struct inode *inode, loff_t newsize) { + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_trans_handle *trans; loff_t oldsize = i_size_read(inode); int ret; @@ -3377,16 +3422,19 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return 0; if (newsize > oldsize) { - i_size_write(inode, newsize); - btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); truncate_pagecache(inode, oldsize, newsize); ret = btrfs_cont_expand(inode, oldsize, newsize); - if (ret) { - btrfs_setsize(inode, oldsize); + if (ret) return ret; - } - mark_inode_dirty(inode); + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + i_size_write(inode, newsize); + btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); + ret = btrfs_update_inode(trans, root, inode); + btrfs_end_transaction_throttle(trans, root); } else { /* @@ -3426,9 +3474,9 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid) { setattr_copy(inode, attr); - mark_inode_dirty(inode); + err = btrfs_dirty_inode(inode); - if (attr->ia_valid & ATTR_MODE) + if (!err && attr->ia_valid & ATTR_MODE) err = btrfs_acl_chmod(inode); } @@ -4204,42 +4252,80 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc) * FIXME, needs more benchmarking...there are no reasons other than performance * to keep or drop this code. */ -void btrfs_dirty_inode(struct inode *inode, int flags) +int btrfs_dirty_inode(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; int ret; if (BTRFS_I(inode)->dummy_inode) - return; + return 0; trans = btrfs_join_transaction(root); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = btrfs_update_inode(trans, root, inode); if (ret && ret == -ENOSPC) { /* whoops, lets try again with the full transaction */ btrfs_end_transaction(trans, root); trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { - printk_ratelimited(KERN_ERR "btrfs: fail to " - "dirty inode %llu error %ld\n", - (unsigned long long)btrfs_ino(inode), - PTR_ERR(trans)); - return; - } + if (IS_ERR(trans)) + return PTR_ERR(trans); ret = btrfs_update_inode(trans, root, inode); - if (ret) { - printk_ratelimited(KERN_ERR "btrfs: fail to " - "dirty inode %llu error %d\n", - (unsigned long long)btrfs_ino(inode), - ret); - } } btrfs_end_transaction(trans, root); if (BTRFS_I(inode)->delayed_node) btrfs_balance_delayed_items(root); + + return ret; +} + +/* + * This is a copy of file_update_time. We need this so we can return error on + * ENOSPC for updating the inode in the case of file write and mmap writes. + */ +int btrfs_update_time(struct file *file) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct timespec now; + int ret; + enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; + + /* First try to exhaust all avenues to not sync */ + if (IS_NOCMTIME(inode)) + return 0; + + now = current_fs_time(inode->i_sb); + if (!timespec_equal(&inode->i_mtime, &now)) + sync_it = S_MTIME; + + if (!timespec_equal(&inode->i_ctime, &now)) + sync_it |= S_CTIME; + + if (IS_I_VERSION(inode)) + sync_it |= S_VERSION; + + if (!sync_it) + return 0; + + /* Finally allowed to write? Takes lock. */ + if (mnt_want_write_file(file)) + return 0; + + /* Only change inode inside the lock region */ + if (sync_it & S_VERSION) + inode_inc_iversion(inode); + if (sync_it & S_CTIME) + inode->i_ctime = now; + if (sync_it & S_MTIME) + inode->i_mtime = now; + ret = btrfs_dirty_inode(inode); + if (!ret) + mark_inode_dirty_sync(inode); + mnt_drop_write(file->f_path.mnt); + return ret; } /* @@ -4555,11 +4641,18 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ + + inode->i_op = &btrfs_special_inode_operations; err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { - inode->i_op = &btrfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); btrfs_update_inode(trans, root, inode); } @@ -4613,14 +4706,21 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; - inode->i_fop = &btrfs_file_operations; - inode->i_op = &btrfs_file_inode_operations; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; } out_unlock: @@ -6303,7 +6403,12 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) u64 page_start; u64 page_end; + /* Need this to keep space reservations serialized */ + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); + mutex_unlock(&inode->i_mutex); + if (!ret) + ret = btrfs_update_time(vma->vm_file); if (ret) { if (ret == -ENOMEM) ret = VM_FAULT_OOM; @@ -6515,8 +6620,9 @@ static int btrfs_truncate(struct inode *inode) /* Just need the 1 for updating the inode */ trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { - err = PTR_ERR(trans); - goto out; + ret = err = PTR_ERR(trans); + trans = NULL; + break; } } @@ -7076,14 +7182,21 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, goto out_unlock; } + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; - inode->i_fop = &btrfs_file_operations; - inode->i_op = &btrfs_file_inode_operations; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; } if (drop_inode) @@ -7353,6 +7466,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { .follow_link = page_follow_link_light, .put_link = page_put_link, .getattr = btrfs_getattr, + .setattr = btrfs_setattr, .permission = btrfs_permission, .setxattr = btrfs_setxattr, .getxattr = btrfs_getxattr, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 72d461656f60..c04f02c7d5bb 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -252,11 +252,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) trans = btrfs_join_transaction(root); BUG_ON(IS_ERR(trans)); + btrfs_update_iflags(inode); + inode->i_ctime = CURRENT_TIME; ret = btrfs_update_inode(trans, root, inode); BUG_ON(ret); - btrfs_update_iflags(inode); - inode->i_ctime = CURRENT_TIME; btrfs_end_transaction(trans, root); mnt_drop_write(file->f_path.mnt); @@ -858,8 +858,10 @@ static int cluster_pages_for_defrag(struct inode *inode, return 0; file_end = (isize - 1) >> PAGE_CACHE_SHIFT; + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_space(inode, num_pages << PAGE_CACHE_SHIFT); + mutex_unlock(&inode->i_mutex); if (ret) return ret; again: diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index dff29d5e151a..cfb55434a469 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2947,7 +2947,9 @@ static int relocate_file_extent_cluster(struct inode *inode, index = (cluster->start - offset) >> PAGE_CACHE_SHIFT; last_index = (cluster->end - offset) >> PAGE_CACHE_SHIFT; while (index <= last_index) { + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_metadata(inode, PAGE_CACHE_SIZE); + mutex_unlock(&inode->i_mutex); if (ret) goto out; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index c27bcb67f330..ddf2c90d3fc0 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1535,18 +1535,22 @@ static noinline_for_stack int scrub_supers(struct scrub_dev *sdev) static noinline_for_stack int scrub_workers_get(struct btrfs_root *root) { struct btrfs_fs_info *fs_info = root->fs_info; + int ret = 0; mutex_lock(&fs_info->scrub_lock); if (fs_info->scrub_workers_refcnt == 0) { btrfs_init_workers(&fs_info->scrub_workers, "scrub", fs_info->thread_pool_size, &fs_info->generic_worker); fs_info->scrub_workers.idle_thresh = 4; - btrfs_start_workers(&fs_info->scrub_workers, 1); + ret = btrfs_start_workers(&fs_info->scrub_workers); + if (ret) + goto out; } ++fs_info->scrub_workers_refcnt; +out: mutex_unlock(&fs_info->scrub_lock); - return 0; + return ret; } static noinline_for_stack void scrub_workers_put(struct btrfs_root *root) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index e28ad4baf483..200f63bc6675 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -41,6 +41,7 @@ #include <linux/slab.h> #include <linux/cleancache.h> #include <linux/mnt_namespace.h> +#include <linux/ratelimit.h> #include "compat.h" #include "delayed-inode.h" #include "ctree.h" @@ -1053,7 +1054,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) u64 avail_space; u64 used_space; u64 min_stripe_size; - int min_stripes = 1; + int min_stripes = 1, num_stripes = 1; int i = 0, nr_devices; int ret; @@ -1067,12 +1068,16 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) /* calc min stripe number for data space alloction */ type = btrfs_get_alloc_profile(root, 1); - if (type & BTRFS_BLOCK_GROUP_RAID0) + if (type & BTRFS_BLOCK_GROUP_RAID0) { min_stripes = 2; - else if (type & BTRFS_BLOCK_GROUP_RAID1) + num_stripes = nr_devices; + } else if (type & BTRFS_BLOCK_GROUP_RAID1) { min_stripes = 2; - else if (type & BTRFS_BLOCK_GROUP_RAID10) + num_stripes = 2; + } else if (type & BTRFS_BLOCK_GROUP_RAID10) { min_stripes = 4; + num_stripes = 4; + } if (type & BTRFS_BLOCK_GROUP_DUP) min_stripe_size = 2 * BTRFS_STRIPE_LEN; @@ -1141,13 +1146,16 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) i = nr_devices - 1; avail_space = 0; while (nr_devices >= min_stripes) { + if (num_stripes > nr_devices) + num_stripes = nr_devices; + if (devices_info[i].max_avail >= min_stripe_size) { int j; u64 alloc_size; - avail_space += devices_info[i].max_avail * min_stripes; + avail_space += devices_info[i].max_avail * num_stripes; alloc_size = devices_info[i].max_avail; - for (j = i + 1 - min_stripes; j <= i; j++) + for (j = i + 1 - num_stripes; j <= i; j++) devices_info[j].max_avail -= alloc_size; } i--; @@ -1264,6 +1272,16 @@ static int btrfs_unfreeze(struct super_block *sb) return 0; } +static void btrfs_fs_dirty_inode(struct inode *inode, int flags) +{ + int ret; + + ret = btrfs_dirty_inode(inode); + if (ret) + printk_ratelimited(KERN_ERR "btrfs: fail to dirty inode %Lu " + "error %d\n", btrfs_ino(inode), ret); +} + static const struct super_operations btrfs_super_ops = { .drop_inode = btrfs_drop_inode, .evict_inode = btrfs_evict_inode, @@ -1271,7 +1289,7 @@ static const struct super_operations btrfs_super_ops = { .sync_fs = btrfs_sync_fs, .show_options = btrfs_show_options, .write_inode = btrfs_write_inode, - .dirty_inode = btrfs_dirty_inode, + .dirty_inode = btrfs_fs_dirty_inode, .alloc_inode = btrfs_alloc_inode, .destroy_inode = btrfs_destroy_inode, .statfs = btrfs_statfs, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 0a8c8f8304b1..f4b839fd3c9d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -295,6 +295,12 @@ loop_lock: btrfs_requeue_work(&device->work); goto done; } + /* unplug every 64 requests just for good measure */ + if (batch_run % 64 == 0) { + blk_finish_plug(&plug); + blk_start_plug(&plug); + sync_pending = 0; + } } cond_resched(); @@ -3258,7 +3264,7 @@ static void btrfs_end_bio(struct bio *bio, int err) */ if (atomic_read(&bbio->error) > bbio->max_errors) { err = -EIO; - } else if (err) { + } else { /* * this bio is actually up to date, we didn't * go over the max number of errors diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 4144caf2f9d3..173b1d22e59b 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -87,7 +87,7 @@ static int ceph_set_page_dirty(struct page *page) snapc = ceph_get_snap_context(ci->i_snap_realm->cached_context); /* dirty the head */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_head_snapc == NULL) ci->i_head_snapc = ceph_get_snap_context(snapc); ++ci->i_wrbuffer_ref_head; @@ -100,7 +100,7 @@ static int ceph_set_page_dirty(struct page *page) ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1, ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head, snapc, snapc->seq, snapc->num_snaps); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* now adjust page */ spin_lock_irq(&mapping->tree_lock); @@ -391,7 +391,7 @@ static struct ceph_snap_context *get_oldest_context(struct inode *inode, struct ceph_snap_context *snapc = NULL; struct ceph_cap_snap *capsnap = NULL; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap, capsnap->context, capsnap->dirty_pages); @@ -407,7 +407,7 @@ static struct ceph_snap_context *get_oldest_context(struct inode *inode, dout(" head snapc %p has %d dirty pages\n", snapc, ci->i_wrbuffer_ref_head); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return snapc; } diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 0f327c6c9679..8b53193e4f7c 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -309,7 +309,7 @@ void ceph_reservation_status(struct ceph_fs_client *fsc, /* * Find ceph_cap for given mds, if any. * - * Called with i_lock held. + * Called with i_ceph_lock held. */ static struct ceph_cap *__get_cap_for_mds(struct ceph_inode_info *ci, int mds) { @@ -332,9 +332,9 @@ struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, int mds) { struct ceph_cap *cap; - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ci, mds); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); return cap; } @@ -361,15 +361,16 @@ static int __ceph_get_cap_mds(struct ceph_inode_info *ci) int ceph_get_cap_mds(struct inode *inode) { + struct ceph_inode_info *ci = ceph_inode(inode); int mds; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); mds = __ceph_get_cap_mds(ceph_inode(inode)); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return mds; } /* - * Called under i_lock. + * Called under i_ceph_lock. */ static void __insert_cap_node(struct ceph_inode_info *ci, struct ceph_cap *new) @@ -415,7 +416,7 @@ static void __cap_set_timeouts(struct ceph_mds_client *mdsc, * * If I_FLUSH is set, leave the inode at the front of the list. * - * Caller holds i_lock + * Caller holds i_ceph_lock * -> we take mdsc->cap_delay_lock */ static void __cap_delay_requeue(struct ceph_mds_client *mdsc, @@ -457,7 +458,7 @@ static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc, /* * Cancel delayed work on cap. * - * Caller must hold i_lock. + * Caller must hold i_ceph_lock. */ static void __cap_delay_cancel(struct ceph_mds_client *mdsc, struct ceph_inode_info *ci) @@ -532,14 +533,14 @@ int ceph_add_cap(struct inode *inode, wanted |= ceph_caps_for_mode(fmode); retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ci, mds); if (!cap) { if (new_cap) { cap = new_cap; new_cap = NULL; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); new_cap = get_cap(mdsc, caps_reservation); if (new_cap == NULL) return -ENOMEM; @@ -625,7 +626,7 @@ retry: if (fmode >= 0) __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); wake_up_all(&ci->i_cap_wq); return 0; } @@ -792,7 +793,7 @@ int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) struct rb_node *p; int ret = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { cap = rb_entry(p, struct ceph_cap, ci_node); if (__cap_is_valid(cap) && @@ -801,7 +802,7 @@ int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) break; } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("ceph_caps_revoking %p %s = %d\n", inode, ceph_cap_string(mask), ret); return ret; @@ -855,7 +856,7 @@ int __ceph_caps_mds_wanted(struct ceph_inode_info *ci) } /* - * called under i_lock + * called under i_ceph_lock */ static int __ceph_is_any_caps(struct ceph_inode_info *ci) { @@ -865,7 +866,7 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci) /* * Remove a cap. Take steps to deal with a racing iterate_session_caps. * - * caller should hold i_lock. + * caller should hold i_ceph_lock. * caller will not hold session s_mutex if called from destroy_inode. */ void __ceph_remove_cap(struct ceph_cap *cap) @@ -1028,7 +1029,7 @@ static void __queue_cap_release(struct ceph_mds_session *session, /* * Queue cap releases when an inode is dropped from our cache. Since - * inode is about to be destroyed, there is no need for i_lock. + * inode is about to be destroyed, there is no need for i_ceph_lock. */ void ceph_queue_caps_release(struct inode *inode) { @@ -1049,7 +1050,7 @@ void ceph_queue_caps_release(struct inode *inode) /* * Send a cap msg on the given inode. Update our caps state, then - * drop i_lock and send the message. + * drop i_ceph_lock and send the message. * * Make note of max_size reported/requested from mds, revoked caps * that have now been implemented. @@ -1061,13 +1062,13 @@ void ceph_queue_caps_release(struct inode *inode) * Return non-zero if delayed release, or we experienced an error * such that the caller should requeue + retry later. * - * called with i_lock, then drops it. + * called with i_ceph_lock, then drops it. * caller should hold snap_rwsem (read), s_mutex. */ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, int op, int used, int want, int retain, int flushing, unsigned *pflush_tid) - __releases(cap->ci->vfs_inode->i_lock) + __releases(cap->ci->i_ceph_lock) { struct ceph_inode_info *ci = cap->ci; struct inode *inode = &ci->vfs_inode; @@ -1170,7 +1171,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, xattr_version = ci->i_xattrs.version; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ret = send_cap_msg(session, ceph_vino(inode).ino, cap_id, op, keep, want, flushing, seq, flush_tid, issue_seq, mseq, @@ -1198,13 +1199,13 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, * Unless @again is true, skip cap_snaps that were already sent to * the MDS (i.e., during this session). * - * Called under i_lock. Takes s_mutex as needed. + * Called under i_ceph_lock. Takes s_mutex as needed. */ void __ceph_flush_snaps(struct ceph_inode_info *ci, struct ceph_mds_session **psession, int again) - __releases(ci->vfs_inode->i_lock) - __acquires(ci->vfs_inode->i_lock) + __releases(ci->i_ceph_lock) + __acquires(ci->i_ceph_lock) { struct inode *inode = &ci->vfs_inode; int mds; @@ -1261,7 +1262,7 @@ retry: session = NULL; } if (!session) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); mutex_lock(&mdsc->mutex); session = __ceph_lookup_mds_session(mdsc, mds); mutex_unlock(&mdsc->mutex); @@ -1275,7 +1276,7 @@ retry: * deletion or migration. retry, and we'll * get a better @mds value next time. */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); goto retry; } @@ -1285,7 +1286,7 @@ retry: list_del_init(&capsnap->flushing_item); list_add_tail(&capsnap->flushing_item, &session->s_cap_snaps_flushing); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("flush_snaps %p cap_snap %p follows %lld tid %llu\n", inode, capsnap, capsnap->follows, capsnap->flush_tid); @@ -1302,7 +1303,7 @@ retry: next_follows = capsnap->follows + 1; ceph_put_cap_snap(capsnap); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); goto retry; } @@ -1322,11 +1323,9 @@ out: static void ceph_flush_snaps(struct ceph_inode_info *ci) { - struct inode *inode = &ci->vfs_inode; - - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_flush_snaps(ci, NULL, 0); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -1373,7 +1372,7 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) * Add dirty inode to the flushing list. Assigned a seq number so we * can wait for caps to flush without starving. * - * Called under i_lock. + * Called under i_ceph_lock. */ static int __mark_caps_flushing(struct inode *inode, struct ceph_mds_session *session) @@ -1421,9 +1420,9 @@ static int try_nonblocking_invalidate(struct inode *inode) struct ceph_inode_info *ci = ceph_inode(inode); u32 invalidating_gen = ci->i_rdcache_gen; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); invalidate_mapping_pages(&inode->i_data, 0, -1); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (inode->i_data.nrpages == 0 && invalidating_gen == ci->i_rdcache_gen) { @@ -1470,7 +1469,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, if (mdsc->stopping) is_delayed = 1; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_ceph_flags & CEPH_I_FLUSH) flags |= CHECK_CAPS_FLUSH; @@ -1480,7 +1479,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, __ceph_flush_snaps(ci, &session, 0); goto retry_locked; retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); retry_locked: file_wanted = __ceph_caps_file_wanted(ci); used = __ceph_caps_used(ci); @@ -1634,7 +1633,7 @@ ack: if (mutex_trylock(&session->s_mutex) == 0) { dout("inverting session/ino locks on %p\n", session); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (took_snap_rwsem) { up_read(&mdsc->snap_rwsem); took_snap_rwsem = 0; @@ -1648,7 +1647,7 @@ ack: if (down_read_trylock(&mdsc->snap_rwsem) == 0) { dout("inverting snap/in locks on %p\n", inode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); down_read(&mdsc->snap_rwsem); took_snap_rwsem = 1; goto retry; @@ -1664,10 +1663,10 @@ ack: mds = cap->mds; /* remember mds, so we don't repeat */ sent++; - /* __send_cap drops i_lock */ + /* __send_cap drops i_ceph_lock */ delayed += __send_cap(mdsc, cap, CEPH_CAP_OP_UPDATE, used, want, retain, flushing, NULL); - goto retry; /* retake i_lock and restart our cap scan. */ + goto retry; /* retake i_ceph_lock and restart our cap scan. */ } /* @@ -1681,7 +1680,7 @@ ack: else if (!is_delayed || force_requeue) __cap_delay_requeue(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (queue_invalidate) ceph_queue_invalidate(inode); @@ -1704,7 +1703,7 @@ static int try_flush_caps(struct inode *inode, struct ceph_mds_session *session, int flushing = 0; retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_ceph_flags & CEPH_I_NOFLUSH) { dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode); goto out; @@ -1716,7 +1715,7 @@ retry: int delayed; if (!session) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); session = cap->session; mutex_lock(&session->s_mutex); goto retry; @@ -1727,18 +1726,18 @@ retry: flushing = __mark_caps_flushing(inode, session); - /* __send_cap drops i_lock */ + /* __send_cap drops i_ceph_lock */ delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH, used, want, cap->issued | cap->implemented, flushing, flush_tid); if (!delayed) goto out_unlocked; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __cap_delay_requeue(mdsc, ci); } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); out_unlocked: if (session && unlock_session) mutex_unlock(&session->s_mutex); @@ -1753,7 +1752,7 @@ static int caps_are_flushed(struct inode *inode, unsigned tid) struct ceph_inode_info *ci = ceph_inode(inode); int i, ret = 1; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); for (i = 0; i < CEPH_CAP_BITS; i++) if ((ci->i_flushing_caps & (1 << i)) && ci->i_cap_flush_tid[i] <= tid) { @@ -1761,7 +1760,7 @@ static int caps_are_flushed(struct inode *inode, unsigned tid) ret = 0; break; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ret; } @@ -1868,10 +1867,10 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc) struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (__ceph_caps_dirty(ci)) __cap_delay_requeue_front(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } return err; } @@ -1894,7 +1893,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode = &ci->vfs_inode; struct ceph_cap *cap; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = ci->i_auth_cap; if (cap && cap->session == session) { dout("kick_flushing_caps %p cap %p capsnap %p\n", inode, @@ -1904,7 +1903,7 @@ static void kick_flushing_capsnaps(struct ceph_mds_client *mdsc, pr_err("%p auth cap %p not mds%d ???\n", inode, cap, session->s_mds); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } @@ -1921,7 +1920,7 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, struct ceph_cap *cap; int delayed = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = ci->i_auth_cap; if (cap && cap->session == session) { dout("kick_flushing_caps %p cap %p %s\n", inode, @@ -1932,14 +1931,14 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, cap->issued | cap->implemented, ci->i_flushing_caps, NULL); if (delayed) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __cap_delay_requeue(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } else { pr_err("%p auth cap %p not mds%d ???\n", inode, cap, session->s_mds); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } } @@ -1952,7 +1951,7 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, struct ceph_cap *cap; int delayed = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = ci->i_auth_cap; dout("kick_flushing_inode_caps %p flushing %s flush_seq %lld\n", inode, ceph_cap_string(ci->i_flushing_caps), ci->i_cap_flush_seq); @@ -1964,12 +1963,12 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, cap->issued | cap->implemented, ci->i_flushing_caps, NULL); if (delayed) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __cap_delay_requeue(mdsc, ci); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } @@ -1978,7 +1977,7 @@ static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, * Take references to capabilities we hold, so that we don't release * them to the MDS prematurely. * - * Protected by i_lock. + * Protected by i_ceph_lock. */ static void __take_cap_refs(struct ceph_inode_info *ci, int got) { @@ -2016,7 +2015,7 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want, dout("get_cap_refs %p need %s want %s\n", inode, ceph_cap_string(need), ceph_cap_string(want)); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); /* make sure file is actually open */ file_wanted = __ceph_caps_file_wanted(ci); @@ -2077,7 +2076,7 @@ static int try_get_cap_refs(struct ceph_inode_info *ci, int need, int want, ceph_cap_string(have), ceph_cap_string(need)); } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("get_cap_refs %p ret %d got %s\n", inode, ret, ceph_cap_string(*got)); return ret; @@ -2094,7 +2093,7 @@ static void check_max_size(struct inode *inode, loff_t endoff) int check = 0; /* do we need to explicitly request a larger max_size? */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if ((endoff >= ci->i_max_size || endoff > (inode->i_size << 1)) && endoff > ci->i_wanted_max_size) { @@ -2103,7 +2102,7 @@ static void check_max_size(struct inode *inode, loff_t endoff) ci->i_wanted_max_size = endoff; check = 1; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (check) ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); } @@ -2140,9 +2139,9 @@ retry: */ void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps) { - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); __take_cap_refs(ci, caps); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -2160,7 +2159,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) int last = 0, put = 0, flushsnaps = 0, wake = 0; struct ceph_cap_snap *capsnap; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (had & CEPH_CAP_PIN) --ci->i_pin_ref; if (had & CEPH_CAP_FILE_RD) @@ -2193,7 +2192,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) } } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had), last ? " last" : "", put ? " put" : ""); @@ -2225,7 +2224,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, int found = 0; struct ceph_cap_snap *capsnap = NULL; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_wrbuffer_ref -= nr; last = !ci->i_wrbuffer_ref; @@ -2274,7 +2273,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (last) { ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); @@ -2291,7 +2290,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, * Handle a cap GRANT message from the MDS. (Note that a GRANT may * actually be a revocation if it specifies a smaller cap set.) * - * caller holds s_mutex and i_lock, we drop both. + * caller holds s_mutex and i_ceph_lock, we drop both. * * return value: * 0 - ok @@ -2302,7 +2301,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, struct ceph_mds_session *session, struct ceph_cap *cap, struct ceph_buffer *xattr_buf) - __releases(inode->i_lock) + __releases(ci->i_ceph_lock) { struct ceph_inode_info *ci = ceph_inode(inode); int mds = session->s_mds; @@ -2453,7 +2452,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, } BUG_ON(cap->issued & ~cap->implemented); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (writeback) /* * queue inode for writeback: we can't actually call @@ -2483,7 +2482,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, struct ceph_mds_caps *m, struct ceph_mds_session *session, struct ceph_cap *cap) - __releases(inode->i_lock) + __releases(ci->i_ceph_lock) { struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; @@ -2539,7 +2538,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, wake_up_all(&ci->i_cap_wq); out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (drop) iput(inode); } @@ -2562,7 +2561,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, dout("handle_cap_flushsnap_ack inode %p ci %p mds%d follows %lld\n", inode, ci, session->s_mds, follows); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { if (capsnap->follows == follows) { if (capsnap->flush_tid != flush_tid) { @@ -2585,7 +2584,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, capsnap, capsnap->follows); } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (drop) iput(inode); } @@ -2598,7 +2597,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, static void handle_cap_trunc(struct inode *inode, struct ceph_mds_caps *trunc, struct ceph_mds_session *session) - __releases(inode->i_lock) + __releases(ci->i_ceph_lock) { struct ceph_inode_info *ci = ceph_inode(inode); int mds = session->s_mds; @@ -2617,7 +2616,7 @@ static void handle_cap_trunc(struct inode *inode, inode, mds, seq, truncate_size, truncate_seq); queue_trunc = ceph_fill_file_size(inode, issued, truncate_seq, truncate_size, size); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (queue_trunc) ceph_queue_vmtruncate(inode); @@ -2646,7 +2645,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, dout("handle_cap_export inode %p ci %p mds%d mseq %d\n", inode, ci, mds, mseq); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); /* make sure we haven't seen a higher mseq */ for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { @@ -2690,7 +2689,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, } /* else, we already released it */ - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -2745,9 +2744,9 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, up_read(&mdsc->snap_rwsem); /* make sure we re-request max_size, if necessary */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_requested_max_size = 0; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -2762,6 +2761,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, struct ceph_mds_client *mdsc = session->s_mdsc; struct super_block *sb = mdsc->fsc->sb; struct inode *inode; + struct ceph_inode_info *ci; struct ceph_cap *cap; struct ceph_mds_caps *h; int mds = session->s_mds; @@ -2815,6 +2815,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, /* lookup ino */ inode = ceph_find_inode(sb, vino); + ci = ceph_inode(inode); dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino, vino.snap, inode); if (!inode) { @@ -2844,16 +2845,16 @@ void ceph_handle_caps(struct ceph_mds_session *session, } /* the rest require a cap */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ceph_inode(inode), mds); if (!cap) { dout(" no cap on %p ino %llx.%llx from mds%d\n", inode, ceph_ino(inode), ceph_snap(inode), mds); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); goto flush_cap_releases; } - /* note that each of these drops i_lock for us */ + /* note that each of these drops i_ceph_lock for us */ switch (op) { case CEPH_CAP_OP_REVOKE: case CEPH_CAP_OP_GRANT: @@ -2869,7 +2870,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, break; default: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); pr_err("ceph_handle_caps: unknown cap op %d %s\n", op, ceph_cap_op_name(op)); } @@ -2962,13 +2963,13 @@ void ceph_put_fmode(struct ceph_inode_info *ci, int fmode) struct inode *inode = &ci->vfs_inode; int last = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("put_fmode %p fmode %d %d -> %d\n", inode, fmode, ci->i_nr_by_mode[fmode], ci->i_nr_by_mode[fmode]-1); BUG_ON(ci->i_nr_by_mode[fmode] == 0); if (--ci->i_nr_by_mode[fmode] == 0) last++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (last && ci->i_vino.snap == CEPH_NOSNAP) ceph_check_caps(ci, 0, NULL); @@ -2991,7 +2992,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode, int used, dirty; int ret = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); used = __ceph_caps_used(ci); dirty = __ceph_caps_dirty(ci); @@ -3046,7 +3047,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode, inode, cap, ceph_cap_string(cap->issued)); } } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ret; } @@ -3061,7 +3062,7 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry, /* * force an record for the directory caps if we have a dentry lease. - * this is racy (can't take i_lock and d_lock together), but it + * this is racy (can't take i_ceph_lock and d_lock together), but it * doesn't have to be perfect; the mds will revoke anything we don't * release. */ diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index bca3948e9dbf..3eeb97661262 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -281,18 +281,18 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) } /* can we use the dcache? */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if ((filp->f_pos == 2 || fi->dentry) && !ceph_test_mount_opt(fsc, NOASYNCREADDIR) && ceph_snap(inode) != CEPH_SNAPDIR && ceph_dir_test_complete(inode) && __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = __dcache_readdir(filp, dirent, filldir); if (err != -EAGAIN) return err; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } if (fi->dentry) { err = note_last_dentry(fi, fi->dentry->d_name.name, @@ -428,12 +428,12 @@ more: * were released during the whole readdir, and we should have * the complete dir contents in our cache. */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_release_count == fi->dir_release_count) { ceph_dir_set_complete(inode); ci->i_max_offset = filp->f_pos; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("readdir %p filp %p done.\n", inode, filp); return 0; @@ -607,7 +607,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, struct ceph_inode_info *ci = ceph_inode(dir); struct ceph_dentry_info *di = ceph_dentry(dentry); - spin_lock(&dir->i_lock); + spin_lock(&ci->i_ceph_lock); dout(" dir %p flags are %d\n", dir, ci->i_ceph_flags); if (strncmp(dentry->d_name.name, fsc->mount_options->snapdir_name, @@ -615,13 +615,13 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, !is_root_ceph_dentry(dir, dentry) && ceph_dir_test_complete(dir) && (__ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1))) { - spin_unlock(&dir->i_lock); + spin_unlock(&ci->i_ceph_lock); dout(" dir %p complete, -ENOENT\n", dir); d_add(dentry, NULL); di->lease_shared_gen = ci->i_shared_gen; return NULL; } - spin_unlock(&dir->i_lock); + spin_unlock(&ci->i_ceph_lock); } op = ceph_snap(dir) == CEPH_SNAPDIR ? @@ -841,12 +841,12 @@ static int drop_caps_for_unlink(struct inode *inode) struct ceph_inode_info *ci = ceph_inode(inode); int drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (inode->i_nlink == 1) { drop |= ~(__ceph_caps_wanted(ci) | CEPH_CAP_PIN); ci->i_ceph_flags |= CEPH_I_NODELAY; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return drop; } @@ -1015,10 +1015,10 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) struct ceph_dentry_info *di = ceph_dentry(dentry); int valid = 0; - spin_lock(&dir->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_shared_gen == di->lease_shared_gen) valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1); - spin_unlock(&dir->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("dir_lease_is_valid dir %p v%u dentry %p v%u = %d\n", dir, (unsigned)ci->i_shared_gen, dentry, (unsigned)di->lease_shared_gen, valid); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index ce549d31eeb7..ed72428d9c75 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -147,9 +147,9 @@ int ceph_open(struct inode *inode, struct file *file) /* trivially open snapdir */ if (ceph_snap(inode) == CEPH_SNAPDIR) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ceph_init_file(inode, file, fmode); } @@ -158,7 +158,7 @@ int ceph_open(struct inode *inode, struct file *file) * write) or any MDS (for read). Update wanted set * asynchronously. */ - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (__ceph_is_any_real_caps(ci) && (((fmode & CEPH_FILE_MODE_WR) == 0) || ci->i_auth_cap)) { int mds_wanted = __ceph_caps_mds_wanted(ci); @@ -168,7 +168,7 @@ int ceph_open(struct inode *inode, struct file *file) inode, fmode, ceph_cap_string(wanted), ceph_cap_string(issued)); __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* adjust wanted? */ if ((issued & wanted) != wanted && @@ -180,10 +180,10 @@ int ceph_open(struct inode *inode, struct file *file) } else if (ceph_snap(inode) != CEPH_NOSNAP && (ci->i_snap_caps & wanted) == wanted) { __ceph_get_fmode(ci, fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ceph_init_file(inode, file, fmode); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("open fmode %d wants %s\n", fmode, ceph_cap_string(wanted)); req = prepare_open_request(inode->i_sb, flags, 0); @@ -743,9 +743,9 @@ retry_snap: */ int dirty; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ceph_put_cap_refs(ci, got); ret = generic_file_aio_write(iocb, iov, nr_segs, pos); @@ -764,9 +764,9 @@ retry_snap: if (ret >= 0) { int dirty; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (dirty) __mark_inode_dirty(inode, dirty); } @@ -797,7 +797,8 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int origin) mutex_lock(&inode->i_mutex); __ceph_do_pending_vmtruncate(inode); - if (origin != SEEK_CUR || origin != SEEK_SET) { + + if (origin == SEEK_END || origin == SEEK_DATA || origin == SEEK_HOLE) { ret = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE); if (ret < 0) { offset = ret; diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 116f36502f17..87fb132fb330 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -297,6 +297,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb) dout("alloc_inode %p\n", &ci->vfs_inode); + spin_lock_init(&ci->i_ceph_lock); + ci->i_version = 0; ci->i_time_warp_seq = 0; ci->i_ceph_flags = 0; @@ -583,7 +585,7 @@ static int fill_inode(struct inode *inode, iinfo->xattr_len); } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); /* * provided version will be odd if inode value is projected, @@ -680,7 +682,7 @@ static int fill_inode(struct inode *inode, char *sym; BUG_ON(symlen != inode->i_size); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = -ENOMEM; sym = kmalloc(symlen+1, GFP_NOFS); @@ -689,7 +691,7 @@ static int fill_inode(struct inode *inode, memcpy(sym, iinfo->symlink, symlen); sym[symlen] = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (!ci->i_symlink) ci->i_symlink = sym; else @@ -715,7 +717,7 @@ static int fill_inode(struct inode *inode, } no_change: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* queue truncate if we saw i_size decrease */ if (queue_trunc) @@ -750,13 +752,13 @@ no_change: info->cap.flags, caps_reservation); } else { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout(" %p got snap_caps %s\n", inode, ceph_cap_string(le32_to_cpu(info->cap.caps))); ci->i_snap_caps |= le32_to_cpu(info->cap.caps); if (cap_fmode >= 0) __ceph_get_fmode(ci, cap_fmode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } } else if (cap_fmode >= 0) { pr_warning("mds issued no caps on %llx.%llx\n", @@ -849,19 +851,20 @@ static void ceph_set_dentry_offset(struct dentry *dn) { struct dentry *dir = dn->d_parent; struct inode *inode = dir->d_inode; + struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_dentry_info *di; BUG_ON(!inode); di = ceph_dentry(dn); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (!ceph_dir_test_complete(inode)) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return; } di->offset = ceph_inode(inode)->i_max_offset++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); spin_lock(&dir->d_lock); spin_lock_nested(&dn->d_lock, DENTRY_D_LOCK_NESTED); @@ -1308,7 +1311,7 @@ int ceph_inode_set_size(struct inode *inode, loff_t size) struct ceph_inode_info *ci = ceph_inode(inode); int ret = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("set_size %p %llu -> %llu\n", inode, inode->i_size, size); inode->i_size = size; inode->i_blocks = (size + (1 << 9) - 1) >> 9; @@ -1318,7 +1321,7 @@ int ceph_inode_set_size(struct inode *inode, loff_t size) (ci->i_reported_size << 1) < ci->i_max_size) ret = 1; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return ret; } @@ -1376,20 +1379,20 @@ static void ceph_invalidate_work(struct work_struct *work) u32 orig_gen; int check = 0; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("invalidate_pages %p gen %d revoking %d\n", inode, ci->i_rdcache_gen, ci->i_rdcache_revoking); if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { /* nevermind! */ - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); goto out; } orig_gen = ci->i_rdcache_gen; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); truncate_inode_pages(&inode->i_data, 0); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (orig_gen == ci->i_rdcache_gen && orig_gen == ci->i_rdcache_revoking) { dout("invalidate_pages %p gen %d successful\n", inode, @@ -1401,7 +1404,7 @@ static void ceph_invalidate_work(struct work_struct *work) inode, orig_gen, ci->i_rdcache_gen, ci->i_rdcache_revoking); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (check) ceph_check_caps(ci, 0, NULL); @@ -1460,10 +1463,10 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) int wrbuffer_refs, wake = 0; retry: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_truncate_pending == 0) { dout("__do_pending_vmtruncate %p none pending\n", inode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return; } @@ -1474,7 +1477,7 @@ retry: if (ci->i_wrbuffer_ref_head < ci->i_wrbuffer_ref) { dout("__do_pending_vmtruncate %p flushing snaps first\n", inode); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); filemap_write_and_wait_range(&inode->i_data, 0, inode->i_sb->s_maxbytes); goto retry; @@ -1484,15 +1487,15 @@ retry: wrbuffer_refs = ci->i_wrbuffer_ref; dout("__do_pending_vmtruncate %p (%d) to %lld\n", inode, ci->i_truncate_pending, to); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); truncate_inode_pages(inode->i_mapping, to); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_truncate_pending--; if (ci->i_truncate_pending == 0) wake = 1; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (wrbuffer_refs == 0) ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); @@ -1547,7 +1550,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) if (IS_ERR(req)) return PTR_ERR(req); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); issued = __ceph_caps_issued(ci, NULL); dout("setattr %p issued %s\n", inode, ceph_cap_string(issued)); @@ -1695,7 +1698,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) } release &= issued; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (inode_dirty_flags) __mark_inode_dirty(inode, inode_dirty_flags); @@ -1717,7 +1720,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) __ceph_do_pending_vmtruncate(inode); return err; out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ceph_mdsc_put_request(req); return err; } diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 5a14c29cbba6..790914a598dd 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c @@ -241,11 +241,11 @@ static long ceph_ioctl_lazyio(struct file *file) struct ceph_inode_info *ci = ceph_inode(inode); if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_nr_by_mode[fi->fmode]--; fi->fmode |= CEPH_FILE_MODE_LAZY; ci->i_nr_by_mode[fi->fmode]++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout("ioctl_layzio: file %p marked lazy\n", file); ceph_check_caps(ci, 0, NULL); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 264ab701154f..6203d805eb45 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -732,21 +732,21 @@ static int __choose_mds(struct ceph_mds_client *mdsc, } } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap = NULL; if (mode == USE_AUTH_MDS) cap = ci->i_auth_cap; if (!cap && !RB_EMPTY_ROOT(&ci->i_caps)) cap = rb_entry(rb_first(&ci->i_caps), struct ceph_cap, ci_node); if (!cap) { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); goto random; } mds = cap->session->s_mds; dout("choose_mds %p %llx.%llx mds%d (%scap %p)\n", inode, ceph_vinop(inode), mds, cap == ci->i_auth_cap ? "auth " : "", cap); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return mds; random: @@ -951,7 +951,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, dout("removing cap %p, ci is %p, inode is %p\n", cap, ci, &ci->vfs_inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_remove_cap(cap); if (!__ceph_is_any_real_caps(ci)) { struct ceph_mds_client *mdsc = @@ -984,7 +984,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, } spin_unlock(&mdsc->cap_dirty_lock); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); while (drop--) iput(inode); return 0; @@ -1015,10 +1015,10 @@ static int wake_up_session_cb(struct inode *inode, struct ceph_cap *cap, wake_up_all(&ci->i_cap_wq); if (arg) { - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_wanted_max_size = 0; ci->i_requested_max_size = 0; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } return 0; } @@ -1151,7 +1151,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) if (session->s_trim_caps <= 0) return -1; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); mine = cap->issued | cap->implemented; used = __ceph_caps_used(ci); oissued = __ceph_caps_issued_other(ci, cap); @@ -1170,7 +1170,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) __ceph_remove_cap(cap); } else { /* try to drop referring dentries */ - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); d_prune_aliases(inode); dout("trim_caps_cb %p cap %p pruned, count now %d\n", inode, cap, atomic_read(&inode->i_count)); @@ -1178,7 +1178,7 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return 0; } @@ -1296,7 +1296,7 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) i_flushing_item); struct inode *inode = &ci->vfs_inode; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_cap_flush_seq <= want_flush_seq) { dout("check_cap_flush still flushing %p " "seq %lld <= %lld to mds%d\n", inode, @@ -1304,7 +1304,7 @@ static int check_cap_flush(struct ceph_mds_client *mdsc, u64 want_flush_seq) session->s_mds); ret = 0; } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } mutex_unlock(&session->s_mutex); ceph_put_mds_session(session); @@ -1495,6 +1495,7 @@ retry: pos, temp); } else if (stop_on_nosnap && inode && ceph_snap(inode) == CEPH_NOSNAP) { + spin_unlock(&temp->d_lock); break; } else { pos -= temp->d_name.len; @@ -2011,10 +2012,10 @@ void ceph_invalidate_dir_request(struct ceph_mds_request *req) struct ceph_inode_info *ci = ceph_inode(inode); dout("invalidate_dir_request %p (D_COMPLETE, lease(s))\n", inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ceph_dir_clear_complete(inode); ci->i_release_count++; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (req->r_dentry) ceph_invalidate_dentry_lease(req->r_dentry); @@ -2422,7 +2423,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, if (err) goto out_free; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); cap->seq = 0; /* reset cap seq */ cap->issue_seq = 0; /* and issue_seq */ @@ -2445,7 +2446,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, rec.v1.pathbase = cpu_to_le64(pathbase); reclen = sizeof(rec.v1); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (recon_state->flock) { int num_fcntl_locks, num_flock_locks; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 4bb239921dbd..a50ca0e39475 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -20,7 +20,7 @@ * * mdsc->snap_rwsem * - * inode->i_lock + * ci->i_ceph_lock * mdsc->snap_flush_lock * mdsc->cap_delay_lock * diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index e26437191333..a559c80f127a 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -446,7 +446,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) return; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); used = __ceph_caps_used(ci); dirty = __ceph_caps_dirty(ci); @@ -528,7 +528,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) kfree(capsnap); } - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } /* @@ -537,7 +537,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) * * If capsnap can now be flushed, add to snap_flush list, and return 1. * - * Caller must hold i_lock. + * Caller must hold i_ceph_lock. */ int __ceph_finish_cap_snap(struct ceph_inode_info *ci, struct ceph_cap_snap *capsnap) @@ -739,9 +739,9 @@ static void flush_snaps(struct ceph_mds_client *mdsc) inode = &ci->vfs_inode; ihold(inode); spin_unlock(&mdsc->snap_flush_lock); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __ceph_flush_snaps(ci, &session, 0); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); iput(inode); spin_lock(&mdsc->snap_flush_lock); } @@ -847,7 +847,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, continue; ci = ceph_inode(inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (!ci->i_snap_realm) goto skip_inode; /* @@ -876,7 +876,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, oldrealm = ci->i_snap_realm; ci->i_snap_realm = realm; spin_unlock(&realm->inodes_with_caps_lock); - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); ceph_get_snap_realm(mdsc, realm); ceph_put_snap_realm(mdsc, oldrealm); @@ -885,7 +885,7 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, continue; skip_inode: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); iput(inode); } diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 8dc73a594a90..b48f15f101a0 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -383,7 +383,7 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt) if (fsopt->rsize != CEPH_RSIZE_DEFAULT) seq_printf(m, ",rsize=%d", fsopt->rsize); if (fsopt->rasize != CEPH_RASIZE_DEFAULT) - seq_printf(m, ",rasize=%d", fsopt->rsize); + seq_printf(m, ",rasize=%d", fsopt->rasize); if (fsopt->congestion_kb != default_congestion_kb()) seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb); if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT) diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 01bf189e08a9..edcbf3774a56 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -220,7 +220,7 @@ struct ceph_dentry_info { * The locking for D_COMPLETE is a bit odd: * - we can clear it at almost any time (see ceph_d_prune) * - it is only meaningful if: - * - we hold dir inode i_lock + * - we hold dir inode i_ceph_lock * - we hold dir FILE_SHARED caps * - the dentry D_COMPLETE is set */ @@ -250,6 +250,8 @@ struct ceph_inode_xattrs_info { struct ceph_inode_info { struct ceph_vino i_vino; /* ceph ino + snap */ + spinlock_t i_ceph_lock; + u64 i_version; u32 i_time_warp_seq; @@ -271,7 +273,7 @@ struct ceph_inode_info { struct ceph_inode_xattrs_info i_xattrs; - /* capabilities. protected _both_ by i_lock and cap->session's + /* capabilities. protected _both_ by i_ceph_lock and cap->session's * s_mutex. */ struct rb_root i_caps; /* cap list */ struct ceph_cap *i_auth_cap; /* authoritative cap, if any */ @@ -437,18 +439,18 @@ static inline void ceph_i_clear(struct inode *inode, unsigned mask) { struct ceph_inode_info *ci = ceph_inode(inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_ceph_flags &= ~mask; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } static inline void ceph_i_set(struct inode *inode, unsigned mask) { struct ceph_inode_info *ci = ceph_inode(inode); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); ci->i_ceph_flags |= mask; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); } static inline bool ceph_i_test(struct inode *inode, unsigned mask) @@ -456,9 +458,9 @@ static inline bool ceph_i_test(struct inode *inode, unsigned mask) struct ceph_inode_info *ci = ceph_inode(inode); bool r; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); r = (ci->i_ceph_flags & mask) == mask; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return r; } @@ -508,9 +510,9 @@ extern int __ceph_caps_issued_other(struct ceph_inode_info *ci, static inline int ceph_caps_issued(struct ceph_inode_info *ci) { int issued; - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); issued = __ceph_caps_issued(ci, NULL); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); return issued; } @@ -518,9 +520,9 @@ static inline int ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) { int r; - spin_lock(&ci->vfs_inode.i_lock); + spin_lock(&ci->i_ceph_lock); r = __ceph_caps_issued_mask(ci, mask, touch); - spin_unlock(&ci->vfs_inode.i_lock); + spin_unlock(&ci->i_ceph_lock); return r; } @@ -743,10 +745,9 @@ extern int ceph_add_cap(struct inode *inode, extern void __ceph_remove_cap(struct ceph_cap *cap); static inline void ceph_remove_cap(struct ceph_cap *cap) { - struct inode *inode = &cap->ci->vfs_inode; - spin_lock(&inode->i_lock); + spin_lock(&cap->ci->i_ceph_lock); __ceph_remove_cap(cap); - spin_unlock(&inode->i_lock); + spin_unlock(&cap->ci->i_ceph_lock); } extern void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap); diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 96c6739a0280..a5e36e4488a7 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -343,8 +343,8 @@ void __ceph_destroy_xattrs(struct ceph_inode_info *ci) } static int __build_xattrs(struct inode *inode) - __releases(inode->i_lock) - __acquires(inode->i_lock) + __releases(ci->i_ceph_lock) + __acquires(ci->i_ceph_lock) { u32 namelen; u32 numattr = 0; @@ -372,7 +372,7 @@ start: end = p + ci->i_xattrs.blob->vec.iov_len; ceph_decode_32_safe(&p, end, numattr, bad); xattr_version = ci->i_xattrs.version; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); xattrs = kcalloc(numattr, sizeof(struct ceph_xattr *), GFP_NOFS); @@ -387,7 +387,7 @@ start: goto bad_lock; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_xattrs.version != xattr_version) { /* lost a race, retry */ for (i = 0; i < numattr; i++) @@ -418,7 +418,7 @@ start: return err; bad_lock: - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); bad: if (xattrs) { for (i = 0; i < numattr; i++) @@ -512,7 +512,7 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, if (vxattrs) vxattr = ceph_match_vxattr(vxattrs, name); - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("getxattr %p ver=%lld index_ver=%lld\n", inode, ci->i_xattrs.version, ci->i_xattrs.index_version); @@ -520,14 +520,14 @@ ssize_t ceph_getxattr(struct dentry *dentry, const char *name, void *value, (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { goto get_xattr; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); /* get xattrs from mds (if we don't already have them) */ err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); if (err) return err; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (vxattr && vxattr->readonly) { err = vxattr->getxattr_cb(ci, value, size); @@ -558,7 +558,7 @@ get_xattr: memcpy(value, xattr->val, xattr->val_len); out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return err; } @@ -573,7 +573,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) u32 len; int i; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); dout("listxattr %p ver=%lld index_ver=%lld\n", inode, ci->i_xattrs.version, ci->i_xattrs.index_version); @@ -581,13 +581,13 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) (ci->i_xattrs.index_version >= ci->i_xattrs.version)) { goto list_xattr; } else { - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = ceph_do_getattr(inode, CEPH_STAT_CAP_XATTR); if (err) return err; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); err = __build_xattrs(inode); if (err < 0) @@ -619,7 +619,7 @@ list_xattr: } out: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); return err; } @@ -739,7 +739,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name, if (!xattr) goto out; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); retry: issued = __ceph_caps_issued(ci, NULL); if (!(issued & CEPH_CAP_XATTR_EXCL)) @@ -752,12 +752,12 @@ retry: required_blob_size > ci->i_xattrs.prealloc_blob->alloc_len) { struct ceph_buffer *blob = NULL; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); dout(" preaallocating new blob size=%d\n", required_blob_size); blob = ceph_buffer_new(required_blob_size, GFP_NOFS); if (!blob) goto out; - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); if (ci->i_xattrs.prealloc_blob) ceph_buffer_put(ci->i_xattrs.prealloc_blob); ci->i_xattrs.prealloc_blob = blob; @@ -770,13 +770,13 @@ retry: dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL); ci->i_xattrs.dirty = true; inode->i_ctime = CURRENT_TIME; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (dirty) __mark_inode_dirty(inode, dirty); return err; do_sync: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = ceph_sync_setxattr(dentry, name, value, size, flags); out: kfree(newname); @@ -833,7 +833,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name) return -EOPNOTSUPP; } - spin_lock(&inode->i_lock); + spin_lock(&ci->i_ceph_lock); __build_xattrs(inode); issued = __ceph_caps_issued(ci, NULL); dout("removexattr %p issued %s\n", inode, ceph_cap_string(issued)); @@ -846,12 +846,12 @@ int ceph_removexattr(struct dentry *dentry, const char *name) ci->i_xattrs.dirty = true; inode->i_ctime = CURRENT_TIME; - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); if (dirty) __mark_inode_dirty(inode, dirty); return err; do_sync: - spin_unlock(&inode->i_lock); + spin_unlock(&ci->i_ceph_lock); err = ceph_send_removexattr(dentry, name); return err; } diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index ca418aaf6352..9d8715c45f25 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c @@ -292,7 +292,7 @@ int __init configfs_inode_init(void) return bdi_init(&configfs_backing_dev_info); } -void __exit configfs_inode_exit(void) +void configfs_inode_exit(void) { bdi_destroy(&configfs_backing_dev_info); } diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index ecc62178beda..276e15cafd58 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -143,28 +143,26 @@ static int __init configfs_init(void) goto out; config_kobj = kobject_create_and_add("config", kernel_kobj); - if (!config_kobj) { - kmem_cache_destroy(configfs_dir_cachep); - configfs_dir_cachep = NULL; - goto out; - } + if (!config_kobj) + goto out2; + + err = configfs_inode_init(); + if (err) + goto out3; err = register_filesystem(&configfs_fs_type); - if (err) { - printk(KERN_ERR "configfs: Unable to register filesystem!\n"); - kobject_put(config_kobj); - kmem_cache_destroy(configfs_dir_cachep); - configfs_dir_cachep = NULL; - goto out; - } + if (err) + goto out4; - err = configfs_inode_init(); - if (err) { - unregister_filesystem(&configfs_fs_type); - kobject_put(config_kobj); - kmem_cache_destroy(configfs_dir_cachep); - configfs_dir_cachep = NULL; - } + return 0; +out4: + printk(KERN_ERR "configfs: Unable to register filesystem!\n"); + configfs_inode_exit(); +out3: + kobject_put(config_kobj); +out2: + kmem_cache_destroy(configfs_dir_cachep); + configfs_dir_cachep = NULL; out: return err; } diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 61fa9e1614af..607b1557d292 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1095,7 +1095,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block), ext4_idx_pblock(EXT_FIRST_INDEX(neh))); - neh->eh_depth = cpu_to_le16(neh->eh_depth + 1); + neh->eh_depth = cpu_to_le16(le16_to_cpu(neh->eh_depth) + 1); ext4_mark_inode_dirty(handle, inode); out: brelse(bh); @@ -2955,7 +2955,6 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, /* Pre-conditions */ BUG_ON(!ext4_ext_is_uninitialized(ex)); BUG_ON(!in_range(map->m_lblk, ee_block, ee_len)); - BUG_ON(map->m_lblk + map->m_len > ee_block + ee_len); /* * Attempt to transfer newly initialized blocks from the currently diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 848f436df29f..92655fd89657 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1339,8 +1339,11 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, clear_buffer_unwritten(bh); } - /* skip page if block allocation undone */ - if (buffer_delay(bh) || buffer_unwritten(bh)) + /* + * skip page if block allocation undone and + * block is dirty + */ + if (ext4_bh_delay_or_unwritten(NULL, bh)) skip_page = 1; bh = bh->b_this_page; block_start += bh->b_size; @@ -2387,7 +2390,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, pgoff_t index; struct inode *inode = mapping->host; handle_t *handle; - loff_t page_len; index = pos >> PAGE_CACHE_SHIFT; @@ -2434,13 +2436,6 @@ retry: */ if (pos + len > inode->i_size) ext4_truncate_failed_write(inode); - } else { - page_len = pos & (PAGE_CACHE_SIZE - 1); - if (page_len > 0) { - ret = ext4_discard_partial_page_buffers_no_lock(handle, - inode, page, pos - page_len, page_len, - EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); - } } if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) @@ -2483,7 +2478,6 @@ static int ext4_da_write_end(struct file *file, loff_t new_i_size; unsigned long start, end; int write_mode = (int)(unsigned long)fsdata; - loff_t page_len; if (write_mode == FALL_BACK_TO_NONDELALLOC) { if (ext4_should_order_data(inode)) { @@ -2508,7 +2502,7 @@ static int ext4_da_write_end(struct file *file, */ new_i_size = pos + copied; - if (new_i_size > EXT4_I(inode)->i_disksize) { + if (copied && new_i_size > EXT4_I(inode)->i_disksize) { if (ext4_da_should_update_i_disksize(page, end)) { down_write(&EXT4_I(inode)->i_data_sem); if (new_i_size > EXT4_I(inode)->i_disksize) { @@ -2532,16 +2526,6 @@ static int ext4_da_write_end(struct file *file, } ret2 = generic_write_end(file, mapping, pos, len, copied, page, fsdata); - - page_len = PAGE_CACHE_SIZE - - ((pos + copied - 1) & (PAGE_CACHE_SIZE - 1)); - - if (page_len > 0) { - ret = ext4_discard_partial_page_buffers_no_lock(handle, - inode, page, pos + copied - 1, page_len, - EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED); - } - copied = ret2; if (ret2 < 0) ret = ret2; @@ -2781,10 +2765,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, iocb->private, io_end->inode->i_ino, iocb, offset, size); + iocb->private = NULL; + /* if not aio dio with unwritten extents, just free io and return */ if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { ext4_free_io_end(io_end); - iocb->private = NULL; out: if (is_async) aio_complete(iocb, ret, 0); @@ -2807,7 +2792,6 @@ out: spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); /* queue the work to convert unwritten extents to written */ - iocb->private = NULL; queue_work(wq, &io_end->work); /* XXX: probably should move into the real I/O completion handler */ @@ -3203,26 +3187,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle, iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); - if (!page_has_buffers(page)) { - /* - * If the range to be discarded covers a partial block - * we need to get the page buffers. This is because - * partial blocks cannot be released and the page needs - * to be updated with the contents of the block before - * we write the zeros on top of it. - */ - if ((from & (blocksize - 1)) || - ((from + length) & (blocksize - 1))) { - create_empty_buffers(page, blocksize, 0); - } else { - /* - * If there are no partial blocks, - * there is nothing to update, - * so we can return now - */ - return 0; - } - } + if (!page_has_buffers(page)) + create_empty_buffers(page, blocksize, 0); /* Find the buffer that contains "offset" */ bh = page_buffers(page); diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 7ce1d0b19c94..7e106c810c62 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -385,6 +385,18 @@ int ext4_bio_write_page(struct ext4_io_submit *io, block_end = block_start + blocksize; if (block_start >= len) { + /* + * Comments copied from block_write_full_page_endio: + * + * The page straddles i_size. It must be zeroed out on + * each and every writepage invocation because it may + * be mmapped. "A file is mapped in multiples of the + * page size. For a file that is not a multiple of + * the page size, the remaining memory is zeroed when + * mapped, and writes to that region are not written + * out to the file." + */ + zero_user_segment(page, block_start, block_end); clear_buffer_dirty(bh); set_buffer_uptodate(bh); continue; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3858767ec672..3e1329e2f826 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1155,9 +1155,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) seq_puts(seq, ",block_validity"); if (!test_opt(sb, INIT_INODE_TABLE)) - seq_puts(seq, ",noinit_inode_table"); + seq_puts(seq, ",noinit_itable"); else if (sbi->s_li_wait_mult != EXT4_DEF_LI_WAIT_MULT) - seq_printf(seq, ",init_inode_table=%u", + seq_printf(seq, ",init_itable=%u", (unsigned) sbi->s_li_wait_mult); ext4_show_quota_options(seq, sb); @@ -1333,8 +1333,7 @@ enum { Opt_nomblk_io_submit, Opt_block_validity, Opt_noblock_validity, Opt_inode_readahead_blks, Opt_journal_ioprio, Opt_dioread_nolock, Opt_dioread_lock, - Opt_discard, Opt_nodiscard, - Opt_init_inode_table, Opt_noinit_inode_table, + Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable, }; static const match_table_t tokens = { @@ -1407,9 +1406,9 @@ static const match_table_t tokens = { {Opt_dioread_lock, "dioread_lock"}, {Opt_discard, "discard"}, {Opt_nodiscard, "nodiscard"}, - {Opt_init_inode_table, "init_itable=%u"}, - {Opt_init_inode_table, "init_itable"}, - {Opt_noinit_inode_table, "noinit_itable"}, + {Opt_init_itable, "init_itable=%u"}, + {Opt_init_itable, "init_itable"}, + {Opt_noinit_itable, "noinit_itable"}, {Opt_err, NULL}, }; @@ -1892,7 +1891,7 @@ set_qf_format: case Opt_dioread_lock: clear_opt(sb, DIOREAD_NOLOCK); break; - case Opt_init_inode_table: + case Opt_init_itable: set_opt(sb, INIT_INODE_TABLE); if (args[0].from) { if (match_int(&args[0], &option)) @@ -1903,7 +1902,7 @@ set_qf_format: return 0; sbi->s_li_wait_mult = option; break; - case Opt_noinit_inode_table: + case Opt_noinit_itable: clear_opt(sb, INIT_INODE_TABLE); break; default: diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 73c3992b2bb4..ac86f8b3e3cb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -156,6 +156,7 @@ __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, * bdi_start_writeback - start writeback * @bdi: the backing device to write from * @nr_pages: the number of pages to write + * @reason: reason why some writeback work was initiated * * Description: * This does WB_SYNC_NONE opportunistic writeback. The IO is only @@ -1223,6 +1224,7 @@ static void wait_sb_inodes(struct super_block *sb) * writeback_inodes_sb_nr - writeback dirty inodes from given super_block * @sb: the superblock * @nr: the number of pages to write + * @reason: reason why some writeback work initiated * * Start writeback on some inodes on this super_block. No guarantees are made * on how many (if any) will be written, and this function does not wait @@ -1251,6 +1253,7 @@ EXPORT_SYMBOL(writeback_inodes_sb_nr); /** * writeback_inodes_sb - writeback dirty inodes from given super_block * @sb: the superblock + * @reason: reason why some writeback work was initiated * * Start writeback on some inodes on this super_block. No guarantees are made * on how many (if any) will be written, and this function does not wait @@ -1265,6 +1268,7 @@ EXPORT_SYMBOL(writeback_inodes_sb); /** * writeback_inodes_sb_if_idle - start writeback if none underway * @sb: the superblock + * @reason: reason why some writeback work was initiated * * Invoke writeback_inodes_sb if no writeback is currently underway. * Returns 1 if writeback was started, 0 if not. @@ -1285,6 +1289,7 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle); * writeback_inodes_sb_if_idle - start writeback if none underway * @sb: the superblock * @nr: the number of pages to write + * @reason: reason why some writeback work was initiated * * Invoke writeback_inodes_sb if no writeback is currently underway. * Returns 1 if writeback was started, 0 if not. diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 5cb8614508c3..2aaf3eaaf13d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1512,7 +1512,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, else if (outarg->offset + num > file_size) num = file_size - outarg->offset; - while (num) { + while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) { struct page *page; unsigned int this_num; @@ -1526,6 +1526,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, num -= this_num; total_len += this_num; + index++; } req->misc.retrieve_in.offset = outarg->offset; req->misc.retrieve_in.size = total_len; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 594f07a81c28..0c84100acd44 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1556,7 +1556,7 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) struct inode *inode = file->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); - if (origin != SEEK_CUR || origin != SEEK_SET) { + if (origin != SEEK_CUR && origin != SEEK_SET) { retval = fuse_update_attributes(inode, NULL, file, NULL); if (retval) goto exit; @@ -1567,6 +1567,10 @@ static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin) offset += i_size_read(inode); break; case SEEK_CUR: + if (offset == 0) { + retval = file->f_pos; + goto exit; + } offset += file->f_pos; break; case SEEK_DATA: diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3e6d72756479..aa83109b9431 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1138,28 +1138,28 @@ static int __init fuse_fs_init(void) { int err; - err = register_filesystem(&fuse_fs_type); - if (err) - goto out; - - err = register_fuseblk(); - if (err) - goto out_unreg; - fuse_inode_cachep = kmem_cache_create("fuse_inode", sizeof(struct fuse_inode), 0, SLAB_HWCACHE_ALIGN, fuse_inode_init_once); err = -ENOMEM; if (!fuse_inode_cachep) - goto out_unreg2; + goto out; + + err = register_fuseblk(); + if (err) + goto out2; + + err = register_filesystem(&fuse_fs_type); + if (err) + goto out3; return 0; - out_unreg2: + out3: unregister_fuseblk(); - out_unreg: - unregister_filesystem(&fuse_fs_type); + out2: + kmem_cache_destroy(fuse_inode_cachep); out: return err; } diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 5b5fa33b6b9d..cbd1a61c110a 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -548,7 +548,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY); if (error) - goto out_bdi; + goto out_fput; server->ncp_filp = ncp_filp; server->ncp_sock = sock; @@ -559,7 +559,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) error = -EBADF; server->info_filp = fget(data.info_fd); if (!server->info_filp) - goto out_fput; + goto out_bdi; error = -ENOTSOCK; sock_inode = server->info_filp->f_path.dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) @@ -746,9 +746,9 @@ out_nls: out_fput2: if (server->info_filp) fput(server->info_filp); -out_fput: - bdi_destroy(&server->bdi); out_bdi: + bdi_destroy(&server->bdi); +out_fput: /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: * * The previously used put_filp(ncp_filp); was bogus, since diff --git a/fs/proc/root.c b/fs/proc/root.c index 9a8a2b77b874..03102d978180 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -91,20 +91,18 @@ static struct file_system_type proc_fs_type = { void __init proc_root_init(void) { - struct vfsmount *mnt; int err; proc_init_inodecache(); err = register_filesystem(&proc_fs_type); if (err) return; - mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); - if (IS_ERR(mnt)) { + err = pid_ns_prepare_proc(&init_pid_ns); + if (err) { unregister_filesystem(&proc_fs_type); return; } - init_pid_ns.proc_mnt = mnt; proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); @@ -209,5 +207,5 @@ int pid_ns_prepare_proc(struct pid_namespace *ns) void pid_ns_release_proc(struct pid_namespace *ns) { - mntput(ns->proc_mnt); + kern_unmount(ns->proc_mnt); } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 20403dc5d437..ae0e76bb6ebf 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2264,19 +2264,12 @@ static int __init ubifs_init(void) return -EINVAL; } - err = register_filesystem(&ubifs_fs_type); - if (err) { - ubifs_err("cannot register file system, error %d", err); - return err; - } - - err = -ENOMEM; ubifs_inode_slab = kmem_cache_create("ubifs_inode_slab", sizeof(struct ubifs_inode), 0, SLAB_MEM_SPREAD | SLAB_RECLAIM_ACCOUNT, &inode_slab_ctor); if (!ubifs_inode_slab) - goto out_reg; + return -ENOMEM; register_shrinker(&ubifs_shrinker_info); @@ -2288,15 +2281,20 @@ static int __init ubifs_init(void) if (err) goto out_compr; + err = register_filesystem(&ubifs_fs_type); + if (err) { + ubifs_err("cannot register file system, error %d", err); + goto out_dbg; + } return 0; +out_dbg: + dbg_debugfs_exit(); out_compr: ubifs_compressors_exit(); out_shrinker: unregister_shrinker(&ubifs_shrinker_info); kmem_cache_destroy(ubifs_inode_slab); -out_reg: - unregister_filesystem(&ubifs_fs_type); return err; } /* late_initcall to let compressors initialize first */ diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 4e4fbb820e20..14b6cd022284 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -182,8 +182,11 @@ {0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6759, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x675B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x675D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x675F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6760, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6761, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -195,8 +198,10 @@ {0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x677B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -246,6 +251,7 @@ {0x1002, 0x68f2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68f9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x68fa, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x68fe, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CEDAR|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R520|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -488,6 +494,8 @@ {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -502,6 +510,8 @@ {0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h index d12f077a6daf..12e023c19ac1 100644 --- a/include/linux/amba/pl330.h +++ b/include/linux/amba/pl330.h @@ -12,17 +12,9 @@ #ifndef __AMBA_PL330_H_ #define __AMBA_PL330_H_ +#include <linux/dmaengine.h> #include <asm/hardware/pl330.h> -struct dma_pl330_peri { - /* - * Peri_Req i/f of the DMAC that is - * peripheral could be reached from. - */ - u8 peri_id; /* specific dma id */ - enum pl330_reqtype rqtype; -}; - struct dma_pl330_platdata { /* * Number of valid peripherals connected to DMAC. @@ -33,9 +25,12 @@ struct dma_pl330_platdata { */ u8 nr_valid_peri; /* Array of valid peripherals */ - struct dma_pl330_peri *peri; + u8 *peri_id; + /* Operational capabilities */ + dma_cap_mask_t cap_mask; /* Bytes to allocate for MC buffer */ unsigned mcbuf_sz; }; +extern bool pl330_filter(struct dma_chan *chan, void *param); #endif /* __AMBA_PL330_H_ */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c7a6d3b5bc7b..94acd8172b5b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -805,9 +805,6 @@ extern void blk_unprep_request(struct request *); */ extern struct request_queue *blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id); -extern struct request_queue *blk_init_allocated_queue_node(struct request_queue *, - request_fn_proc *, - spinlock_t *, int node_id); extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *); extern struct request_queue *blk_init_allocated_queue(struct request_queue *, request_fn_proc *, spinlock_t *); diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index ef90cbd8e173..57c9a8ae4f2d 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -31,6 +31,7 @@ extern void free_dmar_iommu(struct intel_iommu *iommu); extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); extern int dmar_disabled; +extern int intel_iommu_enabled; #else static inline int iommu_calculate_agaw(struct intel_iommu *iommu) { @@ -44,6 +45,7 @@ static inline void free_dmar_iommu(struct intel_iommu *iommu) { } #define dmar_disabled (1) +#define intel_iommu_enabled (0) #endif diff --git a/include/linux/gpio-pxa.h b/include/linux/gpio-pxa.h new file mode 100644 index 000000000000..05071ee34c3f --- /dev/null +++ b/include/linux/gpio-pxa.h @@ -0,0 +1,16 @@ +#ifndef __GPIO_PXA_H +#define __GPIO_PXA_H + +#define GPIO_bit(x) (1 << ((x) & 0x1f)) + +#define gpio_to_bank(gpio) ((gpio) >> 5) + +/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). + * Those cases currently cause holes in the GPIO number space, the + * actual number of the last GPIO is recorded by 'pxa_last_gpio'. + */ +extern int pxa_last_gpio; + +extern int pxa_irq_to_gpio(int irq); + +#endif /* __GPIO_PXA_H */ diff --git a/include/linux/log2.h b/include/linux/log2.h index 25b808631cd9..fd7ff3d91e6a 100644 --- a/include/linux/log2.h +++ b/include/linux/log2.h @@ -185,7 +185,6 @@ unsigned long __rounddown_pow_of_two(unsigned long n) #define rounddown_pow_of_two(n) \ ( \ __builtin_constant_p(n) ? ( \ - (n == 1) ? 0 : \ (1UL << ilog2(n))) : \ __rounddown_pow_of_two(n) \ ) diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 415f2db414e1..c8ef9bc54d50 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -218,6 +218,7 @@ struct mmc_card { #define MMC_QUIRK_INAND_CMD38 (1<<6) /* iNAND devices have broken CMD38 */ #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ +#define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ /* byte mode */ unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ #define MMC_NO_POWER_NOTIFICATION 0 @@ -433,6 +434,11 @@ static inline int mmc_card_broken_byte_mode_512(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_BYTE_MODE_512; } +static inline int mmc_card_long_read_time(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_LONG_READ_TIME; +} + #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) (dev_name(&(c)->dev)) diff --git a/include/linux/platform_data/macb.h b/include/linux/platform_data/macb.h new file mode 100644 index 000000000000..e7c748fb6053 --- /dev/null +++ b/include/linux/platform_data/macb.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __MACB_PDATA_H__ +#define __MACB_PDATA_H__ + +struct macb_platform_data { + u32 phy_mask; + u8 phy_irq_pin; /* PHY IRQ */ + u8 is_rmii; /* using RMII interface? */ +}; + +#endif /* __MACB_PDATA_H__ */ diff --git a/include/sound/saif.h b/include/sound/saif.h index d0e0de7984ec..f22f3e16edf4 100644 --- a/include/sound/saif.h +++ b/include/sound/saif.h @@ -10,7 +10,7 @@ #define __SOUND_SAIF_H__ struct mxs_saif_platform_data { - int (*init) (void); - int (*get_master_id) (unsigned int saif_id); + bool master_mode; /* if true use master mode */ + int master_id; /* id of the master if in slave mode */ }; #endif diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 2e0ecfcc881d..5b4293d9819d 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1269,7 +1269,7 @@ void mq_clear_sbinfo(struct ipc_namespace *ns) void mq_put_mnt(struct ipc_namespace *ns) { - mntput(ns->mq_mnt); + kern_unmount(ns->mq_mnt); } static int __init init_mqueue_fs(void) @@ -1291,11 +1291,9 @@ static int __init init_mqueue_fs(void) spin_lock_init(&mq_lock); - init_ipc_ns.mq_mnt = kern_mount_data(&mqueue_fs_type, &init_ipc_ns); - if (IS_ERR(init_ipc_ns.mq_mnt)) { - error = PTR_ERR(init_ipc_ns.mq_mnt); + error = mq_init_ns(&init_ipc_ns); + if (error) goto out_filesystem; - } return 0; diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 8b5ce5d3f3ef..5652101cdac0 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -27,11 +27,6 @@ DEFINE_SPINLOCK(mq_lock); */ struct ipc_namespace init_ipc_ns = { .count = ATOMIC_INIT(1), -#ifdef CONFIG_POSIX_MQUEUE - .mq_queues_max = DFLT_QUEUESMAX, - .mq_msg_max = DFLT_MSGMAX, - .mq_msgsize_max = DFLT_MSGSIZEMAX, -#endif .user_ns = &init_user_ns, }; diff --git a/mm/filemap.c b/mm/filemap.c index c0018f2d50e0..c106d3b3cc64 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2407,7 +2407,6 @@ static ssize_t generic_perform_write(struct file *file, iov_iter_count(i)); again: - /* * Bring in the user page that we will copy from _first_. * Otherwise there's a nasty deadlock on copying from the @@ -2463,7 +2462,10 @@ again: written += copied; balance_dirty_pages_ratelimited(mapping); - + if (fatal_signal_pending(current)) { + status = -EINTR; + break; + } } while (iov_iter_count(i)); return written ? written : status; diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 71252486bc6f..50f08241f981 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -411,8 +411,13 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty) * * Returns @bdi's dirty limit in pages. The term "dirty" in the context of * dirty balancing includes all PG_dirty, PG_writeback and NFS unstable pages. - * And the "limit" in the name is not seriously taken as hard limit in - * balance_dirty_pages(). + * + * Note that balance_dirty_pages() will only seriously take it as a hard limit + * when sleeping max_pause per page is not enough to keep the dirty pages under + * control. For example, when the device is completely stalled due to some error + * conditions, or when there are 1000 dd tasks writing to a slow 10MB/s USB key. + * In the other normal situations, it acts more gently by throttling the tasks + * more (rather than completely block them) when the bdi dirty pages go high. * * It allocates high/low dirty limits to fast/slow devices, in order to prevent * - starving fast devices @@ -594,6 +599,13 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi, */ if (unlikely(bdi_thresh > thresh)) bdi_thresh = thresh; + /* + * It's very possible that bdi_thresh is close to 0 not because the + * device is slow, but that it has remained inactive for long time. + * Honour such devices a reasonable good (hopefully IO efficient) + * threshold, so that the occasional writes won't be blocked and active + * writes can rampup the threshold quickly. + */ bdi_thresh = max(bdi_thresh, (limit - dirty) / 8); /* * scale global setpoint to bdi's: @@ -977,8 +989,7 @@ static unsigned long bdi_max_pause(struct backing_dev_info *bdi, * * 8 serves as the safety ratio. */ - if (bdi_dirty) - t = min(t, bdi_dirty * HZ / (8 * bw + 1)); + t = min(t, bdi_dirty * HZ / (8 * bw + 1)); /* * The pause time will be settled within range (max_pause/4, max_pause). @@ -1136,6 +1147,19 @@ pause: if (task_ratelimit) break; + /* + * In the case of an unresponding NFS server and the NFS dirty + * pages exceeds dirty_thresh, give the other good bdi's a pipe + * to go through, so that tasks on them still remain responsive. + * + * In theory 1 page is enough to keep the comsumer-producer + * pipe going: the flusher cleans 1 page => the task dirties 1 + * more page. However bdi_dirty has accounting errors. So use + * the larger and more IO friendly bdi_stat_error. + */ + if (bdi_dirty <= bdi_stat_error(bdi)) + break; + if (fatal_signal_pending(current)) break; } diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index c7aafc7c5ed4..5f09a578d49d 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -245,9 +245,11 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, if (tt_global_entry) { /* This node is probably going to update its tt table */ tt_global_entry->orig_node->tt_poss_change = true; - /* The global entry has to be marked as PENDING and has to be + /* The global entry has to be marked as ROAMING and has to be * kept for consistency purpose */ - tt_global_entry->flags |= TT_CLIENT_PENDING; + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + send_roam_adv(bat_priv, tt_global_entry->addr, tt_global_entry->orig_node); } @@ -694,6 +696,7 @@ void tt_global_del(struct bat_priv *bat_priv, const char *message, bool roaming) { struct tt_global_entry *tt_global_entry = NULL; + struct tt_local_entry *tt_local_entry = NULL; tt_global_entry = tt_global_hash_find(bat_priv, addr); if (!tt_global_entry) @@ -701,15 +704,29 @@ void tt_global_del(struct bat_priv *bat_priv, if (tt_global_entry->orig_node == orig_node) { if (roaming) { - tt_global_entry->flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - goto out; + /* if we are deleting a global entry due to a roam + * event, there are two possibilities: + * 1) the client roamed from node A to node B => we mark + * it with TT_CLIENT_ROAM, we start a timer and we + * wait for node B to claim it. In case of timeout + * the entry is purged. + * 2) the client roamed to us => we can directly delete + * the global entry, since it is useless now. */ + tt_local_entry = tt_local_hash_find(bat_priv, + tt_global_entry->addr); + if (!tt_local_entry) { + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + goto out; + } } _tt_global_del(bat_priv, tt_global_entry, message); } out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); + if (tt_local_entry) + tt_local_entry_free_ref(tt_local_entry); } void tt_global_del_orig(struct bat_priv *bat_priv, diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 91bcd3a961ec..1eea8208b2cc 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -79,17 +79,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst) static void __bnep_link_session(struct bnep_session *s) { - /* It's safe to call __module_get() here because sessions are added - by the socket layer which has to hold the reference to this module. - */ - __module_get(THIS_MODULE); list_add(&s->list, &bnep_session_list); } static void __bnep_unlink_session(struct bnep_session *s) { list_del(&s->list); - module_put(THIS_MODULE); } static int bnep_send(struct bnep_session *s, void *data, size_t len) @@ -530,6 +525,7 @@ static int bnep_session(void *arg) up_write(&bnep_session_sem); free_netdev(dev); + module_put_and_exit(0); return 0; } @@ -616,9 +612,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) __bnep_link_session(s); + __module_get(THIS_MODULE); s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); if (IS_ERR(s->task)) { /* Session thread start failed, gotta cleanup. */ + module_put(THIS_MODULE); unregister_netdev(dev); __bnep_unlink_session(s); err = PTR_ERR(s->task); diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 7d00ddf9e9dc..5a6e634f7fca 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -67,14 +67,12 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr) static void __cmtp_link_session(struct cmtp_session *session) { - __module_get(THIS_MODULE); list_add(&session->list, &cmtp_session_list); } static void __cmtp_unlink_session(struct cmtp_session *session) { list_del(&session->list); - module_put(THIS_MODULE); } static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) @@ -327,6 +325,7 @@ static int cmtp_session(void *arg) up_write(&cmtp_session_sem); kfree(session); + module_put_and_exit(0); return 0; } @@ -376,9 +375,11 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) __cmtp_link_session(session); + __module_get(THIS_MODULE); session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", session->num); if (IS_ERR(session->task)) { + module_put(THIS_MODULE); err = PTR_ERR(session->task); goto unlink; } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d7d96b6b1f0d..643a41b76e2e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -545,7 +545,7 @@ static void hci_setup(struct hci_dev *hdev) { hci_setup_event_mask(hdev); - if (hdev->lmp_ver > 1) + if (hdev->hci_ver > 1) hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); if (hdev->features[6] & LMP_SIMPLE_PAIR) { diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index 42599e31dcad..3a94eae7abe9 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -477,7 +477,6 @@ int crush_do_rule(struct crush_map *map, int i, j; int numrep; int firstn; - int rc = -1; BUG_ON(ruleno >= map->max_rules); @@ -491,23 +490,18 @@ int crush_do_rule(struct crush_map *map, * that this may or may not correspond to the specific types * referenced by the crush rule. */ - if (force >= 0) { - if (force >= map->max_devices || - map->device_parents[force] == 0) { - /*dprintk("CRUSH: forcefed device dne\n");*/ - rc = -1; /* force fed device dne */ - goto out; - } - if (!is_out(map, weight, force, x)) { - while (1) { - force_context[++force_pos] = force; - if (force >= 0) - force = map->device_parents[force]; - else - force = map->bucket_parents[-1-force]; - if (force == 0) - break; - } + if (force >= 0 && + force < map->max_devices && + map->device_parents[force] != 0 && + !is_out(map, weight, force, x)) { + while (1) { + force_context[++force_pos] = force; + if (force >= 0) + force = map->device_parents[force]; + else + force = map->bucket_parents[-1-force]; + if (force == 0) + break; } } @@ -600,10 +594,7 @@ int crush_do_rule(struct crush_map *map, BUG_ON(1); } } - rc = result_len; - -out: - return rc; + return result_len; } diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 065effd8349a..0b2e7329abda 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -285,6 +285,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; + strcpy(nt->parms.name, dev->name); + dev_hold(dev); ipip_tunnel_link(ipn, nt); return nt; @@ -759,7 +761,6 @@ static int ipip_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; - strcpy(tunnel->parms.name, dev->name); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -825,6 +826,7 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head) static int __net_init ipip_init_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); + struct ip_tunnel *t; int err; ipn->tunnels[0] = ipn->tunnels_wc; @@ -848,6 +850,9 @@ static int __net_init ipip_init_net(struct net *net) if ((err = register_netdev(ipn->fb_tunnel_dev))) goto err_reg_dev; + t = netdev_priv(ipn->fb_tunnel_dev); + + strcpy(t->parms.name, ipn->fb_tunnel_dev->name); return 0; err_reg_dev: diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index cf88df82e2c2..36806def8cfd 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1805,7 +1805,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) return ERR_PTR(-EACCES); /* Add default multicast route */ - addrconf_add_mroute(dev); + if (!(dev->flags & IFF_LOOPBACK)) + addrconf_add_mroute(dev); /* Add link local route */ addrconf_add_lroute(dev); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3399dd326287..b582a0a0f1c5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -728,7 +728,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, int attempts = !in_softirq(); if (!(rt->rt6i_flags&RTF_GATEWAY)) { - if (rt->rt6i_dst.plen != 128 && + if (ort->rt6i_dst.plen != 128 && ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) rt->rt6i_flags |= RTF_ANYCAST; ipv6_addr_copy(&rt->rt6i_gateway, daddr); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index a7a18602a046..96f3623618e3 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -263,6 +263,8 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; + strcpy(nt->parms.name, dev->name); + dev_hold(dev); ipip6_tunnel_link(sitn, nt); @@ -1144,7 +1146,6 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; - strcpy(tunnel->parms.name, dev->name); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -1207,6 +1208,7 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea static int __net_init sit_init_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); + struct ip_tunnel *t; int err; sitn->tunnels[0] = sitn->tunnels_wc; @@ -1231,6 +1233,9 @@ static int __net_init sit_init_net(struct net *net) if ((err = register_netdev(sitn->fb_tunnel_dev))) goto err_reg_dev; + t = netdev_priv(sitn->fb_tunnel_dev); + + strcpy(t->parms.name, sitn->fb_tunnel_dev->name); return 0; err_reg_dev: diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index b064e4df12c6..2e4b961648d4 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -303,6 +303,38 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) __release(agg_queue); } +/* + * splice packets from the STA's pending to the local pending, + * requires a call to ieee80211_agg_splice_finish later + */ +static void __acquires(agg_queue) +ieee80211_agg_splice_packets(struct ieee80211_local *local, + struct tid_ampdu_tx *tid_tx, u16 tid) +{ + int queue = ieee80211_ac_from_tid(tid); + unsigned long flags; + + ieee80211_stop_queue_agg(local, tid); + + if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" + " from the pending queue\n", tid)) + return; + + if (!skb_queue_empty(&tid_tx->pending)) { + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + /* copy over remaining packets */ + skb_queue_splice_tail_init(&tid_tx->pending, + &local->pending[queue]); + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + } +} + +static void __releases(agg_queue) +ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) +{ + ieee80211_wake_queue_agg(local, tid); +} + void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) { struct tid_ampdu_tx *tid_tx; @@ -314,19 +346,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* - * While we're asking the driver about the aggregation, - * stop the AC queue so that we don't have to worry - * about frames that came in while we were doing that, - * which would require us to put them to the AC pending - * afterwards which just makes the code more complex. + * Start queuing up packets for this aggregation session. + * We're going to release them once the driver is OK with + * that. */ - ieee80211_stop_queue_agg(local, tid); - clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); /* - * make sure no packets are being processed to get - * valid starting sequence number + * Make sure no packets are being processed. This ensures that + * we have a valid starting sequence number and that in-flight + * packets have been flushed out and no packets for this TID + * will go into the driver during the ampdu_action call. */ synchronize_net(); @@ -340,17 +370,15 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) " tid %d\n", tid); #endif spin_lock_bh(&sta->lock); + ieee80211_agg_splice_packets(local, tid_tx, tid); ieee80211_assign_tid_tx(sta, tid, NULL); + ieee80211_agg_splice_finish(local, tid); spin_unlock_bh(&sta->lock); - ieee80211_wake_queue_agg(local, tid); kfree_rcu(tid_tx, rcu_head); return; } - /* we can take packets again now */ - ieee80211_wake_queue_agg(local, tid); - /* activate the timer for the recipient's addBA response */ mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -466,38 +494,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, } EXPORT_SYMBOL(ieee80211_start_tx_ba_session); -/* - * splice packets from the STA's pending to the local pending, - * requires a call to ieee80211_agg_splice_finish later - */ -static void __acquires(agg_queue) -ieee80211_agg_splice_packets(struct ieee80211_local *local, - struct tid_ampdu_tx *tid_tx, u16 tid) -{ - int queue = ieee80211_ac_from_tid(tid); - unsigned long flags; - - ieee80211_stop_queue_agg(local, tid); - - if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" - " from the pending queue\n", tid)) - return; - - if (!skb_queue_empty(&tid_tx->pending)) { - spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - /* copy over remaining packets */ - skb_queue_splice_tail_init(&tid_tx->pending, - &local->pending[queue]); - spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - } -} - -static void __releases(agg_queue) -ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) -{ - ieee80211_wake_queue_agg(local, tid); -} - static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index b9493a09a870..6cd8ddfb512d 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -385,7 +385,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, struct gred_sched_data *q; if (table->tab[dp] == NULL) { - table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL); + table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC); if (table->tab[dp] == NULL) return -ENOMEM; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7d98240def0b..c2f79e63124d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2507,6 +2507,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS 1101HA", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), @@ -2970,7 +2971,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ + /* ICH */ { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_BUFSIZE }, /* ICH6 */ diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index eeb25d529e30..616678fde486 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4929,6 +4929,12 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) set_hp_led_gpio(codec); return 1; } + /* BIOS bug: unfilled OEM string */ + if (strstr(dev->name, "HP_Mute_LED_P_G")) { + set_hp_led_gpio(codec); + spec->gpio_led_polarity = 1; + return 1; + } } /* diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4584514d93d4..fa787d45d74a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -33,7 +33,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_CX20442 select SND_SOC_DA7210 if I2C select SND_SOC_DFBMCS320 - select SND_SOC_JZ4740_CODEC if SOC_JZ4740 + select SND_SOC_JZ4740_CODEC select SND_SOC_LM4857 if I2C select SND_SOC_MAX98088 if I2C select SND_SOC_MAX98095 if I2C diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index e373f8f06907..3e1f4e172bfb 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/io.h> #include <linux/delay.h> diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 0293763debe5..5a14d5c0e0e1 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -60,6 +60,8 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name, } if (memcmp(fw->data, "WMFW", 4) != 0) { + memcpy(&data32, fw->data, sizeof(data32)); + data32 = be32_to_cpu(data32); dev_err(codec->dev, "%s: firmware has bad file magic %08x\n", name, data32); goto err; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 645c980d6b80..a33b04d17195 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -1968,6 +1968,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, break; case 24576000: ratediv = WM8996_SYSCLK_DIV; + wm8996->sysclk /= 2; case 12288000: snd_soc_update_bits(codec, WM8996_AIF_RATE, WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE); diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index dea5aa4aa647..f39d7dd9fbcb 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -357,3 +357,6 @@ static void __exit snd_mxs_pcm_exit(void) platform_driver_unregister(&mxs_pcm_driver); } module_exit(snd_mxs_pcm_exit); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mxs-pcm-audio"); diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 76dc74d24fc2..1ef697fe1731 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -625,13 +625,6 @@ static int mxs_saif_probe(struct platform_device *pdev) if (pdev->id >= ARRAY_SIZE(mxs_saif)) return -EINVAL; - pdata = pdev->dev.platform_data; - if (pdata && pdata->init) { - ret = pdata->init(); - if (ret) - return ret; - } - saif = kzalloc(sizeof(*saif), GFP_KERNEL); if (!saif) return -ENOMEM; @@ -639,12 +632,17 @@ static int mxs_saif_probe(struct platform_device *pdev) mxs_saif[pdev->id] = saif; saif->id = pdev->id; - saif->master_id = saif->id; - if (pdata && pdata->get_master_id) { - saif->master_id = pdata->get_master_id(saif->id); + pdata = pdev->dev.platform_data; + if (pdata && !pdata->master_mode) { + saif->master_id = pdata->master_id; if (saif->master_id < 0 || - saif->master_id >= ARRAY_SIZE(mxs_saif)) + saif->master_id >= ARRAY_SIZE(mxs_saif) || + saif->master_id == saif->id) { + dev_err(&pdev->dev, "get wrong master id\n"); return -EINVAL; + } + } else { + saif->master_id = saif->id; } saif->clk = clk_get(&pdev->dev, NULL); diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c index 7fbeaec06eb4..1c57f6630a48 100644 --- a/sound/soc/mxs/mxs-sgtl5000.c +++ b/sound/soc/mxs/mxs-sgtl5000.c @@ -171,3 +171,4 @@ module_exit(mxs_sgtl5000_exit); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("MXS ALSA SoC Machine driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mxs-sgtl5000"); diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c index 65c124831a00..c664e33fb6d7 100644 --- a/sound/soc/pxa/hx4700.c +++ b/sound/soc/pxa/hx4700.c @@ -209,9 +209,10 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev) snd_soc_card_hx4700.dev = &pdev->dev; ret = snd_soc_register_card(&snd_soc_card_hx4700); if (ret) - return ret; + gpio_free_array(hx4700_audio_gpios, + ARRAY_SIZE(hx4700_audio_gpios)); - return 0; + return ret; } static int __devexit hx4700_audio_remove(struct platform_device *pdev) diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 1826acf20f7c..8e523fd9189e 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c @@ -101,7 +101,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_codec *codec = rtd->codec; struct snd_soc_dapm_context *dapm = &codec->dapm; - int err; /* These endpoints are not being used. */ snd_soc_dapm_nc_pin(dapm, "LINPUT2"); @@ -131,7 +130,7 @@ static struct snd_soc_card snd_soc_machine_jive = { .dai_link = &jive_dai, .num_links = 1, - .dapm_widgtets = wm8750_dapm_widgets, + .dapm_widgets = wm8750_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets), .dapm_routes = audio_map, .num_dapm_routes = ARRAY_SIZE(audio_map), diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c index 3a0dbfc793f0..8bd1dc5706bf 100644 --- a/sound/soc/samsung/smdk2443_wm9710.c +++ b/sound/soc/samsung/smdk2443_wm9710.c @@ -12,6 +12,7 @@ * */ +#include <linux/module.h> #include <sound/soc.h> static struct snd_soc_card smdk2443; |